@nolag/feed 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react-native.d.ts +13 -0
- package/dist/react-native.js +1100 -0
- package/dist/react-native.js.map +1 -0
- package/package.json +10 -4
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nolag/feed
|
|
3
|
+
* React Native entry point.
|
|
4
|
+
*
|
|
5
|
+
* Identical to the browser entry: this SDK is transport-agnostic and attaches
|
|
6
|
+
* to an injected NoLag client, so it has no platform-specific code of its own.
|
|
7
|
+
* The entry exists purely so Metro has a `react-native` condition to resolve.
|
|
8
|
+
* Metro matches "react-native" then "import"/"require" and does not understand
|
|
9
|
+
* the "browser" condition, so without this it resolves the Node build of this
|
|
10
|
+
* package and, through it, the Node build of @nolag/js-sdk (which imports
|
|
11
|
+
* `ws` and fails to bundle).
|
|
12
|
+
*/
|
|
13
|
+
export * from "./browser";
|
|
@@ -0,0 +1,1100 @@
|
|
|
1
|
+
class EventEmitter {
|
|
2
|
+
constructor() {
|
|
3
|
+
this._handlers = new Map();
|
|
4
|
+
}
|
|
5
|
+
on(event, handler) {
|
|
6
|
+
if (!this._handlers.has(event)) {
|
|
7
|
+
this._handlers.set(event, new Set());
|
|
8
|
+
}
|
|
9
|
+
this._handlers.get(event).add(handler);
|
|
10
|
+
return this;
|
|
11
|
+
}
|
|
12
|
+
off(event, handler) {
|
|
13
|
+
if (handler) {
|
|
14
|
+
this._handlers.get(event)?.delete(handler);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
this._handlers.delete(event);
|
|
18
|
+
}
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
removeAllListeners() {
|
|
22
|
+
this._handlers.clear();
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
emit(event, ...args) {
|
|
26
|
+
const handlers = this._handlers.get(event);
|
|
27
|
+
if (!handlers)
|
|
28
|
+
return;
|
|
29
|
+
for (const handler of handlers) {
|
|
30
|
+
try {
|
|
31
|
+
handler(...args);
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
console.error(`Error in ${String(event)} handler:`, e);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
listenerCount(event) {
|
|
39
|
+
return this._handlers.get(event)?.size ?? 0;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Bounded, deduplicated post cache ordered by timestamp.
|
|
45
|
+
*/
|
|
46
|
+
class PostStore {
|
|
47
|
+
constructor(maxSize) {
|
|
48
|
+
this._posts = [];
|
|
49
|
+
this._ids = new Set();
|
|
50
|
+
this._maxSize = maxSize;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Add a post. Returns true if the post was new (not a duplicate).
|
|
54
|
+
*/
|
|
55
|
+
add(post) {
|
|
56
|
+
if (this._ids.has(post.id)) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
this._ids.add(post.id);
|
|
60
|
+
this._posts.push(post);
|
|
61
|
+
// Keep sorted by timestamp (newest last)
|
|
62
|
+
if (this._posts.length > 1 &&
|
|
63
|
+
post.timestamp < this._posts[this._posts.length - 2].timestamp) {
|
|
64
|
+
this._posts.sort((a, b) => a.timestamp - b.timestamp);
|
|
65
|
+
}
|
|
66
|
+
// Trim if over capacity (remove oldest)
|
|
67
|
+
while (this._posts.length > this._maxSize) {
|
|
68
|
+
const removed = this._posts.shift();
|
|
69
|
+
this._ids.delete(removed.id);
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get a post by ID.
|
|
75
|
+
*/
|
|
76
|
+
get(id) {
|
|
77
|
+
return this._posts.find((p) => p.id === id);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get all posts in timestamp order (oldest first).
|
|
81
|
+
*/
|
|
82
|
+
getAll() {
|
|
83
|
+
return [...this._posts];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Update the like count (and likedByMe flag) for a post in-place.
|
|
87
|
+
*/
|
|
88
|
+
updateLikeCount(postId, count, likedByMe) {
|
|
89
|
+
const post = this._posts.find((p) => p.id === postId);
|
|
90
|
+
if (post) {
|
|
91
|
+
post.likeCount = count;
|
|
92
|
+
post.likedByMe = likedByMe;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Increment the comment count for a post in-place.
|
|
97
|
+
*/
|
|
98
|
+
incrementCommentCount(postId) {
|
|
99
|
+
const post = this._posts.find((p) => p.id === postId);
|
|
100
|
+
if (post) {
|
|
101
|
+
post.commentCount++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Check if a post ID exists.
|
|
106
|
+
*/
|
|
107
|
+
has(id) {
|
|
108
|
+
return this._ids.has(id);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get post count.
|
|
112
|
+
*/
|
|
113
|
+
get size() {
|
|
114
|
+
return this._posts.length;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Clear all posts.
|
|
118
|
+
*/
|
|
119
|
+
clear() {
|
|
120
|
+
this._posts = [];
|
|
121
|
+
this._ids.clear();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Tracks like/unlike state per post with per-user deduplication.
|
|
127
|
+
*
|
|
128
|
+
* Internal: Map<postId, Set<userId>>
|
|
129
|
+
*/
|
|
130
|
+
class ReactionManager {
|
|
131
|
+
constructor() {
|
|
132
|
+
this._likes = new Map();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Record a like from userId on postId.
|
|
136
|
+
* Returns the updated likeCount and whether this was a new like.
|
|
137
|
+
*/
|
|
138
|
+
like(postId, userId) {
|
|
139
|
+
if (!this._likes.has(postId)) {
|
|
140
|
+
this._likes.set(postId, new Set());
|
|
141
|
+
}
|
|
142
|
+
const likers = this._likes.get(postId);
|
|
143
|
+
const isNew = !likers.has(userId);
|
|
144
|
+
likers.add(userId);
|
|
145
|
+
return { postId, likeCount: likers.size, isNew };
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Record an unlike from userId on postId.
|
|
149
|
+
* Returns the updated likeCount and whether the like was removed.
|
|
150
|
+
*/
|
|
151
|
+
unlike(postId, userId) {
|
|
152
|
+
const likers = this._likes.get(postId);
|
|
153
|
+
if (!likers) {
|
|
154
|
+
return { postId, likeCount: 0, wasLiked: false };
|
|
155
|
+
}
|
|
156
|
+
const wasLiked = likers.has(userId);
|
|
157
|
+
likers.delete(userId);
|
|
158
|
+
return { postId, likeCount: likers.size, wasLiked };
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check if a userId has liked a postId.
|
|
162
|
+
*/
|
|
163
|
+
isLikedBy(postId, userId) {
|
|
164
|
+
return this._likes.get(postId)?.has(userId) ?? false;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get the total like count for a post.
|
|
168
|
+
*/
|
|
169
|
+
getLikeCount(postId) {
|
|
170
|
+
return this._likes.get(postId)?.size ?? 0;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Clear all reaction state.
|
|
174
|
+
*/
|
|
175
|
+
clear() {
|
|
176
|
+
this._likes.clear();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Maps actorTokenId <-> FeedUser, filtering self.
|
|
182
|
+
*/
|
|
183
|
+
class PresenceManager {
|
|
184
|
+
constructor(localActorId) {
|
|
185
|
+
this._users = new Map();
|
|
186
|
+
this._actorToUserId = new Map();
|
|
187
|
+
this._localActorId = localActorId;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Add or update a user from presence data.
|
|
191
|
+
* Returns the FeedUser if it is a remote user, null if it is self.
|
|
192
|
+
*/
|
|
193
|
+
addFromPresence(actorTokenId, presence, joinedAt) {
|
|
194
|
+
const isLocal = actorTokenId === this._localActorId;
|
|
195
|
+
// Skip self
|
|
196
|
+
if (isLocal)
|
|
197
|
+
return null;
|
|
198
|
+
const existing = this._actorToUserId.get(actorTokenId);
|
|
199
|
+
const userId = presence.userId || existing || actorTokenId;
|
|
200
|
+
const user = {
|
|
201
|
+
userId,
|
|
202
|
+
actorTokenId,
|
|
203
|
+
username: presence.username,
|
|
204
|
+
avatar: presence.avatar,
|
|
205
|
+
metadata: presence.metadata,
|
|
206
|
+
joinedAt: joinedAt || Date.now(),
|
|
207
|
+
isLocal: false,
|
|
208
|
+
};
|
|
209
|
+
this._users.set(userId, user);
|
|
210
|
+
this._actorToUserId.set(actorTokenId, userId);
|
|
211
|
+
return user;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Remove a user by actorTokenId.
|
|
215
|
+
* Returns the removed user, or null if not found / is self.
|
|
216
|
+
*/
|
|
217
|
+
removeByActorId(actorTokenId) {
|
|
218
|
+
if (actorTokenId === this._localActorId)
|
|
219
|
+
return null;
|
|
220
|
+
const userId = this._actorToUserId.get(actorTokenId);
|
|
221
|
+
if (!userId)
|
|
222
|
+
return null;
|
|
223
|
+
const user = this._users.get(userId) || null;
|
|
224
|
+
this._users.delete(userId);
|
|
225
|
+
this._actorToUserId.delete(actorTokenId);
|
|
226
|
+
return user;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Get a user by userId.
|
|
230
|
+
*/
|
|
231
|
+
getUser(userId) {
|
|
232
|
+
return this._users.get(userId);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get a user by actorTokenId.
|
|
236
|
+
*/
|
|
237
|
+
getUserByActorId(actorTokenId) {
|
|
238
|
+
const userId = this._actorToUserId.get(actorTokenId);
|
|
239
|
+
return userId ? this._users.get(userId) : undefined;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Get all remote users.
|
|
243
|
+
*/
|
|
244
|
+
getAll() {
|
|
245
|
+
return Array.from(this._users.values());
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Get the users Map (readonly view).
|
|
249
|
+
*/
|
|
250
|
+
get users() {
|
|
251
|
+
return this._users;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Clear all tracked users.
|
|
255
|
+
*/
|
|
256
|
+
clear() {
|
|
257
|
+
this._users.clear();
|
|
258
|
+
this._actorToUserId.clear();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function generateId() {
|
|
263
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
264
|
+
return crypto.randomUUID();
|
|
265
|
+
}
|
|
266
|
+
return 'xxxx-xxxx-xxxx-xxxx'.replace(/x/g, () => Math.floor(Math.random() * 16).toString(16));
|
|
267
|
+
}
|
|
268
|
+
function createLogger(prefix, enabled) {
|
|
269
|
+
if (!enabled) {
|
|
270
|
+
return (..._args) => { };
|
|
271
|
+
}
|
|
272
|
+
return (...args) => { console.log(`[${prefix}]`, ...args); };
|
|
273
|
+
}
|
|
274
|
+
// ============ Wrapper registry ============
|
|
275
|
+
// One wrapper instance per (client, appName): two wrappers sharing an app on
|
|
276
|
+
// one connection would collide on topics, presence and the online lobby.
|
|
277
|
+
// Warn (not throw): HMR and tests legitimately construct before disposing.
|
|
278
|
+
const wrapperRegistry = new WeakMap();
|
|
279
|
+
/** Register a wrapper against a client + appName; warns on collision. */
|
|
280
|
+
function registerWrapper(client, appName, wrapperName) {
|
|
281
|
+
let apps = wrapperRegistry.get(client);
|
|
282
|
+
if (!apps) {
|
|
283
|
+
apps = new Map();
|
|
284
|
+
wrapperRegistry.set(client, apps);
|
|
285
|
+
}
|
|
286
|
+
const existing = apps.get(appName);
|
|
287
|
+
if (existing) {
|
|
288
|
+
console.warn(`[${wrapperName}] Another wrapper (${existing}) is already attached to this client for app "${appName}". ` +
|
|
289
|
+
`Use one wrapper per (client, app) — detach the other instance first.`);
|
|
290
|
+
}
|
|
291
|
+
apps.set(appName, wrapperName);
|
|
292
|
+
}
|
|
293
|
+
/** Release a wrapper's (client, appName) registration on detach. */
|
|
294
|
+
function releaseWrapper(client, appName) {
|
|
295
|
+
wrapperRegistry.get(client)?.delete(appName);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const DEFAULT_APP_NAME = 'feed';
|
|
299
|
+
const DEFAULT_MAX_POST_CACHE = 200;
|
|
300
|
+
const DEFAULT_MAX_COMMENT_CACHE = 100;
|
|
301
|
+
const TOPIC_POSTS = 'posts';
|
|
302
|
+
const TOPIC_REACTIONS = 'reactions';
|
|
303
|
+
const TOPIC_COMMENTS = 'comments';
|
|
304
|
+
const LOBBY_ID = 'online';
|
|
305
|
+
/** Delay before the post-setup lobby presence refetch (catches simultaneous joiners) */
|
|
306
|
+
const LOBBY_REFRESH_DELAY_MS = 2000;
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* FeedChannel — a single feed channel with posts, comments, reactions, and
|
|
310
|
+
* presence.
|
|
311
|
+
*
|
|
312
|
+
* Created via `NoLagFeed.joinChannel(name)`. Do not instantiate directly.
|
|
313
|
+
*/
|
|
314
|
+
class FeedChannel extends EventEmitter {
|
|
315
|
+
/** @internal */
|
|
316
|
+
constructor(name, roomContext, localUser, options, log, isConnected) {
|
|
317
|
+
super();
|
|
318
|
+
this._comments = new Map();
|
|
319
|
+
this._unreadCount = 0;
|
|
320
|
+
this._active = false;
|
|
321
|
+
// Stored topic handler refs — cleanup removes exactly these, never all
|
|
322
|
+
// handlers for a topic (the client may be shared with other consumers).
|
|
323
|
+
this._onPostsRef = null;
|
|
324
|
+
this._onReactionsRef = null;
|
|
325
|
+
this._onCommentsRef = null;
|
|
326
|
+
this.name = name;
|
|
327
|
+
this._roomContext = roomContext;
|
|
328
|
+
this._localUser = localUser;
|
|
329
|
+
this._options = options;
|
|
330
|
+
this._log = log;
|
|
331
|
+
this._isConnected = isConnected;
|
|
332
|
+
this._presenceManager = new PresenceManager(localUser.actorTokenId);
|
|
333
|
+
this._postStore = new PostStore(options.maxPostCache);
|
|
334
|
+
this._reactionManager = new ReactionManager();
|
|
335
|
+
}
|
|
336
|
+
get posts() { return this._postStore.getAll(); }
|
|
337
|
+
get unreadCount() { return this._unreadCount; }
|
|
338
|
+
get active() { return this._active; }
|
|
339
|
+
createPost(opts) {
|
|
340
|
+
const post = {
|
|
341
|
+
id: generateId(), userId: this._localUser.userId, username: this._localUser.username,
|
|
342
|
+
avatar: this._localUser.avatar, content: opts.content, media: opts.media, data: opts.data,
|
|
343
|
+
likeCount: 0, commentCount: 0, likedByMe: false, timestamp: Date.now(), status: 'sending', isReplay: false,
|
|
344
|
+
};
|
|
345
|
+
this._postStore.add(post);
|
|
346
|
+
this.emit('postSent', post);
|
|
347
|
+
this._roomContext.emit(TOPIC_POSTS, {
|
|
348
|
+
id: post.id, userId: post.userId, username: post.username, avatar: post.avatar,
|
|
349
|
+
content: post.content, media: post.media, data: post.data, timestamp: post.timestamp,
|
|
350
|
+
}, { echo: false });
|
|
351
|
+
post.status = 'sent';
|
|
352
|
+
return post;
|
|
353
|
+
}
|
|
354
|
+
getPosts() { return this._postStore.getAll(); }
|
|
355
|
+
likePost(postId) {
|
|
356
|
+
const { likeCount, isNew } = this._reactionManager.like(postId, this._localUser.userId);
|
|
357
|
+
if (isNew) {
|
|
358
|
+
this._postStore.updateLikeCount(postId, likeCount, true);
|
|
359
|
+
this._roomContext.emit(TOPIC_REACTIONS, { postId, userId: this._localUser.userId, type: 'like', timestamp: Date.now() }, { echo: false });
|
|
360
|
+
this.emit('postLiked', { postId, userId: this._localUser.userId, likeCount });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
unlikePost(postId) {
|
|
364
|
+
const { likeCount, wasLiked } = this._reactionManager.unlike(postId, this._localUser.userId);
|
|
365
|
+
if (wasLiked) {
|
|
366
|
+
this._postStore.updateLikeCount(postId, likeCount, false);
|
|
367
|
+
this._roomContext.emit(TOPIC_REACTIONS, { postId, userId: this._localUser.userId, type: 'unlike', timestamp: Date.now() }, { echo: false });
|
|
368
|
+
this.emit('postUnliked', { postId, userId: this._localUser.userId, likeCount });
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
addComment(postId, text) {
|
|
372
|
+
const comment = {
|
|
373
|
+
id: generateId(), postId, userId: this._localUser.userId, username: this._localUser.username,
|
|
374
|
+
avatar: this._localUser.avatar, text, timestamp: Date.now(), isReplay: false,
|
|
375
|
+
};
|
|
376
|
+
if (!this._comments.has(postId))
|
|
377
|
+
this._comments.set(postId, []);
|
|
378
|
+
this._comments.get(postId).push(comment);
|
|
379
|
+
this._postStore.incrementCommentCount(postId);
|
|
380
|
+
this.emit('commentSent', comment);
|
|
381
|
+
this._roomContext.emit(TOPIC_COMMENTS, {
|
|
382
|
+
id: comment.id, postId, userId: comment.userId, username: comment.username,
|
|
383
|
+
avatar: comment.avatar, text: comment.text, timestamp: comment.timestamp,
|
|
384
|
+
}, { echo: false });
|
|
385
|
+
return comment;
|
|
386
|
+
}
|
|
387
|
+
getComments(postId) {
|
|
388
|
+
return this._comments.get(postId) ?? [];
|
|
389
|
+
}
|
|
390
|
+
markRead() {
|
|
391
|
+
if (this._unreadCount !== 0) {
|
|
392
|
+
this._unreadCount = 0;
|
|
393
|
+
this.emit('unreadChanged', { channel: this.name, count: 0 });
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
getUsers() { return this._presenceManager.getAll(); }
|
|
397
|
+
/** @internal Subscribe to post/reaction/comment topics and attach listeners (all channels) */
|
|
398
|
+
_subscribe() {
|
|
399
|
+
this._log('Channel subscribe:', this.name);
|
|
400
|
+
this._roomContext.subscribe(TOPIC_POSTS);
|
|
401
|
+
this._roomContext.subscribe(TOPIC_REACTIONS);
|
|
402
|
+
this._roomContext.subscribe(TOPIC_COMMENTS);
|
|
403
|
+
// Listen for posts (refs stored for handler-specific removal)
|
|
404
|
+
this._onPostsRef = (data, meta) => {
|
|
405
|
+
this._handleIncomingPost(data, meta);
|
|
406
|
+
};
|
|
407
|
+
this._roomContext.on(TOPIC_POSTS, this._onPostsRef);
|
|
408
|
+
// Listen for reactions
|
|
409
|
+
this._onReactionsRef = (data) => {
|
|
410
|
+
this._handleIncomingReaction(data);
|
|
411
|
+
};
|
|
412
|
+
this._roomContext.on(TOPIC_REACTIONS, this._onReactionsRef);
|
|
413
|
+
// Listen for comments
|
|
414
|
+
this._onCommentsRef = (data, meta) => {
|
|
415
|
+
this._handleIncomingComment(data, meta);
|
|
416
|
+
};
|
|
417
|
+
this._roomContext.on(TOPIC_COMMENTS, this._onCommentsRef);
|
|
418
|
+
}
|
|
419
|
+
_activate() {
|
|
420
|
+
this._active = true;
|
|
421
|
+
this._markRead();
|
|
422
|
+
this._setPresence();
|
|
423
|
+
this._roomContext.fetchPresence().then((actors) => {
|
|
424
|
+
for (const actor of actors) {
|
|
425
|
+
if (actor.presence) {
|
|
426
|
+
const user = this._presenceManager.addFromPresence(actor.actorTokenId, actor.presence, actor.joinedAt);
|
|
427
|
+
if (user)
|
|
428
|
+
this.emit('subscriberJoined', user);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}).catch(() => { });
|
|
432
|
+
}
|
|
433
|
+
_deactivate() { this._active = false; this._presenceManager.clear(); }
|
|
434
|
+
_handlePresenceJoin(actorTokenId, presenceData) {
|
|
435
|
+
const user = this._presenceManager.addFromPresence(actorTokenId, presenceData);
|
|
436
|
+
if (user)
|
|
437
|
+
this.emit('subscriberJoined', user);
|
|
438
|
+
}
|
|
439
|
+
_handlePresenceLeave(actorTokenId) {
|
|
440
|
+
const user = this._presenceManager.removeByActorId(actorTokenId);
|
|
441
|
+
if (user)
|
|
442
|
+
this.emit('subscriberLeft', user);
|
|
443
|
+
}
|
|
444
|
+
_handlePresenceUpdate(actorTokenId, presenceData) {
|
|
445
|
+
this._presenceManager.addFromPresence(actorTokenId, presenceData);
|
|
446
|
+
}
|
|
447
|
+
_handleReplayStart(count) { this.emit('replayStart', { count }); }
|
|
448
|
+
_handleReplayEnd(replayed) { this.emit('replayEnd', { replayed }); }
|
|
449
|
+
_updateLocalPresence() { this._setPresence(); }
|
|
450
|
+
/** @internal Unsubscribe and clean up */
|
|
451
|
+
_cleanup() {
|
|
452
|
+
this._log('Channel cleanup:', this.name);
|
|
453
|
+
// Server unsubscribes need a live socket; skip when disconnected
|
|
454
|
+
// (best-effort — the core would no-op with an error callback anyway).
|
|
455
|
+
if (this._isConnected()) {
|
|
456
|
+
this._roomContext.unsubscribe(TOPIC_POSTS);
|
|
457
|
+
this._roomContext.unsubscribe(TOPIC_REACTIONS);
|
|
458
|
+
this._roomContext.unsubscribe(TOPIC_COMMENTS);
|
|
459
|
+
}
|
|
460
|
+
// Handler-specific removal only: the client may be shared, and a bare
|
|
461
|
+
// off(topic) would strip other consumers' handlers too.
|
|
462
|
+
if (this._onPostsRef)
|
|
463
|
+
this._roomContext.off(TOPIC_POSTS, this._onPostsRef);
|
|
464
|
+
if (this._onReactionsRef)
|
|
465
|
+
this._roomContext.off(TOPIC_REACTIONS, this._onReactionsRef);
|
|
466
|
+
if (this._onCommentsRef)
|
|
467
|
+
this._roomContext.off(TOPIC_COMMENTS, this._onCommentsRef);
|
|
468
|
+
this._onPostsRef = null;
|
|
469
|
+
this._onReactionsRef = null;
|
|
470
|
+
this._onCommentsRef = null;
|
|
471
|
+
this._postStore.clear();
|
|
472
|
+
this._reactionManager.clear();
|
|
473
|
+
this._comments.clear();
|
|
474
|
+
this._presenceManager.clear();
|
|
475
|
+
this.removeAllListeners();
|
|
476
|
+
}
|
|
477
|
+
_handleIncomingPost(data, meta) {
|
|
478
|
+
const raw = data;
|
|
479
|
+
const post = {
|
|
480
|
+
id: raw.id, userId: raw.userId, username: raw.username,
|
|
481
|
+
avatar: raw.avatar, content: raw.content,
|
|
482
|
+
media: raw.media, data: raw.data,
|
|
483
|
+
likeCount: 0, commentCount: 0, likedByMe: false,
|
|
484
|
+
timestamp: raw.timestamp, status: 'delivered', isReplay: meta.isReplay ?? false,
|
|
485
|
+
};
|
|
486
|
+
if (this._postStore.add(post)) {
|
|
487
|
+
this.emit('postCreated', post);
|
|
488
|
+
if (!this._active && !post.isReplay) {
|
|
489
|
+
this._unreadCount++;
|
|
490
|
+
this.emit('unreadChanged', { channel: this.name, count: this._unreadCount });
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
_handleIncomingReaction(data) {
|
|
495
|
+
const raw = data;
|
|
496
|
+
if (raw.type === 'like') {
|
|
497
|
+
const { likeCount } = this._reactionManager.like(raw.postId, raw.userId);
|
|
498
|
+
const likedByMe = this._reactionManager.isLikedBy(raw.postId, this._localUser.userId);
|
|
499
|
+
this._postStore.updateLikeCount(raw.postId, likeCount, likedByMe);
|
|
500
|
+
this.emit('postLiked', { postId: raw.postId, userId: raw.userId, likeCount });
|
|
501
|
+
}
|
|
502
|
+
else if (raw.type === 'unlike') {
|
|
503
|
+
const { likeCount } = this._reactionManager.unlike(raw.postId, raw.userId);
|
|
504
|
+
const likedByMe = this._reactionManager.isLikedBy(raw.postId, this._localUser.userId);
|
|
505
|
+
this._postStore.updateLikeCount(raw.postId, likeCount, likedByMe);
|
|
506
|
+
this.emit('postUnliked', { postId: raw.postId, userId: raw.userId, likeCount });
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
_handleIncomingComment(data, meta) {
|
|
510
|
+
const raw = data;
|
|
511
|
+
const comment = {
|
|
512
|
+
id: raw.id, postId: raw.postId, userId: raw.userId,
|
|
513
|
+
username: raw.username, avatar: raw.avatar,
|
|
514
|
+
text: raw.text, timestamp: raw.timestamp, isReplay: meta.isReplay ?? false,
|
|
515
|
+
};
|
|
516
|
+
if (!this._comments.has(comment.postId))
|
|
517
|
+
this._comments.set(comment.postId, []);
|
|
518
|
+
this._comments.get(comment.postId).push(comment);
|
|
519
|
+
this._postStore.incrementCommentCount(comment.postId);
|
|
520
|
+
this.emit('commentAdded', comment);
|
|
521
|
+
}
|
|
522
|
+
_markRead() {
|
|
523
|
+
if (this._unreadCount !== 0) {
|
|
524
|
+
this._unreadCount = 0;
|
|
525
|
+
this.emit('unreadChanged', { channel: this.name, count: 0 });
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
_setPresence() {
|
|
529
|
+
this._roomContext.setPresence({
|
|
530
|
+
userId: this._localUser.userId, username: this._localUser.username,
|
|
531
|
+
avatar: this._localUser.avatar, metadata: this._localUser.metadata,
|
|
532
|
+
// Scope tag: on a shared client, other apps' wrappers filter our
|
|
533
|
+
// presence out by this (and we filter theirs).
|
|
534
|
+
__scope: this._options.appName,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* NoLagFeed — high-level activity-feed SDK built on @nolag/js-sdk.
|
|
541
|
+
*
|
|
542
|
+
* Provides multi-channel feeds, posts, likes, comments, presence (who's
|
|
543
|
+
* online), replay, and user mapping — all framework-agnostic via events.
|
|
544
|
+
*
|
|
545
|
+
* The wrapper NEVER manages the connection. The app owns one core NoLag
|
|
546
|
+
* client (shared by any number of wrappers on distinct apps) and the
|
|
547
|
+
* wrapper attaches to it at construction and releases it via `detach()`.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```typescript
|
|
551
|
+
* import { NoLag } from '@nolag/js-sdk';
|
|
552
|
+
* import { NoLagFeed } from '@nolag/feed';
|
|
553
|
+
*
|
|
554
|
+
* const client = NoLag(async () => (await (await fetch('/api/nolag-token')).json()).token);
|
|
555
|
+
* const feed = new NoLagFeed({ client, appName: 'my-feed', username: 'Alice' });
|
|
556
|
+
*
|
|
557
|
+
* feed.on('userOnline', (user) => console.log(user.username, 'is online'));
|
|
558
|
+
*
|
|
559
|
+
* await client.connect(); // the app owns the connection
|
|
560
|
+
* await feed.ready(); // wrapper setup done (identity, lobby, channels)
|
|
561
|
+
*
|
|
562
|
+
* const channel = feed.joinChannel('general');
|
|
563
|
+
* channel.on('postCreated', (post) => console.log(post.username + ':', post.content));
|
|
564
|
+
* channel.createPost({ content: 'Hello!' });
|
|
565
|
+
*
|
|
566
|
+
* feed.detach(); // wrapper releases its handlers and topics
|
|
567
|
+
* client.disconnect(); // the app closes the socket
|
|
568
|
+
* ```
|
|
569
|
+
*/
|
|
570
|
+
class NoLagFeed extends EventEmitter {
|
|
571
|
+
constructor(options) {
|
|
572
|
+
super();
|
|
573
|
+
this._localUser = null;
|
|
574
|
+
this._channels = new Map();
|
|
575
|
+
this._lobby = null;
|
|
576
|
+
this._onlineUsers = new Map();
|
|
577
|
+
this._actorToUserId = new Map();
|
|
578
|
+
this._activeChannel = null;
|
|
579
|
+
// Lifecycle: one setup run per connection epoch; detach is terminal.
|
|
580
|
+
this._epoch = 0;
|
|
581
|
+
this._detached = false;
|
|
582
|
+
this._isReady = false;
|
|
583
|
+
this._lobbyRefreshTimer = null;
|
|
584
|
+
// Stored client handler refs. INVARIANT: every client.on() below has a
|
|
585
|
+
// matching client.off() in detach() — never bare off(event), never inline
|
|
586
|
+
// closures on the client.
|
|
587
|
+
this._onConnectRef = () => this._onConnect();
|
|
588
|
+
this._onDisconnectRef = (reason) => {
|
|
589
|
+
this._log('Disconnected:', reason);
|
|
590
|
+
this.emit('disconnected', reason);
|
|
591
|
+
};
|
|
592
|
+
this._onReconnectRef = () => {
|
|
593
|
+
this._log('Reconnecting...');
|
|
594
|
+
this.emit('reconnecting');
|
|
595
|
+
};
|
|
596
|
+
this._onErrorRef = (error) => {
|
|
597
|
+
this._log('Error:', error);
|
|
598
|
+
this.emit('error', error);
|
|
599
|
+
};
|
|
600
|
+
this._onReplayStartRef = (data) => {
|
|
601
|
+
const event = data;
|
|
602
|
+
for (const channel of this._channels.values()) {
|
|
603
|
+
channel._handleReplayStart(event.count);
|
|
604
|
+
}
|
|
605
|
+
};
|
|
606
|
+
this._onReplayEndRef = (data) => {
|
|
607
|
+
const event = data;
|
|
608
|
+
for (const channel of this._channels.values()) {
|
|
609
|
+
channel._handleReplayEnd(event.replayed);
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
this._onPresenceJoinRef = (data) => this._handleRoomPresenceJoin(data);
|
|
613
|
+
this._onPresenceLeaveRef = (data) => this._handleRoomPresenceLeave(data);
|
|
614
|
+
this._onPresenceUpdateRef = (data) => this._handleRoomPresenceUpdate(data);
|
|
615
|
+
this._onLobbyJoinRef = (data) => this._handleLobbyJoin(data);
|
|
616
|
+
this._onLobbyLeaveRef = (data) => this._handleLobbyLeave(data);
|
|
617
|
+
this._onLobbyUpdateRef = (data) => this._handleLobbyUpdate(data);
|
|
618
|
+
if (!options?.client) {
|
|
619
|
+
throw new TypeError('NoLagFeed requires an injected NoLag client: new NoLagFeed({ client, username, ... })');
|
|
620
|
+
}
|
|
621
|
+
this._client = options.client;
|
|
622
|
+
this._userId = generateId();
|
|
623
|
+
this._options = {
|
|
624
|
+
username: options.username,
|
|
625
|
+
avatar: options.avatar,
|
|
626
|
+
metadata: options.metadata,
|
|
627
|
+
appName: options.appName ?? DEFAULT_APP_NAME,
|
|
628
|
+
maxPostCache: options.maxPostCache ?? DEFAULT_MAX_POST_CACHE,
|
|
629
|
+
maxCommentCache: options.maxCommentCache ?? DEFAULT_MAX_COMMENT_CACHE,
|
|
630
|
+
debug: options.debug ?? false,
|
|
631
|
+
channels: options.channels ?? [],
|
|
632
|
+
};
|
|
633
|
+
this._log = createLogger('NoLagFeed', this._options.debug);
|
|
634
|
+
this._readyPromise = new Promise((resolve, reject) => {
|
|
635
|
+
this._readyResolve = resolve;
|
|
636
|
+
this._readyReject = reject;
|
|
637
|
+
});
|
|
638
|
+
// ready() rejection is only meaningful to callers that await it
|
|
639
|
+
this._readyPromise.catch(() => { });
|
|
640
|
+
registerWrapper(this._client, this._options.appName, 'NoLagFeed');
|
|
641
|
+
// Construction = attach: wire everything now, with stored refs.
|
|
642
|
+
this._client.on('connect', this._onConnectRef);
|
|
643
|
+
this._client.on('disconnect', this._onDisconnectRef);
|
|
644
|
+
this._client.on('reconnect', this._onReconnectRef);
|
|
645
|
+
this._client.on('error', this._onErrorRef);
|
|
646
|
+
this._client.on('replay:start', this._onReplayStartRef);
|
|
647
|
+
this._client.on('replay:end', this._onReplayEndRef);
|
|
648
|
+
this._client.on('presence:join', this._onPresenceJoinRef);
|
|
649
|
+
this._client.on('presence:leave', this._onPresenceLeaveRef);
|
|
650
|
+
this._client.on('presence:update', this._onPresenceUpdateRef);
|
|
651
|
+
this._client.on('lobbyPresence:join', this._onLobbyJoinRef);
|
|
652
|
+
this._client.on('lobbyPresence:leave', this._onLobbyLeaveRef);
|
|
653
|
+
this._client.on('lobbyPresence:update', this._onLobbyUpdateRef);
|
|
654
|
+
// Attach-to-connected: if the client is already authenticated, run setup.
|
|
655
|
+
// The microtask lets the caller wire wrapper event handlers synchronously
|
|
656
|
+
// first; a racing real 'connect' event wins via the epoch guard.
|
|
657
|
+
queueMicrotask(() => {
|
|
658
|
+
if (this._epoch === 0 && !this._detached && this._client.connected) {
|
|
659
|
+
this._onConnect();
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
// ============ Public Properties ============
|
|
664
|
+
/** Whether the underlying connection is established (connected ≠ ready) */
|
|
665
|
+
get connected() {
|
|
666
|
+
return !this._detached && this._client.connected;
|
|
667
|
+
}
|
|
668
|
+
/** The injected core client (owned by the app, not the wrapper) */
|
|
669
|
+
get client() {
|
|
670
|
+
return this._client;
|
|
671
|
+
}
|
|
672
|
+
/** The local user's info (available after ready) */
|
|
673
|
+
get localUser() {
|
|
674
|
+
return this._localUser;
|
|
675
|
+
}
|
|
676
|
+
/** All currently joined channels */
|
|
677
|
+
get channels() {
|
|
678
|
+
return this._channels;
|
|
679
|
+
}
|
|
680
|
+
// ============ Lifecycle ============
|
|
681
|
+
/**
|
|
682
|
+
* Resolves once the wrapper's first setup completed (identity, lobby and
|
|
683
|
+
* configured channels ready — equivalently, once 'connected' has fired).
|
|
684
|
+
* Rejects only if detach() is called before that. Client auth failures
|
|
685
|
+
* surface via the app's own `await client.connect()`, not here.
|
|
686
|
+
*/
|
|
687
|
+
ready() {
|
|
688
|
+
return this._readyPromise;
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Detach from the client: remove every handler this wrapper added,
|
|
692
|
+
* unsubscribe its topics and lobby (when connected), clear state.
|
|
693
|
+
* Terminal and idempotent; never touches the socket. To use the feed again,
|
|
694
|
+
* construct a new instance.
|
|
695
|
+
*/
|
|
696
|
+
detach() {
|
|
697
|
+
if (this._detached)
|
|
698
|
+
return;
|
|
699
|
+
this._log('Detaching...');
|
|
700
|
+
this._detached = true;
|
|
701
|
+
this._epoch++; // aborts any in-flight setup at its next checkpoint
|
|
702
|
+
if (this._lobbyRefreshTimer) {
|
|
703
|
+
clearTimeout(this._lobbyRefreshTimer);
|
|
704
|
+
this._lobbyRefreshTimer = null;
|
|
705
|
+
}
|
|
706
|
+
// Remove all client handlers by stored ref
|
|
707
|
+
this._client.off('connect', this._onConnectRef);
|
|
708
|
+
this._client.off('disconnect', this._onDisconnectRef);
|
|
709
|
+
this._client.off('reconnect', this._onReconnectRef);
|
|
710
|
+
this._client.off('error', this._onErrorRef);
|
|
711
|
+
this._client.off('replay:start', this._onReplayStartRef);
|
|
712
|
+
this._client.off('replay:end', this._onReplayEndRef);
|
|
713
|
+
this._client.off('presence:join', this._onPresenceJoinRef);
|
|
714
|
+
this._client.off('presence:leave', this._onPresenceLeaveRef);
|
|
715
|
+
this._client.off('presence:update', this._onPresenceUpdateRef);
|
|
716
|
+
this._client.off('lobbyPresence:join', this._onLobbyJoinRef);
|
|
717
|
+
this._client.off('lobbyPresence:leave', this._onLobbyLeaveRef);
|
|
718
|
+
this._client.off('lobbyPresence:update', this._onLobbyUpdateRef);
|
|
719
|
+
// Channels: handler-specific off + connected-gated server unsubscribe
|
|
720
|
+
for (const name of [...this._channels.keys()]) {
|
|
721
|
+
this._channels.get(name)._cleanup();
|
|
722
|
+
this._channels.delete(name);
|
|
723
|
+
}
|
|
724
|
+
this._activeChannel = null;
|
|
725
|
+
// Lobby: server unsubscribe is best-effort and needs a live socket
|
|
726
|
+
if (this._lobby && this._client.connected) {
|
|
727
|
+
try {
|
|
728
|
+
this._lobby.unsubscribe();
|
|
729
|
+
}
|
|
730
|
+
catch {
|
|
731
|
+
/* best-effort */
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
this._lobby = null;
|
|
735
|
+
this._onlineUsers.clear();
|
|
736
|
+
this._actorToUserId.clear();
|
|
737
|
+
this._localUser = null;
|
|
738
|
+
releaseWrapper(this._client, this._options.appName);
|
|
739
|
+
if (!this._isReady) {
|
|
740
|
+
this._readyReject(new Error('NoLagFeed detached before ready'));
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
// ============ Private: Epoch Setup ============
|
|
744
|
+
_onConnect() {
|
|
745
|
+
this._epoch++;
|
|
746
|
+
void this._runSetup(this._epoch);
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* One setup pass per connection epoch. Serves both initial setup (epoch 1)
|
|
750
|
+
* and reconnect restore (epoch > 1). Aborts silently whenever a newer
|
|
751
|
+
* epoch started or the wrapper detached — checked after every await.
|
|
752
|
+
*/
|
|
753
|
+
async _runSetup(epoch) {
|
|
754
|
+
const stale = () => epoch !== this._epoch || this._detached;
|
|
755
|
+
this._log(this._isReady ? 'Restoring after reconnect...' : 'Setting up...');
|
|
756
|
+
// Identity (client.actorId is guaranteed post-auth)
|
|
757
|
+
if (!this._localUser) {
|
|
758
|
+
this._localUser = {
|
|
759
|
+
userId: this._userId,
|
|
760
|
+
actorTokenId: this._client.actorId,
|
|
761
|
+
username: this._options.username,
|
|
762
|
+
avatar: this._options.avatar,
|
|
763
|
+
metadata: this._options.metadata,
|
|
764
|
+
joinedAt: Date.now(),
|
|
765
|
+
isLocal: true,
|
|
766
|
+
};
|
|
767
|
+
this._log('Local user:', this._localUser.userId, '→', this._localUser.actorTokenId);
|
|
768
|
+
}
|
|
769
|
+
else {
|
|
770
|
+
this._localUser.actorTokenId = this._client.actorId;
|
|
771
|
+
}
|
|
772
|
+
// Lobby: subscribe every epoch (idempotent server-side) and diff-hydrate
|
|
773
|
+
// from the returned snapshot — one path for setup and restore.
|
|
774
|
+
if (!this._lobby) {
|
|
775
|
+
this._lobby = this._client.setApp(this._options.appName).setLobby(LOBBY_ID);
|
|
776
|
+
}
|
|
777
|
+
try {
|
|
778
|
+
const state = await this._lobby.subscribe();
|
|
779
|
+
if (stale())
|
|
780
|
+
return;
|
|
781
|
+
this._diffHydrateOnlineUsers(state);
|
|
782
|
+
this._log('Lobby subscribed, online users:', this._onlineUsers.size);
|
|
783
|
+
}
|
|
784
|
+
catch (err) {
|
|
785
|
+
if (stale())
|
|
786
|
+
return;
|
|
787
|
+
this._log('Lobby subscription failed:', err);
|
|
788
|
+
}
|
|
789
|
+
if (!this._isReady) {
|
|
790
|
+
// First successful setup: pre-subscribe configured channels
|
|
791
|
+
// (posts only, no presence)
|
|
792
|
+
for (const channelName of this._options.channels) {
|
|
793
|
+
this._subscribeChannelInternal(channelName);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
else if (this._activeChannel) {
|
|
797
|
+
// Server auto-restored topic subscriptions; only channel-scoped presence
|
|
798
|
+
// needs re-applying (the core does not restore it).
|
|
799
|
+
this._channels.get(this._activeChannel)?._updateLocalPresence();
|
|
800
|
+
}
|
|
801
|
+
if (stale())
|
|
802
|
+
return;
|
|
803
|
+
// Ready keys on the first setup that COMPLETES, not on epoch 1: an
|
|
804
|
+
// epoch aborted by a racing reconnect must not strand ready().
|
|
805
|
+
if (!this._isReady) {
|
|
806
|
+
this._isReady = true;
|
|
807
|
+
this._readyResolve();
|
|
808
|
+
this.emit('connected');
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
this.emit('reconnected');
|
|
812
|
+
}
|
|
813
|
+
// Deferred lobby refetch: catches users who joined during the setup
|
|
814
|
+
// window (e.g. simultaneous multi-tab connects).
|
|
815
|
+
this._scheduleLobbyRefresh(epoch);
|
|
816
|
+
}
|
|
817
|
+
_scheduleLobbyRefresh(epoch) {
|
|
818
|
+
if (this._lobbyRefreshTimer)
|
|
819
|
+
clearTimeout(this._lobbyRefreshTimer);
|
|
820
|
+
this._lobbyRefreshTimer = setTimeout(() => {
|
|
821
|
+
this._lobbyRefreshTimer = null;
|
|
822
|
+
if (epoch !== this._epoch || this._detached || !this._client.connected || !this._lobby) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
this._lobby
|
|
826
|
+
.fetchPresence()
|
|
827
|
+
.then((state) => {
|
|
828
|
+
if (epoch !== this._epoch || this._detached)
|
|
829
|
+
return;
|
|
830
|
+
this._diffHydrateOnlineUsers(state);
|
|
831
|
+
})
|
|
832
|
+
.catch(() => {
|
|
833
|
+
/* best-effort */
|
|
834
|
+
});
|
|
835
|
+
}, LOBBY_REFRESH_DELAY_MS);
|
|
836
|
+
}
|
|
837
|
+
// ============ Channel Management ============
|
|
838
|
+
/**
|
|
839
|
+
* Join (activate) a feed channel. Deactivates the previous active channel.
|
|
840
|
+
* If the channel was pre-subscribed via the `channels` option, activates it.
|
|
841
|
+
* Otherwise creates, subscribes, and activates it.
|
|
842
|
+
*/
|
|
843
|
+
joinChannel(name) {
|
|
844
|
+
this._assertUsable();
|
|
845
|
+
// Deactivate the current active channel
|
|
846
|
+
if (this._activeChannel && this._activeChannel !== name) {
|
|
847
|
+
const prev = this._channels.get(this._activeChannel);
|
|
848
|
+
if (prev)
|
|
849
|
+
prev._deactivate();
|
|
850
|
+
}
|
|
851
|
+
// Get or create the channel
|
|
852
|
+
let channel = this._channels.get(name);
|
|
853
|
+
if (!channel) {
|
|
854
|
+
channel = this._subscribeChannelInternal(name);
|
|
855
|
+
}
|
|
856
|
+
this._activeChannel = name;
|
|
857
|
+
channel._activate();
|
|
858
|
+
return channel;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Leave a feed channel. Fully unsubscribes and removes it.
|
|
862
|
+
*/
|
|
863
|
+
leaveChannel(name) {
|
|
864
|
+
const channel = this._channels.get(name);
|
|
865
|
+
if (!channel)
|
|
866
|
+
return;
|
|
867
|
+
this._log('Leaving channel:', name);
|
|
868
|
+
channel._cleanup();
|
|
869
|
+
this._channels.delete(name);
|
|
870
|
+
if (this._activeChannel === name) {
|
|
871
|
+
this._activeChannel = null;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Get all joined channels.
|
|
876
|
+
*/
|
|
877
|
+
getChannels() {
|
|
878
|
+
return Array.from(this._channels.values());
|
|
879
|
+
}
|
|
880
|
+
// ============ Global Presence ============
|
|
881
|
+
/**
|
|
882
|
+
* Get all users currently online across all channels.
|
|
883
|
+
*/
|
|
884
|
+
getOnlineUsers() {
|
|
885
|
+
return Array.from(this._onlineUsers.values());
|
|
886
|
+
}
|
|
887
|
+
// ============ Profile ============
|
|
888
|
+
/**
|
|
889
|
+
* Update the local user's profile info (broadcast to the active channel).
|
|
890
|
+
*/
|
|
891
|
+
updateProfile(updates) {
|
|
892
|
+
if (!this._localUser)
|
|
893
|
+
return;
|
|
894
|
+
if (updates.username !== undefined) {
|
|
895
|
+
this._localUser.username = updates.username;
|
|
896
|
+
this._options.username = updates.username;
|
|
897
|
+
}
|
|
898
|
+
if (updates.avatar !== undefined) {
|
|
899
|
+
this._localUser.avatar = updates.avatar;
|
|
900
|
+
this._options.avatar = updates.avatar;
|
|
901
|
+
}
|
|
902
|
+
if (updates.metadata !== undefined) {
|
|
903
|
+
this._localUser.metadata = { ...this._localUser.metadata, ...updates.metadata };
|
|
904
|
+
this._options.metadata = this._localUser.metadata;
|
|
905
|
+
}
|
|
906
|
+
// Re-set presence only on the active channel
|
|
907
|
+
if (this._activeChannel) {
|
|
908
|
+
const activeChannel = this._channels.get(this._activeChannel);
|
|
909
|
+
if (activeChannel)
|
|
910
|
+
activeChannel._updateLocalPresence();
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
// ============ Private: Guards ============
|
|
914
|
+
_assertUsable() {
|
|
915
|
+
if (this._detached) {
|
|
916
|
+
throw new Error('NoLagFeed has been detached — construct a new instance');
|
|
917
|
+
}
|
|
918
|
+
if (!this._isReady || !this._localUser) {
|
|
919
|
+
throw new Error('NoLagFeed not ready — await ready() or the "connected" event');
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
// ============ Private: Channel Setup ============
|
|
923
|
+
_subscribeChannelInternal(name) {
|
|
924
|
+
this._log('Subscribing channel:', name);
|
|
925
|
+
const roomContext = this._client.setApp(this._options.appName).setRoom(name);
|
|
926
|
+
const channel = new FeedChannel(name, roomContext, this._localUser, this._options, createLogger(`FeedChannel:${name}`, this._options.debug), () => this._client.connected);
|
|
927
|
+
this._channels.set(name, channel);
|
|
928
|
+
channel._subscribe();
|
|
929
|
+
return channel;
|
|
930
|
+
}
|
|
931
|
+
// ============ Private: Scope Filtering ============
|
|
932
|
+
/**
|
|
933
|
+
* On a shared client, presence events from other apps' wrappers arrive on
|
|
934
|
+
* the same connection-level events. Wrappers stamp their presence with a
|
|
935
|
+
* `__scope` (their appName); a mismatched tag means another app's data.
|
|
936
|
+
* Untagged presence is accepted (older peers in this same app).
|
|
937
|
+
*/
|
|
938
|
+
_foreignScope(data) {
|
|
939
|
+
const scope = data?.__scope;
|
|
940
|
+
return typeof scope === 'string' && scope !== this._options.appName;
|
|
941
|
+
}
|
|
942
|
+
// ============ Private: Channel Presence → Active Channel ============
|
|
943
|
+
_handleRoomPresenceJoin(data) {
|
|
944
|
+
if (data.actorTokenId === this._localUser?.actorTokenId)
|
|
945
|
+
return;
|
|
946
|
+
const presenceData = data.presence;
|
|
947
|
+
if (!presenceData?.userId || this._foreignScope(presenceData))
|
|
948
|
+
return;
|
|
949
|
+
// Track as online user
|
|
950
|
+
const user = this._presenceToUser(data.actorTokenId, presenceData);
|
|
951
|
+
this._actorToUserId.set(data.actorTokenId, user.userId);
|
|
952
|
+
if (!this._onlineUsers.has(user.userId)) {
|
|
953
|
+
this._onlineUsers.set(user.userId, user);
|
|
954
|
+
this.emit('userOnline', user);
|
|
955
|
+
}
|
|
956
|
+
const channel = this._activeChannel ? this._channels.get(this._activeChannel) : undefined;
|
|
957
|
+
if (channel) {
|
|
958
|
+
channel._handlePresenceJoin(data.actorTokenId, presenceData);
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
_handleRoomPresenceLeave(data) {
|
|
962
|
+
if (data.actorTokenId === this._localUser?.actorTokenId)
|
|
963
|
+
return;
|
|
964
|
+
// Channel leave ≠ offline — user may still be in another channel.
|
|
965
|
+
// Lobby leave handles actual offline status.
|
|
966
|
+
const channel = this._activeChannel ? this._channels.get(this._activeChannel) : undefined;
|
|
967
|
+
if (channel) {
|
|
968
|
+
channel._handlePresenceLeave(data.actorTokenId);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
_handleRoomPresenceUpdate(data) {
|
|
972
|
+
if (data.actorTokenId === this._localUser?.actorTokenId)
|
|
973
|
+
return;
|
|
974
|
+
const presenceData = data.presence;
|
|
975
|
+
if (!presenceData?.userId || this._foreignScope(presenceData))
|
|
976
|
+
return;
|
|
977
|
+
// Update online user info if we already track them
|
|
978
|
+
if (this._onlineUsers.has(presenceData.userId)) {
|
|
979
|
+
const user = this._presenceToUser(data.actorTokenId, presenceData);
|
|
980
|
+
this._onlineUsers.set(user.userId, user);
|
|
981
|
+
}
|
|
982
|
+
const channel = this._activeChannel ? this._channels.get(this._activeChannel) : undefined;
|
|
983
|
+
if (channel) {
|
|
984
|
+
channel._handlePresenceUpdate(data.actorTokenId, presenceData);
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
// ============ Private: Lobby ============
|
|
988
|
+
_handleLobbyJoin(event) {
|
|
989
|
+
const { actorId, data } = event;
|
|
990
|
+
if (actorId === this._localUser?.actorTokenId)
|
|
991
|
+
return;
|
|
992
|
+
const presenceData = data;
|
|
993
|
+
if (!presenceData.userId || this._foreignScope(presenceData))
|
|
994
|
+
return;
|
|
995
|
+
const user = this._presenceToUser(actorId, presenceData);
|
|
996
|
+
this._actorToUserId.set(actorId, user.userId);
|
|
997
|
+
if (!this._onlineUsers.has(user.userId)) {
|
|
998
|
+
this._onlineUsers.set(user.userId, user);
|
|
999
|
+
this.emit('userOnline', user);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
_handleLobbyLeave(event) {
|
|
1003
|
+
const { actorId, data } = event;
|
|
1004
|
+
if (actorId === this._localUser?.actorTokenId)
|
|
1005
|
+
return;
|
|
1006
|
+
const presenceData = data;
|
|
1007
|
+
if (this._foreignScope(presenceData))
|
|
1008
|
+
return;
|
|
1009
|
+
const userId = presenceData?.userId
|
|
1010
|
+
|| this._actorToUserId.get(actorId)
|
|
1011
|
+
|| this._findUserIdByActorId(actorId);
|
|
1012
|
+
if (userId) {
|
|
1013
|
+
const user = this._onlineUsers.get(userId);
|
|
1014
|
+
if (user) {
|
|
1015
|
+
this._onlineUsers.delete(userId);
|
|
1016
|
+
this._actorToUserId.delete(actorId);
|
|
1017
|
+
this.emit('userOffline', user);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
_handleLobbyUpdate(event) {
|
|
1022
|
+
const { actorId, data } = event;
|
|
1023
|
+
if (actorId === this._localUser?.actorTokenId)
|
|
1024
|
+
return;
|
|
1025
|
+
const presenceData = data;
|
|
1026
|
+
if (!presenceData.userId || this._foreignScope(presenceData))
|
|
1027
|
+
return;
|
|
1028
|
+
const user = this._presenceToUser(actorId, presenceData);
|
|
1029
|
+
this._onlineUsers.set(user.userId, user);
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Reconcile the online-user map against a fresh lobby snapshot, emitting
|
|
1033
|
+
* only the deltas (userOffline for vanished, userOnline for new). One path
|
|
1034
|
+
* for initial hydration, reconnect restore, and the deferred refetch.
|
|
1035
|
+
*/
|
|
1036
|
+
_diffHydrateOnlineUsers(state) {
|
|
1037
|
+
// Build the fresh user set from the snapshot
|
|
1038
|
+
const fresh = new Map();
|
|
1039
|
+
const freshActors = new Map();
|
|
1040
|
+
for (const roomId of Object.keys(state)) {
|
|
1041
|
+
const roomPresence = state[roomId];
|
|
1042
|
+
for (const actorId of Object.keys(roomPresence)) {
|
|
1043
|
+
if (actorId === this._localUser?.actorTokenId)
|
|
1044
|
+
continue;
|
|
1045
|
+
const raw = roomPresence[actorId];
|
|
1046
|
+
// Server returns full actor records with presence nested under .presence
|
|
1047
|
+
const presenceData = (raw?.presence ?? raw);
|
|
1048
|
+
if (presenceData?.userId && !this._foreignScope(presenceData)) {
|
|
1049
|
+
if (!fresh.has(presenceData.userId)) {
|
|
1050
|
+
fresh.set(presenceData.userId, this._presenceToUser(actorId, presenceData));
|
|
1051
|
+
}
|
|
1052
|
+
freshActors.set(actorId, presenceData.userId);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
// Vanished users
|
|
1057
|
+
for (const [userId, user] of [...this._onlineUsers]) {
|
|
1058
|
+
if (!fresh.has(userId)) {
|
|
1059
|
+
this._onlineUsers.delete(userId);
|
|
1060
|
+
for (const [actorId, mappedUserId] of [...this._actorToUserId]) {
|
|
1061
|
+
if (mappedUserId === userId)
|
|
1062
|
+
this._actorToUserId.delete(actorId);
|
|
1063
|
+
}
|
|
1064
|
+
this.emit('userOffline', user);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
// New users
|
|
1068
|
+
for (const [userId, user] of fresh) {
|
|
1069
|
+
if (!this._onlineUsers.has(userId)) {
|
|
1070
|
+
this._onlineUsers.set(userId, user);
|
|
1071
|
+
this.emit('userOnline', user);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
for (const [actorId, userId] of freshActors) {
|
|
1075
|
+
this._actorToUserId.set(actorId, userId);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
// ============ Private: Helpers ============
|
|
1079
|
+
_presenceToUser(actorTokenId, data) {
|
|
1080
|
+
return {
|
|
1081
|
+
userId: data.userId,
|
|
1082
|
+
actorTokenId,
|
|
1083
|
+
username: data.username,
|
|
1084
|
+
avatar: data.avatar,
|
|
1085
|
+
metadata: data.metadata,
|
|
1086
|
+
joinedAt: Date.now(),
|
|
1087
|
+
isLocal: false,
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
_findUserIdByActorId(actorTokenId) {
|
|
1091
|
+
for (const user of this._onlineUsers.values()) {
|
|
1092
|
+
if (user.actorTokenId === actorTokenId)
|
|
1093
|
+
return user.userId;
|
|
1094
|
+
}
|
|
1095
|
+
return undefined;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
export { EventEmitter, FeedChannel, NoLagFeed };
|
|
1100
|
+
//# sourceMappingURL=react-native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-native.js","sources":["../src/EventEmitter.ts","../src/PostStore.ts","../src/ReactionManager.ts","../src/PresenceManager.ts","../src/utils.ts","../src/constants.ts","../src/FeedChannel.ts","../src/NoLagFeed.ts"],"sourcesContent":[null,null,null,null,null,null,null,null],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nolag/feed",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -9,9 +9,14 @@
|
|
|
9
9
|
"main": "./dist/index.cjs",
|
|
10
10
|
"module": "./dist/index.mjs",
|
|
11
11
|
"browser": "./dist/browser.js",
|
|
12
|
+
"react-native": "./dist/react-native.js",
|
|
12
13
|
"types": "./dist/index.d.ts",
|
|
13
14
|
"exports": {
|
|
14
15
|
".": {
|
|
16
|
+
"react-native": {
|
|
17
|
+
"types": "./dist/react-native.d.ts",
|
|
18
|
+
"default": "./dist/react-native.js"
|
|
19
|
+
},
|
|
15
20
|
"browser": {
|
|
16
21
|
"types": "./dist/browser.d.ts",
|
|
17
22
|
"default": "./dist/browser.js"
|
|
@@ -25,7 +30,8 @@
|
|
|
25
30
|
"default": "./dist/index.cjs"
|
|
26
31
|
},
|
|
27
32
|
"default": "./dist/index.mjs"
|
|
28
|
-
}
|
|
33
|
+
},
|
|
34
|
+
"./package.json": "./package.json"
|
|
29
35
|
},
|
|
30
36
|
"files": [
|
|
31
37
|
"dist"
|
|
@@ -46,10 +52,10 @@
|
|
|
46
52
|
"license": "MIT",
|
|
47
53
|
"homepage": "https://nolag.app",
|
|
48
54
|
"devDependencies": {
|
|
49
|
-
"@nolag/js-sdk": "^1.
|
|
55
|
+
"@nolag/js-sdk": "^1.12.0"
|
|
50
56
|
},
|
|
51
57
|
"peerDependencies": {
|
|
52
|
-
"@nolag/js-sdk": "^1.
|
|
58
|
+
"@nolag/js-sdk": "^1.12.0"
|
|
53
59
|
},
|
|
54
60
|
"publishConfig": {
|
|
55
61
|
"access": "public"
|