@liveblocks/react 2.7.0-versions2 → 2.7.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/{chunk-YGRZXVI6.js → chunk-KNPU4P3Y.js} +1060 -663
- package/dist/chunk-KNPU4P3Y.js.map +1 -0
- package/dist/{chunk-HS6BFH3A.mjs → chunk-OKR7ROQ5.mjs} +1065 -668
- package/dist/chunk-OKR7ROQ5.mjs.map +1 -0
- package/dist/index.d.mts +2 -10
- package/dist/index.d.ts +2 -10
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{suspense-2UL0jBvg.d.mts → suspense-pL0llH_6.d.mts} +283 -30
- package/dist/{suspense-2UL0jBvg.d.ts → suspense-pL0llH_6.d.ts} +283 -30
- package/dist/suspense.d.mts +1 -1
- package/dist/suspense.d.ts +1 -1
- package/dist/suspense.js +3 -3
- package/dist/suspense.mjs +1 -1
- package/package.json +3 -3
- package/dist/chunk-HS6BFH3A.mjs.map +0 -1
- package/dist/chunk-YGRZXVI6.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
2
|
var PKG_NAME = "@liveblocks/react";
|
|
3
|
-
var PKG_VERSION = "2.7.0
|
|
3
|
+
var PKG_VERSION = "2.7.0";
|
|
4
4
|
var PKG_FORMAT = "esm";
|
|
5
5
|
|
|
6
6
|
// src/ClientSideSuspense.tsx
|
|
@@ -13,65 +13,6 @@ function ClientSideSuspense(props) {
|
|
|
13
13
|
return /* @__PURE__ */ React.createElement(React.Suspense, { fallback: props.fallback }, mounted ? typeof props.children === "function" ? props.children() : props.children : props.fallback);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
// src/comments/lib/selected-threads.ts
|
|
17
|
-
import {
|
|
18
|
-
applyOptimisticUpdates
|
|
19
|
-
} from "@liveblocks/core";
|
|
20
|
-
function selectedUserThreads(state) {
|
|
21
|
-
const result = applyOptimisticUpdates(state);
|
|
22
|
-
const threads = Object.values(result.threads).filter(
|
|
23
|
-
(thread) => {
|
|
24
|
-
if (thread.deletedAt !== void 0) {
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
);
|
|
30
|
-
return threads.sort(
|
|
31
|
-
(a, b) => (b.updatedAt ?? b.createdAt).getTime() - (a.updatedAt ?? a.createdAt).getTime()
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
function selectedThreads(roomId, state, options) {
|
|
35
|
-
const result = applyOptimisticUpdates(state);
|
|
36
|
-
const threads = Object.values(result.threads).filter(
|
|
37
|
-
(thread) => {
|
|
38
|
-
if (thread.roomId !== roomId) return false;
|
|
39
|
-
if (thread.deletedAt !== void 0) {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
const query = options.query;
|
|
43
|
-
if (!query) return true;
|
|
44
|
-
if (query.resolved !== void 0 && thread.resolved !== query.resolved) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
for (const key in query.metadata) {
|
|
48
|
-
const metadataValue = thread.metadata[key];
|
|
49
|
-
const filterValue = query.metadata[key];
|
|
50
|
-
if (assertFilterIsStartsWithOperator(filterValue) && assertMetadataValueIsString(metadataValue)) {
|
|
51
|
-
if (metadataValue.startsWith(filterValue.startsWith)) {
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
if (metadataValue !== filterValue) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
);
|
|
62
|
-
return threads.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
63
|
-
}
|
|
64
|
-
var assertFilterIsStartsWithOperator = (filter) => {
|
|
65
|
-
if (typeof filter === "object" && typeof filter.startsWith === "string") {
|
|
66
|
-
return true;
|
|
67
|
-
} else {
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
var assertMetadataValueIsString = (value) => {
|
|
72
|
-
return typeof value === "string";
|
|
73
|
-
};
|
|
74
|
-
|
|
75
16
|
// src/comments/errors.ts
|
|
76
17
|
var CreateThreadError = class extends Error {
|
|
77
18
|
constructor(cause, context) {
|
|
@@ -173,46 +114,66 @@ var UpdateNotificationSettingsError = class extends Error {
|
|
|
173
114
|
// src/room.tsx
|
|
174
115
|
import { shallow as shallow2 } from "@liveblocks/client";
|
|
175
116
|
import {
|
|
176
|
-
addReaction,
|
|
177
117
|
CommentsApiError,
|
|
178
|
-
console as
|
|
118
|
+
console as console3,
|
|
179
119
|
createCommentId,
|
|
180
120
|
createThreadId,
|
|
181
|
-
deleteComment,
|
|
182
121
|
deprecateIf,
|
|
183
122
|
errorIf,
|
|
184
123
|
kInternal as kInternal2,
|
|
185
124
|
makeEventSource,
|
|
186
125
|
makePoller as makePoller2,
|
|
187
|
-
|
|
126
|
+
nn,
|
|
188
127
|
NotificationsApiError,
|
|
189
|
-
removeReaction,
|
|
190
128
|
ServerMsgCode,
|
|
191
|
-
stringify
|
|
192
|
-
upsertComment
|
|
129
|
+
stringify as stringify2
|
|
193
130
|
} from "@liveblocks/core";
|
|
194
131
|
import * as React4 from "react";
|
|
195
132
|
import { useSyncExternalStoreWithSelector as useSyncExternalStoreWithSelector2 } from "use-sync-external-store/shim/with-selector.js";
|
|
196
133
|
|
|
197
|
-
// src/
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
134
|
+
// src/lib/compare.ts
|
|
135
|
+
function byFirstCreated(a, b) {
|
|
136
|
+
return a.createdAt.getTime() - b.createdAt.getTime();
|
|
137
|
+
}
|
|
138
|
+
function isMoreRecentlyUpdated(a, b) {
|
|
139
|
+
return byMostRecentlyUpdated(a, b) < 0;
|
|
140
|
+
}
|
|
141
|
+
function byMostRecentlyUpdated(a, b) {
|
|
142
|
+
return (b.updatedAt ?? b.createdAt).getTime() - (a.updatedAt ?? a.createdAt).getTime();
|
|
205
143
|
}
|
|
206
144
|
|
|
207
|
-
// src/
|
|
208
|
-
import {
|
|
209
|
-
function
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
145
|
+
// src/lib/guards.ts
|
|
146
|
+
import { isPlainObject } from "@liveblocks/core";
|
|
147
|
+
function isStartsWith(blob) {
|
|
148
|
+
return isPlainObject(blob) && isString(blob.startsWith);
|
|
149
|
+
}
|
|
150
|
+
function isString(value) {
|
|
151
|
+
return typeof value === "string";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/lib/querying.ts
|
|
155
|
+
function makeThreadsFilter(query) {
|
|
156
|
+
return (thread) => matchesQuery(thread, query) && matchesMetadata(thread, query);
|
|
157
|
+
}
|
|
158
|
+
function matchesQuery(thread, q) {
|
|
159
|
+
return q.resolved === void 0 || thread.resolved === q.resolved;
|
|
160
|
+
}
|
|
161
|
+
function matchesMetadata(thread, q) {
|
|
162
|
+
const metadata = thread.metadata;
|
|
163
|
+
return q.metadata === void 0 || Object.entries(q.metadata).every(
|
|
164
|
+
([key, op]) => (
|
|
165
|
+
// Boolean logic: op? => value matches the operator
|
|
166
|
+
op === void 0 || matchesOperator(metadata[key], op)
|
|
167
|
+
)
|
|
214
168
|
);
|
|
215
169
|
}
|
|
170
|
+
function matchesOperator(value, op) {
|
|
171
|
+
if (isStartsWith(op)) {
|
|
172
|
+
return isString(value) && value.startsWith(op.startsWith);
|
|
173
|
+
} else {
|
|
174
|
+
return value === op;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
216
177
|
|
|
217
178
|
// src/lib/retry-error.ts
|
|
218
179
|
import { wait } from "@liveblocks/core";
|
|
@@ -307,9 +268,9 @@ import {
|
|
|
307
268
|
kInternal,
|
|
308
269
|
makePoller,
|
|
309
270
|
memoizeOnSuccess,
|
|
310
|
-
nanoid,
|
|
311
271
|
raise,
|
|
312
|
-
shallow
|
|
272
|
+
shallow,
|
|
273
|
+
stringify
|
|
313
274
|
} from "@liveblocks/core";
|
|
314
275
|
import React2, {
|
|
315
276
|
createContext,
|
|
@@ -320,6 +281,709 @@ import React2, {
|
|
|
320
281
|
} from "react";
|
|
321
282
|
import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
|
|
322
283
|
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/shim/with-selector.js";
|
|
284
|
+
|
|
285
|
+
// src/umbrella-store.ts
|
|
286
|
+
import { console as console2, createStore, mapValues, nanoid } from "@liveblocks/core";
|
|
287
|
+
var UmbrellaStore = class {
|
|
288
|
+
constructor() {
|
|
289
|
+
this._store = createStore({
|
|
290
|
+
threads: {},
|
|
291
|
+
queries: {},
|
|
292
|
+
optimisticUpdates: [],
|
|
293
|
+
inboxNotifications: {},
|
|
294
|
+
notificationSettings: {},
|
|
295
|
+
versions: {}
|
|
296
|
+
});
|
|
297
|
+
this.get = this.get.bind(this);
|
|
298
|
+
this.subscribe = this.subscribe.bind(this);
|
|
299
|
+
}
|
|
300
|
+
get() {
|
|
301
|
+
return this._store.get();
|
|
302
|
+
}
|
|
303
|
+
subscribe(callback) {
|
|
304
|
+
return this._store.subscribe(callback);
|
|
305
|
+
}
|
|
306
|
+
// Direct low-level cache mutations ------------------------------------------------- {{{
|
|
307
|
+
updateThreadsCache(mapFn) {
|
|
308
|
+
this._store.set((state) => {
|
|
309
|
+
const threads = mapFn(state.threads);
|
|
310
|
+
return threads !== state.threads ? { ...state, threads } : state;
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
updateInboxNotificationsCache(mapFn) {
|
|
314
|
+
this._store.set((state) => {
|
|
315
|
+
const inboxNotifications = mapFn(state.inboxNotifications);
|
|
316
|
+
return inboxNotifications !== state.inboxNotifications ? { ...state, inboxNotifications } : state;
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
setNotificationSettings(roomId, settings) {
|
|
320
|
+
this._store.set((state) => ({
|
|
321
|
+
...state,
|
|
322
|
+
notificationSettings: {
|
|
323
|
+
...state.notificationSettings,
|
|
324
|
+
[roomId]: settings
|
|
325
|
+
}
|
|
326
|
+
}));
|
|
327
|
+
}
|
|
328
|
+
setVersions(roomId, versions) {
|
|
329
|
+
this._store.set((state) => ({
|
|
330
|
+
...state,
|
|
331
|
+
versions: {
|
|
332
|
+
...state.versions,
|
|
333
|
+
[roomId]: versions
|
|
334
|
+
}
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
setQueryState(queryKey, queryState) {
|
|
338
|
+
this._store.set((state) => ({
|
|
339
|
+
...state,
|
|
340
|
+
queries: {
|
|
341
|
+
...state.queries,
|
|
342
|
+
[queryKey]: queryState
|
|
343
|
+
}
|
|
344
|
+
}));
|
|
345
|
+
}
|
|
346
|
+
updateOptimisticUpdatesCache(mapFn) {
|
|
347
|
+
this._store.set((state) => ({
|
|
348
|
+
...state,
|
|
349
|
+
optimisticUpdates: mapFn(state.optimisticUpdates)
|
|
350
|
+
}));
|
|
351
|
+
}
|
|
352
|
+
// ---------------------------------------------------------------------------------- }}}
|
|
353
|
+
/** @internal - Only call this method from unit tests. */
|
|
354
|
+
force_set(callback) {
|
|
355
|
+
return this._store.set(callback);
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Updates an existing inbox notification with a new value, replacing the
|
|
359
|
+
* corresponding optimistic update.
|
|
360
|
+
*
|
|
361
|
+
* This will not update anything if the inbox notification ID isn't found in
|
|
362
|
+
* the cache.
|
|
363
|
+
*/
|
|
364
|
+
updateInboxNotification(inboxNotificationId, optimisticUpdateId, callback) {
|
|
365
|
+
this._store.batch(() => {
|
|
366
|
+
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
367
|
+
this.updateInboxNotificationsCache((cache) => {
|
|
368
|
+
const existing = cache[inboxNotificationId];
|
|
369
|
+
if (!existing) {
|
|
370
|
+
return cache;
|
|
371
|
+
}
|
|
372
|
+
const inboxNotifications = {
|
|
373
|
+
...cache,
|
|
374
|
+
[inboxNotificationId]: callback(existing)
|
|
375
|
+
};
|
|
376
|
+
return inboxNotifications;
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Updates *all* inbox notifications by running a mapper function over all of
|
|
382
|
+
* them, replacing the corresponding optimistic update.
|
|
383
|
+
*/
|
|
384
|
+
updateAllInboxNotifications(optimisticUpdateId, mapFn) {
|
|
385
|
+
this._store.batch(() => {
|
|
386
|
+
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
387
|
+
this.updateInboxNotificationsCache((cache) => mapValues(cache, mapFn));
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Deletes an existing inbox notification, replacing the corresponding
|
|
392
|
+
* optimistic update.
|
|
393
|
+
*/
|
|
394
|
+
deleteInboxNotification(inboxNotificationId, optimisticUpdateId) {
|
|
395
|
+
this._store.batch(() => {
|
|
396
|
+
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
397
|
+
this.updateInboxNotificationsCache((cache) => {
|
|
398
|
+
const { [inboxNotificationId]: removed, ...newCache } = cache;
|
|
399
|
+
return removed === void 0 ? cache : newCache;
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Deletes *all* inbox notifications, replacing the corresponding optimistic
|
|
405
|
+
* update.
|
|
406
|
+
*/
|
|
407
|
+
deleteAllInboxNotifications(optimisticUpdateId) {
|
|
408
|
+
this._store.batch(() => {
|
|
409
|
+
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
410
|
+
this.updateInboxNotificationsCache(() => ({}));
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Creates an new thread, replacing the corresponding optimistic update.
|
|
415
|
+
*/
|
|
416
|
+
createThread(optimisticUpdateId, thread) {
|
|
417
|
+
this._store.batch(() => {
|
|
418
|
+
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
419
|
+
this.updateThreadsCache((cache) => ({ ...cache, [thread.id]: thread }));
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Updates an existing thread with a new value, replacing the corresponding
|
|
424
|
+
* optimistic update.
|
|
425
|
+
*
|
|
426
|
+
* This will not update anything if:
|
|
427
|
+
* - The thread ID isn't found in the cache; or
|
|
428
|
+
* - The thread ID was already deleted from the cache; or
|
|
429
|
+
* - The thread ID in the cache was updated more recently than the optimistic
|
|
430
|
+
* update's timestamp (if given)
|
|
431
|
+
*/
|
|
432
|
+
updateThread(threadId, optimisticUpdateId, callback, updatedAt) {
|
|
433
|
+
this._store.batch(() => {
|
|
434
|
+
if (optimisticUpdateId !== null) {
|
|
435
|
+
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
436
|
+
}
|
|
437
|
+
this.updateThreadsCache((cache) => {
|
|
438
|
+
const existing = cache[threadId];
|
|
439
|
+
if (!existing) {
|
|
440
|
+
return cache;
|
|
441
|
+
}
|
|
442
|
+
if (existing.deletedAt !== void 0) {
|
|
443
|
+
return cache;
|
|
444
|
+
}
|
|
445
|
+
if (!!updatedAt && !!existing.updatedAt && existing.updatedAt > updatedAt) {
|
|
446
|
+
return cache;
|
|
447
|
+
}
|
|
448
|
+
return { ...cache, [threadId]: callback(existing) };
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Soft-deletes an existing thread by setting its `deletedAt` value,
|
|
454
|
+
* replacing the corresponding optimistic update.
|
|
455
|
+
*
|
|
456
|
+
* This will not update anything if:
|
|
457
|
+
* - The thread ID isn't found in the cache; or
|
|
458
|
+
* - The thread ID was already deleted from the cache
|
|
459
|
+
*/
|
|
460
|
+
deleteThread(threadId, optimisticUpdateId) {
|
|
461
|
+
return this.updateThread(
|
|
462
|
+
threadId,
|
|
463
|
+
optimisticUpdateId,
|
|
464
|
+
// A deletion is actually an update of the deletedAt property internally
|
|
465
|
+
(thread) => ({ ...thread, updatedAt: /* @__PURE__ */ new Date(), deletedAt: /* @__PURE__ */ new Date() })
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Creates an existing comment and ensures the associated notification is
|
|
470
|
+
* updated correctly, replacing the corresponding optimistic update.
|
|
471
|
+
*/
|
|
472
|
+
createComment(newComment, optimisticUpdateId) {
|
|
473
|
+
this._store.batch(() => {
|
|
474
|
+
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
475
|
+
const existingThread = this._store.get().threads[newComment.threadId];
|
|
476
|
+
if (!existingThread) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
this.updateThreadsCache((cache) => ({
|
|
480
|
+
...cache,
|
|
481
|
+
[newComment.threadId]: upsertComment(existingThread, newComment)
|
|
482
|
+
}));
|
|
483
|
+
this.updateInboxNotificationsCache((cache) => {
|
|
484
|
+
const existingNotification = Object.values(cache).find(
|
|
485
|
+
(notification) => notification.kind === "thread" && notification.threadId === newComment.threadId
|
|
486
|
+
);
|
|
487
|
+
if (!existingNotification) {
|
|
488
|
+
return cache;
|
|
489
|
+
}
|
|
490
|
+
return {
|
|
491
|
+
...cache,
|
|
492
|
+
[existingNotification.id]: {
|
|
493
|
+
...existingNotification,
|
|
494
|
+
notifiedAt: newComment.createdAt,
|
|
495
|
+
readAt: newComment.createdAt
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
updateThreadAndNotification(thread, inboxNotification) {
|
|
502
|
+
this._store.batch(() => {
|
|
503
|
+
this.updateThreadsCache((cache) => {
|
|
504
|
+
const existingThread = cache[thread.id];
|
|
505
|
+
return existingThread === void 0 || isMoreRecentlyUpdated(thread, existingThread) ? { ...cache, [thread.id]: thread } : cache;
|
|
506
|
+
});
|
|
507
|
+
if (inboxNotification !== void 0) {
|
|
508
|
+
this.updateInboxNotificationsCache((cache) => ({
|
|
509
|
+
...cache,
|
|
510
|
+
[inboxNotification.id]: inboxNotification
|
|
511
|
+
}));
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
updateThreadsAndNotifications(threads, inboxNotifications, deletedThreads, deletedInboxNotifications, queryKey) {
|
|
516
|
+
this._store.batch(() => {
|
|
517
|
+
this.updateThreadsCache(
|
|
518
|
+
(cache) => applyThreadUpdates(cache, {
|
|
519
|
+
newThreads: threads,
|
|
520
|
+
deletedThreads
|
|
521
|
+
})
|
|
522
|
+
);
|
|
523
|
+
this.updateInboxNotificationsCache(
|
|
524
|
+
(cache) => applyNotificationsUpdates(cache, {
|
|
525
|
+
newInboxNotifications: inboxNotifications,
|
|
526
|
+
deletedNotifications: deletedInboxNotifications
|
|
527
|
+
})
|
|
528
|
+
);
|
|
529
|
+
if (queryKey !== void 0) {
|
|
530
|
+
this.setQueryOK(queryKey);
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Updates existing notification setting for a room with a new value,
|
|
536
|
+
* replacing the corresponding optimistic update.
|
|
537
|
+
*/
|
|
538
|
+
updateRoomInboxNotificationSettings2(roomId, optimisticUpdateId, settings) {
|
|
539
|
+
this._store.batch(() => {
|
|
540
|
+
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
541
|
+
this.setNotificationSettings(roomId, settings);
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
updateRoomInboxNotificationSettings(roomId, settings, queryKey) {
|
|
545
|
+
this._store.batch(() => {
|
|
546
|
+
this.setQueryOK(queryKey);
|
|
547
|
+
this.setNotificationSettings(roomId, settings);
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
updateRoomVersions(roomId, versions, queryKey) {
|
|
551
|
+
this._store.batch(() => {
|
|
552
|
+
this.setVersions(roomId, versions);
|
|
553
|
+
if (queryKey !== void 0) {
|
|
554
|
+
this.setQueryOK(queryKey);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
addOptimisticUpdate(optimisticUpdate) {
|
|
559
|
+
const id = nanoid();
|
|
560
|
+
const newUpdate = { ...optimisticUpdate, id };
|
|
561
|
+
this.updateOptimisticUpdatesCache((cache) => [...cache, newUpdate]);
|
|
562
|
+
return id;
|
|
563
|
+
}
|
|
564
|
+
removeOptimisticUpdate(optimisticUpdateId) {
|
|
565
|
+
this.updateOptimisticUpdatesCache(
|
|
566
|
+
(cache) => cache.filter((ou) => ou.id !== optimisticUpdateId)
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
//
|
|
570
|
+
// Query State APIs
|
|
571
|
+
//
|
|
572
|
+
setQueryLoading(queryKey) {
|
|
573
|
+
this.setQueryState(queryKey, { isLoading: true });
|
|
574
|
+
}
|
|
575
|
+
setQueryOK(queryKey) {
|
|
576
|
+
this.setQueryState(queryKey, { isLoading: false, data: void 0 });
|
|
577
|
+
}
|
|
578
|
+
setQueryError(queryKey, error) {
|
|
579
|
+
this.setQueryState(queryKey, { isLoading: false, error });
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
function applyOptimisticUpdates(state) {
|
|
583
|
+
const result = {
|
|
584
|
+
threads: {
|
|
585
|
+
...state.threads
|
|
586
|
+
},
|
|
587
|
+
inboxNotifications: {
|
|
588
|
+
...state.inboxNotifications
|
|
589
|
+
},
|
|
590
|
+
notificationSettings: {
|
|
591
|
+
...state.notificationSettings
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
for (const optimisticUpdate of state.optimisticUpdates) {
|
|
595
|
+
switch (optimisticUpdate.type) {
|
|
596
|
+
case "create-thread": {
|
|
597
|
+
result.threads[optimisticUpdate.thread.id] = optimisticUpdate.thread;
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
case "edit-thread-metadata": {
|
|
601
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
602
|
+
if (thread === void 0) {
|
|
603
|
+
break;
|
|
604
|
+
}
|
|
605
|
+
if (thread.deletedAt !== void 0) {
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
if (thread.updatedAt !== void 0 && thread.updatedAt > optimisticUpdate.updatedAt) {
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
result.threads[thread.id] = {
|
|
612
|
+
...thread,
|
|
613
|
+
updatedAt: optimisticUpdate.updatedAt,
|
|
614
|
+
metadata: {
|
|
615
|
+
...thread.metadata,
|
|
616
|
+
...optimisticUpdate.metadata
|
|
617
|
+
}
|
|
618
|
+
};
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
case "mark-thread-as-resolved": {
|
|
622
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
623
|
+
if (thread === void 0) {
|
|
624
|
+
break;
|
|
625
|
+
}
|
|
626
|
+
if (thread.deletedAt !== void 0) {
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
result.threads[thread.id] = {
|
|
630
|
+
...thread,
|
|
631
|
+
resolved: true
|
|
632
|
+
};
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
case "mark-thread-as-unresolved": {
|
|
636
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
637
|
+
if (thread === void 0) {
|
|
638
|
+
break;
|
|
639
|
+
}
|
|
640
|
+
if (thread.deletedAt !== void 0) {
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
result.threads[thread.id] = {
|
|
644
|
+
...thread,
|
|
645
|
+
resolved: false
|
|
646
|
+
};
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
case "create-comment": {
|
|
650
|
+
const thread = result.threads[optimisticUpdate.comment.threadId];
|
|
651
|
+
if (thread === void 0) {
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
result.threads[thread.id] = upsertComment(
|
|
655
|
+
thread,
|
|
656
|
+
optimisticUpdate.comment
|
|
657
|
+
);
|
|
658
|
+
const inboxNotification = Object.values(result.inboxNotifications).find(
|
|
659
|
+
(notification) => notification.kind === "thread" && notification.threadId === thread.id
|
|
660
|
+
);
|
|
661
|
+
if (inboxNotification === void 0) {
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
result.inboxNotifications[inboxNotification.id] = {
|
|
665
|
+
...inboxNotification,
|
|
666
|
+
notifiedAt: optimisticUpdate.comment.createdAt,
|
|
667
|
+
readAt: optimisticUpdate.comment.createdAt
|
|
668
|
+
};
|
|
669
|
+
break;
|
|
670
|
+
}
|
|
671
|
+
case "edit-comment": {
|
|
672
|
+
const thread = result.threads[optimisticUpdate.comment.threadId];
|
|
673
|
+
if (thread === void 0) {
|
|
674
|
+
break;
|
|
675
|
+
}
|
|
676
|
+
result.threads[thread.id] = upsertComment(
|
|
677
|
+
thread,
|
|
678
|
+
optimisticUpdate.comment
|
|
679
|
+
);
|
|
680
|
+
break;
|
|
681
|
+
}
|
|
682
|
+
case "delete-comment": {
|
|
683
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
684
|
+
if (thread === void 0) {
|
|
685
|
+
break;
|
|
686
|
+
}
|
|
687
|
+
result.threads[thread.id] = deleteComment(
|
|
688
|
+
thread,
|
|
689
|
+
optimisticUpdate.commentId,
|
|
690
|
+
optimisticUpdate.deletedAt
|
|
691
|
+
);
|
|
692
|
+
break;
|
|
693
|
+
}
|
|
694
|
+
case "delete-thread": {
|
|
695
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
696
|
+
if (thread === void 0) {
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
699
|
+
result.threads[optimisticUpdate.threadId] = {
|
|
700
|
+
...result.threads[optimisticUpdate.threadId],
|
|
701
|
+
deletedAt: optimisticUpdate.deletedAt,
|
|
702
|
+
updatedAt: optimisticUpdate.deletedAt,
|
|
703
|
+
comments: []
|
|
704
|
+
};
|
|
705
|
+
break;
|
|
706
|
+
}
|
|
707
|
+
case "add-reaction": {
|
|
708
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
709
|
+
if (thread === void 0) {
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
result.threads[thread.id] = addReaction(
|
|
713
|
+
thread,
|
|
714
|
+
optimisticUpdate.commentId,
|
|
715
|
+
optimisticUpdate.reaction
|
|
716
|
+
);
|
|
717
|
+
break;
|
|
718
|
+
}
|
|
719
|
+
case "remove-reaction": {
|
|
720
|
+
const thread = result.threads[optimisticUpdate.threadId];
|
|
721
|
+
if (thread === void 0) {
|
|
722
|
+
break;
|
|
723
|
+
}
|
|
724
|
+
result.threads[thread.id] = removeReaction(
|
|
725
|
+
thread,
|
|
726
|
+
optimisticUpdate.commentId,
|
|
727
|
+
optimisticUpdate.emoji,
|
|
728
|
+
optimisticUpdate.userId,
|
|
729
|
+
optimisticUpdate.removedAt
|
|
730
|
+
);
|
|
731
|
+
break;
|
|
732
|
+
}
|
|
733
|
+
case "mark-inbox-notification-as-read": {
|
|
734
|
+
result.inboxNotifications[optimisticUpdate.inboxNotificationId] = {
|
|
735
|
+
...state.inboxNotifications[optimisticUpdate.inboxNotificationId],
|
|
736
|
+
readAt: optimisticUpdate.readAt
|
|
737
|
+
};
|
|
738
|
+
break;
|
|
739
|
+
}
|
|
740
|
+
case "mark-all-inbox-notifications-as-read": {
|
|
741
|
+
for (const id in result.inboxNotifications) {
|
|
742
|
+
result.inboxNotifications[id] = {
|
|
743
|
+
...result.inboxNotifications[id],
|
|
744
|
+
readAt: optimisticUpdate.readAt
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
case "delete-inbox-notification": {
|
|
750
|
+
const {
|
|
751
|
+
[optimisticUpdate.inboxNotificationId]: _,
|
|
752
|
+
...inboxNotifications
|
|
753
|
+
} = result.inboxNotifications;
|
|
754
|
+
result.inboxNotifications = inboxNotifications;
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
case "delete-all-inbox-notifications": {
|
|
758
|
+
result.inboxNotifications = {};
|
|
759
|
+
break;
|
|
760
|
+
}
|
|
761
|
+
case "update-notification-settings": {
|
|
762
|
+
result.notificationSettings[optimisticUpdate.roomId] = {
|
|
763
|
+
...result.notificationSettings[optimisticUpdate.roomId],
|
|
764
|
+
...optimisticUpdate.settings
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return result;
|
|
770
|
+
}
|
|
771
|
+
function applyThreadUpdates(existingThreads, updates) {
|
|
772
|
+
const updatedThreads = { ...existingThreads };
|
|
773
|
+
updates.newThreads.forEach((thread) => {
|
|
774
|
+
const existingThread = updatedThreads[thread.id];
|
|
775
|
+
if (existingThread) {
|
|
776
|
+
if (isMoreRecentlyUpdated(existingThread, thread)) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
updatedThreads[thread.id] = thread;
|
|
781
|
+
});
|
|
782
|
+
updates.deletedThreads.forEach(({ id, deletedAt }) => {
|
|
783
|
+
const existingThread = updatedThreads[id];
|
|
784
|
+
if (existingThread === void 0) return;
|
|
785
|
+
existingThread.deletedAt = deletedAt;
|
|
786
|
+
existingThread.updatedAt = deletedAt;
|
|
787
|
+
existingThread.comments = [];
|
|
788
|
+
});
|
|
789
|
+
return updatedThreads;
|
|
790
|
+
}
|
|
791
|
+
function applyNotificationsUpdates(existingInboxNotifications, updates) {
|
|
792
|
+
const updatedInboxNotifications = { ...existingInboxNotifications };
|
|
793
|
+
updates.newInboxNotifications.forEach((notification) => {
|
|
794
|
+
const existingNotification = updatedInboxNotifications[notification.id];
|
|
795
|
+
if (existingNotification) {
|
|
796
|
+
const result = compareInboxNotifications(
|
|
797
|
+
existingNotification,
|
|
798
|
+
notification
|
|
799
|
+
);
|
|
800
|
+
if (result === 1) return;
|
|
801
|
+
}
|
|
802
|
+
updatedInboxNotifications[notification.id] = notification;
|
|
803
|
+
});
|
|
804
|
+
updates.deletedNotifications.forEach(
|
|
805
|
+
({ id }) => delete updatedInboxNotifications[id]
|
|
806
|
+
);
|
|
807
|
+
return updatedInboxNotifications;
|
|
808
|
+
}
|
|
809
|
+
function compareInboxNotifications(inboxNotificationA, inboxNotificationB) {
|
|
810
|
+
if (inboxNotificationA.notifiedAt > inboxNotificationB.notifiedAt) {
|
|
811
|
+
return 1;
|
|
812
|
+
} else if (inboxNotificationA.notifiedAt < inboxNotificationB.notifiedAt) {
|
|
813
|
+
return -1;
|
|
814
|
+
}
|
|
815
|
+
if (inboxNotificationA.readAt && inboxNotificationB.readAt) {
|
|
816
|
+
return inboxNotificationA.readAt > inboxNotificationB.readAt ? 1 : inboxNotificationA.readAt < inboxNotificationB.readAt ? -1 : 0;
|
|
817
|
+
} else if (inboxNotificationA.readAt || inboxNotificationB.readAt) {
|
|
818
|
+
return inboxNotificationA.readAt ? 1 : -1;
|
|
819
|
+
}
|
|
820
|
+
return 0;
|
|
821
|
+
}
|
|
822
|
+
function upsertComment(thread, comment) {
|
|
823
|
+
if (thread.deletedAt !== void 0) {
|
|
824
|
+
return thread;
|
|
825
|
+
}
|
|
826
|
+
if (comment.threadId !== thread.id) {
|
|
827
|
+
console2.warn(
|
|
828
|
+
`Comment ${comment.id} does not belong to thread ${thread.id}`
|
|
829
|
+
);
|
|
830
|
+
return thread;
|
|
831
|
+
}
|
|
832
|
+
const existingComment = thread.comments.find(
|
|
833
|
+
(existingComment2) => existingComment2.id === comment.id
|
|
834
|
+
);
|
|
835
|
+
if (existingComment === void 0) {
|
|
836
|
+
const updatedAt = new Date(
|
|
837
|
+
Math.max(thread.updatedAt?.getTime() || 0, comment.createdAt.getTime())
|
|
838
|
+
);
|
|
839
|
+
const updatedThread = {
|
|
840
|
+
...thread,
|
|
841
|
+
updatedAt,
|
|
842
|
+
comments: [...thread.comments, comment]
|
|
843
|
+
};
|
|
844
|
+
return updatedThread;
|
|
845
|
+
}
|
|
846
|
+
if (existingComment.deletedAt !== void 0) {
|
|
847
|
+
return thread;
|
|
848
|
+
}
|
|
849
|
+
if (existingComment.editedAt === void 0 || comment.editedAt === void 0 || existingComment.editedAt <= comment.editedAt) {
|
|
850
|
+
const updatedComments = thread.comments.map(
|
|
851
|
+
(existingComment2) => existingComment2.id === comment.id ? comment : existingComment2
|
|
852
|
+
);
|
|
853
|
+
const updatedThread = {
|
|
854
|
+
...thread,
|
|
855
|
+
updatedAt: new Date(
|
|
856
|
+
Math.max(
|
|
857
|
+
thread.updatedAt?.getTime() || 0,
|
|
858
|
+
comment.editedAt?.getTime() || comment.createdAt.getTime()
|
|
859
|
+
)
|
|
860
|
+
),
|
|
861
|
+
comments: updatedComments
|
|
862
|
+
};
|
|
863
|
+
return updatedThread;
|
|
864
|
+
}
|
|
865
|
+
return thread;
|
|
866
|
+
}
|
|
867
|
+
function deleteComment(thread, commentId, deletedAt) {
|
|
868
|
+
if (thread.deletedAt !== void 0) {
|
|
869
|
+
return thread;
|
|
870
|
+
}
|
|
871
|
+
const existingComment = thread.comments.find(
|
|
872
|
+
(comment) => comment.id === commentId
|
|
873
|
+
);
|
|
874
|
+
if (existingComment === void 0) {
|
|
875
|
+
return thread;
|
|
876
|
+
}
|
|
877
|
+
if (existingComment.deletedAt !== void 0) {
|
|
878
|
+
return thread;
|
|
879
|
+
}
|
|
880
|
+
const updatedComments = thread.comments.map(
|
|
881
|
+
(comment) => comment.id === commentId ? {
|
|
882
|
+
...comment,
|
|
883
|
+
deletedAt,
|
|
884
|
+
body: void 0
|
|
885
|
+
} : comment
|
|
886
|
+
);
|
|
887
|
+
if (!updatedComments.some((comment) => comment.deletedAt === void 0)) {
|
|
888
|
+
return {
|
|
889
|
+
...thread,
|
|
890
|
+
deletedAt,
|
|
891
|
+
updatedAt: deletedAt,
|
|
892
|
+
comments: []
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
return {
|
|
896
|
+
...thread,
|
|
897
|
+
updatedAt: deletedAt,
|
|
898
|
+
comments: updatedComments
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
function addReaction(thread, commentId, reaction) {
|
|
902
|
+
if (thread.deletedAt !== void 0) {
|
|
903
|
+
return thread;
|
|
904
|
+
}
|
|
905
|
+
const existingComment = thread.comments.find(
|
|
906
|
+
(comment) => comment.id === commentId
|
|
907
|
+
);
|
|
908
|
+
if (existingComment === void 0) {
|
|
909
|
+
return thread;
|
|
910
|
+
}
|
|
911
|
+
if (existingComment.deletedAt !== void 0) {
|
|
912
|
+
return thread;
|
|
913
|
+
}
|
|
914
|
+
const updatedComments = thread.comments.map(
|
|
915
|
+
(comment) => comment.id === commentId ? {
|
|
916
|
+
...comment,
|
|
917
|
+
reactions: upsertReaction(comment.reactions, reaction)
|
|
918
|
+
} : comment
|
|
919
|
+
);
|
|
920
|
+
return {
|
|
921
|
+
...thread,
|
|
922
|
+
updatedAt: new Date(
|
|
923
|
+
Math.max(reaction.createdAt.getTime(), thread.updatedAt?.getTime() || 0)
|
|
924
|
+
),
|
|
925
|
+
comments: updatedComments
|
|
926
|
+
};
|
|
927
|
+
}
|
|
928
|
+
function removeReaction(thread, commentId, emoji, userId, removedAt) {
|
|
929
|
+
if (thread.deletedAt !== void 0) {
|
|
930
|
+
return thread;
|
|
931
|
+
}
|
|
932
|
+
const existingComment = thread.comments.find(
|
|
933
|
+
(comment) => comment.id === commentId
|
|
934
|
+
);
|
|
935
|
+
if (existingComment === void 0) {
|
|
936
|
+
return thread;
|
|
937
|
+
}
|
|
938
|
+
if (existingComment.deletedAt !== void 0) {
|
|
939
|
+
return thread;
|
|
940
|
+
}
|
|
941
|
+
const updatedComments = thread.comments.map(
|
|
942
|
+
(comment) => comment.id === commentId ? {
|
|
943
|
+
...comment,
|
|
944
|
+
reactions: comment.reactions.map(
|
|
945
|
+
(reaction) => reaction.emoji === emoji ? {
|
|
946
|
+
...reaction,
|
|
947
|
+
users: reaction.users.filter((user) => user.id !== userId)
|
|
948
|
+
} : reaction
|
|
949
|
+
).filter((reaction) => reaction.users.length > 0)
|
|
950
|
+
// Remove reactions with no users left
|
|
951
|
+
} : comment
|
|
952
|
+
);
|
|
953
|
+
return {
|
|
954
|
+
...thread,
|
|
955
|
+
updatedAt: new Date(
|
|
956
|
+
Math.max(removedAt.getTime(), thread.updatedAt?.getTime() || 0)
|
|
957
|
+
),
|
|
958
|
+
comments: updatedComments
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
function upsertReaction(reactions, reaction) {
|
|
962
|
+
const existingReaction = reactions.find(
|
|
963
|
+
(existingReaction2) => existingReaction2.emoji === reaction.emoji
|
|
964
|
+
);
|
|
965
|
+
if (existingReaction === void 0) {
|
|
966
|
+
return [
|
|
967
|
+
...reactions,
|
|
968
|
+
{
|
|
969
|
+
emoji: reaction.emoji,
|
|
970
|
+
createdAt: reaction.createdAt,
|
|
971
|
+
users: [{ id: reaction.userId }]
|
|
972
|
+
}
|
|
973
|
+
];
|
|
974
|
+
}
|
|
975
|
+
if (existingReaction.users.some((user) => user.id === reaction.userId) === false) {
|
|
976
|
+
return reactions.map(
|
|
977
|
+
(existingReaction2) => existingReaction2.emoji === reaction.emoji ? {
|
|
978
|
+
...existingReaction2,
|
|
979
|
+
users: [...existingReaction2.users, { id: reaction.userId }]
|
|
980
|
+
} : existingReaction2
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
return reactions;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// src/liveblocks.tsx
|
|
323
987
|
var ClientContext = createContext(null);
|
|
324
988
|
function missingUserError(userId) {
|
|
325
989
|
return new Error(`resolveUsers didn't return anything for user '${userId}'`);
|
|
@@ -329,6 +993,7 @@ function missingRoomInfoError(roomId) {
|
|
|
329
993
|
`resolveRoomsInfo didn't return anything for room '${roomId}'`
|
|
330
994
|
);
|
|
331
995
|
}
|
|
996
|
+
var _umbrellaStores = /* @__PURE__ */ new WeakMap();
|
|
332
997
|
var _extras = /* @__PURE__ */ new WeakMap();
|
|
333
998
|
var _bundles = /* @__PURE__ */ new WeakMap();
|
|
334
999
|
var POLLING_INTERVAL = 60 * 1e3;
|
|
@@ -348,32 +1013,24 @@ function selectorFor_useInboxNotifications(state) {
|
|
|
348
1013
|
};
|
|
349
1014
|
}
|
|
350
1015
|
return {
|
|
351
|
-
inboxNotifications:
|
|
1016
|
+
inboxNotifications: selectInboxNotifications(state),
|
|
352
1017
|
isLoading: false
|
|
353
1018
|
};
|
|
354
1019
|
}
|
|
355
|
-
function
|
|
356
|
-
const
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
return {
|
|
364
|
-
threads: [],
|
|
365
|
-
error: query.error,
|
|
366
|
-
isLoading: false
|
|
367
|
-
};
|
|
1020
|
+
function selectUserThreads(state, options) {
|
|
1021
|
+
const result = applyOptimisticUpdates(state);
|
|
1022
|
+
let threads = Object.values(result.threads).filter(
|
|
1023
|
+
(thread) => !thread.deletedAt
|
|
1024
|
+
);
|
|
1025
|
+
const query = options.query;
|
|
1026
|
+
if (query) {
|
|
1027
|
+
threads = threads.filter(makeThreadsFilter(query));
|
|
368
1028
|
}
|
|
369
|
-
return
|
|
370
|
-
threads: selectedUserThreads(state),
|
|
371
|
-
isLoading: false
|
|
372
|
-
};
|
|
1029
|
+
return threads.sort(byMostRecentlyUpdated);
|
|
373
1030
|
}
|
|
374
1031
|
function selectUnreadInboxNotificationsCount(state) {
|
|
375
1032
|
let count = 0;
|
|
376
|
-
for (const notification of
|
|
1033
|
+
for (const notification of selectInboxNotifications(state)) {
|
|
377
1034
|
if (notification.readAt === null || notification.readAt < notification.notifiedAt) {
|
|
378
1035
|
count++;
|
|
379
1036
|
}
|
|
@@ -434,6 +1091,13 @@ function selectorFor_useRoomInfo(state, roomId) {
|
|
|
434
1091
|
info: state.data
|
|
435
1092
|
};
|
|
436
1093
|
}
|
|
1094
|
+
function selectInboxNotifications(state) {
|
|
1095
|
+
const result = applyOptimisticUpdates(state);
|
|
1096
|
+
return Object.values(result.inboxNotifications).sort(
|
|
1097
|
+
// Sort so that the most recent notifications are first
|
|
1098
|
+
(a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime()
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
437
1101
|
function getOrCreateContextBundle(client) {
|
|
438
1102
|
let bundle = _bundles.get(client);
|
|
439
1103
|
if (!bundle) {
|
|
@@ -442,6 +1106,14 @@ function getOrCreateContextBundle(client) {
|
|
|
442
1106
|
}
|
|
443
1107
|
return bundle;
|
|
444
1108
|
}
|
|
1109
|
+
function getUmbrellaStoreForClient(client) {
|
|
1110
|
+
let store = _umbrellaStores.get(client);
|
|
1111
|
+
if (!store) {
|
|
1112
|
+
store = new UmbrellaStore();
|
|
1113
|
+
_umbrellaStores.set(client, store);
|
|
1114
|
+
}
|
|
1115
|
+
return store;
|
|
1116
|
+
}
|
|
445
1117
|
function getExtrasForClient(client) {
|
|
446
1118
|
let extras = _extras.get(client);
|
|
447
1119
|
if (!extras) {
|
|
@@ -451,8 +1123,7 @@ function getExtrasForClient(client) {
|
|
|
451
1123
|
return extras;
|
|
452
1124
|
}
|
|
453
1125
|
function makeExtrasForClient(client) {
|
|
454
|
-
const
|
|
455
|
-
const store = internals.cacheStore;
|
|
1126
|
+
const store = getUmbrellaStoreForClient(client);
|
|
456
1127
|
let lastRequestedAt;
|
|
457
1128
|
async function fetchInboxNotifications() {
|
|
458
1129
|
if (lastRequestedAt === void 0) {
|
|
@@ -491,9 +1162,7 @@ function makeExtrasForClient(client) {
|
|
|
491
1162
|
}
|
|
492
1163
|
});
|
|
493
1164
|
const waitUntilInboxNotificationsLoaded = memoizeOnSuccess(async () => {
|
|
494
|
-
store.
|
|
495
|
-
isLoading: true
|
|
496
|
-
});
|
|
1165
|
+
store.setQueryLoading(INBOX_NOTIFICATIONS_QUERY);
|
|
497
1166
|
try {
|
|
498
1167
|
await autoRetry(
|
|
499
1168
|
() => fetchInboxNotifications(),
|
|
@@ -501,10 +1170,7 @@ function makeExtrasForClient(client) {
|
|
|
501
1170
|
[5e3, 5e3, 1e4, 15e3]
|
|
502
1171
|
);
|
|
503
1172
|
} catch (err) {
|
|
504
|
-
store.
|
|
505
|
-
isLoading: false,
|
|
506
|
-
error: err
|
|
507
|
-
});
|
|
1173
|
+
store.setQueryError(INBOX_NOTIFICATIONS_QUERY, err);
|
|
508
1174
|
throw err;
|
|
509
1175
|
}
|
|
510
1176
|
});
|
|
@@ -530,87 +1196,94 @@ function makeExtrasForClient(client) {
|
|
|
530
1196
|
};
|
|
531
1197
|
}, []);
|
|
532
1198
|
}
|
|
533
|
-
|
|
534
|
-
|
|
1199
|
+
const userThreadsPoller = makePoller(refreshUserThreads);
|
|
1200
|
+
let isFetchingUserThreadsUpdates = false;
|
|
1201
|
+
async function refreshUserThreads() {
|
|
1202
|
+
const since = userThreadslastRequestedAt;
|
|
1203
|
+
if (since === void 0 || isFetchingUserThreadsUpdates) {
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
535
1206
|
try {
|
|
536
|
-
|
|
537
|
-
await
|
|
1207
|
+
isFetchingUserThreadsUpdates = true;
|
|
1208
|
+
const updates = await client[kInternal].getThreadsSince({
|
|
1209
|
+
since
|
|
1210
|
+
});
|
|
1211
|
+
isFetchingUserThreadsUpdates = false;
|
|
1212
|
+
store.updateThreadsAndNotifications(
|
|
1213
|
+
updates.threads.updated,
|
|
1214
|
+
[],
|
|
1215
|
+
updates.threads.deleted,
|
|
1216
|
+
[],
|
|
1217
|
+
USER_THREADS_QUERY
|
|
1218
|
+
);
|
|
1219
|
+
userThreadslastRequestedAt = updates.requestedAt;
|
|
538
1220
|
} catch (err) {
|
|
539
|
-
|
|
1221
|
+
isFetchingUserThreadsUpdates = false;
|
|
1222
|
+
return;
|
|
540
1223
|
}
|
|
541
|
-
});
|
|
542
|
-
let userThreadslastRequestedAt;
|
|
543
|
-
function loadUserThreads() {
|
|
544
|
-
void waitUntilUserThreadsLoaded().catch(() => {
|
|
545
|
-
});
|
|
546
1224
|
}
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
1225
|
+
const userThreadsSubscribersByQuery = /* @__PURE__ */ new Map();
|
|
1226
|
+
const userThreadsRequestsByQuery = /* @__PURE__ */ new Map();
|
|
1227
|
+
function incrementUserThreadsQuerySubscribers(queryKey) {
|
|
1228
|
+
const subscribers = userThreadsSubscribersByQuery.get(queryKey) ?? 0;
|
|
1229
|
+
userThreadsSubscribersByQuery.set(queryKey, subscribers + 1);
|
|
1230
|
+
userThreadsPoller.start(POLLING_INTERVAL);
|
|
1231
|
+
return () => {
|
|
1232
|
+
const subscribers2 = userThreadsSubscribersByQuery.get(queryKey);
|
|
1233
|
+
if (subscribers2 === void 0 || subscribers2 <= 0) {
|
|
1234
|
+
console.warn(
|
|
1235
|
+
`Internal unexpected behavior. Cannot decrease subscriber count for query "${queryKey}"`
|
|
1236
|
+
);
|
|
1237
|
+
return;
|
|
1238
|
+
}
|
|
1239
|
+
userThreadsSubscribersByQuery.set(queryKey, subscribers2 - 1);
|
|
1240
|
+
let totalSubscribers = 0;
|
|
1241
|
+
for (const subscribers3 of userThreadsSubscribersByQuery.values()) {
|
|
1242
|
+
totalSubscribers += subscribers3;
|
|
1243
|
+
}
|
|
1244
|
+
if (totalSubscribers <= 0) {
|
|
1245
|
+
userThreadsPoller.stop();
|
|
1246
|
+
}
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
let userThreadslastRequestedAt;
|
|
1250
|
+
async function getUserThreads(queryKey, options, { retryCount } = { retryCount: 0 }) {
|
|
1251
|
+
const existingRequest = userThreadsRequestsByQuery.get(queryKey);
|
|
1252
|
+
if (existingRequest !== void 0) return existingRequest;
|
|
1253
|
+
const request = client[kInternal].getThreads(options);
|
|
1254
|
+
userThreadsRequestsByQuery.set(queryKey, request);
|
|
1255
|
+
store.setQueryLoading(queryKey);
|
|
551
1256
|
try {
|
|
552
|
-
|
|
553
|
-
} catch (err) {
|
|
554
|
-
store.setQueryState(USER_THREADS_QUERY, {
|
|
555
|
-
isLoading: false,
|
|
556
|
-
error: err
|
|
557
|
-
});
|
|
558
|
-
throw err;
|
|
559
|
-
}
|
|
560
|
-
});
|
|
561
|
-
async function fetchUserThreads() {
|
|
562
|
-
if (userThreadslastRequestedAt === void 0) {
|
|
563
|
-
const result = await client[kInternal].getThreads();
|
|
1257
|
+
const result = await request;
|
|
564
1258
|
store.updateThreadsAndNotifications(
|
|
565
1259
|
result.threads,
|
|
566
1260
|
result.inboxNotifications,
|
|
567
1261
|
[],
|
|
568
1262
|
[],
|
|
569
|
-
|
|
570
|
-
);
|
|
571
|
-
userThreadslastRequestedAt = result.requestedAt;
|
|
572
|
-
} else {
|
|
573
|
-
const result = await client[kInternal].getThreadsSince({
|
|
574
|
-
since: userThreadslastRequestedAt
|
|
575
|
-
});
|
|
576
|
-
store.updateThreadsAndNotifications(
|
|
577
|
-
result.threads.updated,
|
|
578
|
-
result.inboxNotifications.updated,
|
|
579
|
-
result.threads.deleted,
|
|
580
|
-
result.inboxNotifications.deleted,
|
|
581
|
-
USER_THREADS_QUERY
|
|
1263
|
+
queryKey
|
|
582
1264
|
);
|
|
583
|
-
if (userThreadslastRequestedAt < result.requestedAt) {
|
|
1265
|
+
if (userThreadslastRequestedAt === void 0 || userThreadslastRequestedAt < result.requestedAt) {
|
|
584
1266
|
userThreadslastRequestedAt = result.requestedAt;
|
|
585
1267
|
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
function useEnableUserThreadsPolling() {
|
|
589
|
-
useEffect3(() => {
|
|
590
|
-
userThreadsPollerSubscribers++;
|
|
591
1268
|
userThreadsPoller.start(POLLING_INTERVAL);
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
};
|
|
604
|
-
}, []);
|
|
1269
|
+
} catch (err) {
|
|
1270
|
+
userThreadsRequestsByQuery.delete(queryKey);
|
|
1271
|
+
retryError(() => {
|
|
1272
|
+
void getUserThreads(queryKey, options, {
|
|
1273
|
+
retryCount: retryCount + 1
|
|
1274
|
+
});
|
|
1275
|
+
}, retryCount);
|
|
1276
|
+
store.setQueryError(queryKey, err);
|
|
1277
|
+
}
|
|
1278
|
+
return;
|
|
605
1279
|
}
|
|
606
1280
|
return {
|
|
607
1281
|
store,
|
|
608
1282
|
useEnableInboxNotificationsPolling,
|
|
609
1283
|
waitUntilInboxNotificationsLoaded,
|
|
610
1284
|
loadInboxNotifications,
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
loadUserThreads
|
|
1285
|
+
incrementUserThreadsQuerySubscribers,
|
|
1286
|
+
getUserThreads
|
|
614
1287
|
};
|
|
615
1288
|
}
|
|
616
1289
|
function makeLiveblocksContextBundle(client) {
|
|
@@ -633,7 +1306,7 @@ function makeLiveblocksContextBundle(client) {
|
|
|
633
1306
|
useDeleteInboxNotification: useDeleteInboxNotification2,
|
|
634
1307
|
useDeleteAllInboxNotifications: useDeleteAllInboxNotifications2,
|
|
635
1308
|
useInboxNotificationThread: useInboxNotificationThread2,
|
|
636
|
-
useUserThreads_experimental
|
|
1309
|
+
useUserThreads_experimental,
|
|
637
1310
|
...shared.classic,
|
|
638
1311
|
suspense: {
|
|
639
1312
|
LiveblocksProvider: LiveblocksProvider2,
|
|
@@ -644,34 +1317,12 @@ function makeLiveblocksContextBundle(client) {
|
|
|
644
1317
|
useDeleteInboxNotification: useDeleteInboxNotification2,
|
|
645
1318
|
useDeleteAllInboxNotifications: useDeleteAllInboxNotifications2,
|
|
646
1319
|
useInboxNotificationThread: useInboxNotificationThread2,
|
|
647
|
-
useUserThreads_experimental:
|
|
1320
|
+
useUserThreads_experimental: useUserThreadsSuspense_experimental,
|
|
648
1321
|
...shared.suspense
|
|
649
1322
|
}
|
|
650
1323
|
};
|
|
651
1324
|
return bundle;
|
|
652
1325
|
}
|
|
653
|
-
function useUserThreads_withClient(client) {
|
|
654
|
-
const { loadUserThreads, store, useEnableUserThreadsPolling } = getExtrasForClient(client);
|
|
655
|
-
useEffect3(() => {
|
|
656
|
-
loadUserThreads();
|
|
657
|
-
}, [loadUserThreads]);
|
|
658
|
-
useEnableUserThreadsPolling();
|
|
659
|
-
return useSyncExternalStoreWithSelector(
|
|
660
|
-
store.subscribe,
|
|
661
|
-
store.get,
|
|
662
|
-
store.get,
|
|
663
|
-
selectorFor_useUserThreads,
|
|
664
|
-
shallow
|
|
665
|
-
);
|
|
666
|
-
}
|
|
667
|
-
function useUserThreadsSuspense_withClient(client) {
|
|
668
|
-
const { waitUntilUserThreadsLoaded } = getExtrasForClient(client);
|
|
669
|
-
use(waitUntilUserThreadsLoaded());
|
|
670
|
-
const result = useUserThreads_withClient(client);
|
|
671
|
-
assert(!result.error, "Did not expect error");
|
|
672
|
-
assert(!result.isLoading, "Did not expect loading");
|
|
673
|
-
return result;
|
|
674
|
-
}
|
|
675
1326
|
function useInboxNotifications_withClient(client) {
|
|
676
1327
|
const { loadInboxNotifications, store, useEnableInboxNotificationsPolling } = getExtrasForClient(client);
|
|
677
1328
|
useEffect3(() => {
|
|
@@ -720,48 +1371,22 @@ function useMarkInboxNotificationAsRead_withClient(client) {
|
|
|
720
1371
|
return useCallback2(
|
|
721
1372
|
(inboxNotificationId) => {
|
|
722
1373
|
const { store } = getExtrasForClient(client);
|
|
723
|
-
const optimisticUpdateId = nanoid();
|
|
724
1374
|
const readAt = /* @__PURE__ */ new Date();
|
|
725
|
-
store.
|
|
1375
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
726
1376
|
type: "mark-inbox-notification-as-read",
|
|
727
|
-
id: optimisticUpdateId,
|
|
728
1377
|
inboxNotificationId,
|
|
729
1378
|
readAt
|
|
730
1379
|
});
|
|
731
1380
|
client.markInboxNotificationAsRead(inboxNotificationId).then(
|
|
732
1381
|
() => {
|
|
733
|
-
store.
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
739
|
-
(update) => update.id !== optimisticUpdateId
|
|
740
|
-
)
|
|
741
|
-
};
|
|
742
|
-
}
|
|
743
|
-
return {
|
|
744
|
-
...state,
|
|
745
|
-
inboxNotifications: {
|
|
746
|
-
...state.inboxNotifications,
|
|
747
|
-
[inboxNotificationId]: {
|
|
748
|
-
...existingNotification,
|
|
749
|
-
readAt
|
|
750
|
-
}
|
|
751
|
-
},
|
|
752
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
753
|
-
(update) => update.id !== optimisticUpdateId
|
|
754
|
-
)
|
|
755
|
-
};
|
|
756
|
-
});
|
|
1382
|
+
store.updateInboxNotification(
|
|
1383
|
+
inboxNotificationId,
|
|
1384
|
+
optimisticUpdateId,
|
|
1385
|
+
(inboxNotification) => ({ ...inboxNotification, readAt })
|
|
1386
|
+
);
|
|
757
1387
|
},
|
|
758
1388
|
() => {
|
|
759
|
-
store.
|
|
760
|
-
...state,
|
|
761
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
762
|
-
(update) => update.id !== optimisticUpdateId
|
|
763
|
-
)
|
|
764
|
-
}));
|
|
1389
|
+
store.removeOptimisticUpdate(optimisticUpdateId);
|
|
765
1390
|
}
|
|
766
1391
|
);
|
|
767
1392
|
},
|
|
@@ -771,37 +1396,20 @@ function useMarkInboxNotificationAsRead_withClient(client) {
|
|
|
771
1396
|
function useMarkAllInboxNotificationsAsRead_withClient(client) {
|
|
772
1397
|
return useCallback2(() => {
|
|
773
1398
|
const { store } = getExtrasForClient(client);
|
|
774
|
-
const optimisticUpdateId = nanoid();
|
|
775
1399
|
const readAt = /* @__PURE__ */ new Date();
|
|
776
|
-
store.
|
|
1400
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
777
1401
|
type: "mark-all-inbox-notifications-as-read",
|
|
778
|
-
id: optimisticUpdateId,
|
|
779
1402
|
readAt
|
|
780
1403
|
});
|
|
781
1404
|
client.markAllInboxNotificationsAsRead().then(
|
|
782
1405
|
() => {
|
|
783
|
-
store.
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
([id, inboxNotification]) => [
|
|
788
|
-
id,
|
|
789
|
-
{ ...inboxNotification, readAt }
|
|
790
|
-
]
|
|
791
|
-
)
|
|
792
|
-
),
|
|
793
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
794
|
-
(update) => update.id !== optimisticUpdateId
|
|
795
|
-
)
|
|
796
|
-
}));
|
|
1406
|
+
store.updateAllInboxNotifications(
|
|
1407
|
+
optimisticUpdateId,
|
|
1408
|
+
(inboxNotification) => ({ ...inboxNotification, readAt })
|
|
1409
|
+
);
|
|
797
1410
|
},
|
|
798
1411
|
() => {
|
|
799
|
-
store.
|
|
800
|
-
...state,
|
|
801
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
802
|
-
(update) => update.id !== optimisticUpdateId
|
|
803
|
-
)
|
|
804
|
-
}));
|
|
1412
|
+
store.removeOptimisticUpdate(optimisticUpdateId);
|
|
805
1413
|
}
|
|
806
1414
|
);
|
|
807
1415
|
}, [client]);
|
|
@@ -810,43 +1418,21 @@ function useDeleteInboxNotification_withClient(client) {
|
|
|
810
1418
|
return useCallback2(
|
|
811
1419
|
(inboxNotificationId) => {
|
|
812
1420
|
const { store } = getExtrasForClient(client);
|
|
813
|
-
const optimisticUpdateId = nanoid();
|
|
814
1421
|
const deletedAt = /* @__PURE__ */ new Date();
|
|
815
|
-
store.
|
|
1422
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
816
1423
|
type: "delete-inbox-notification",
|
|
817
|
-
id: optimisticUpdateId,
|
|
818
1424
|
inboxNotificationId,
|
|
819
1425
|
deletedAt
|
|
820
1426
|
});
|
|
821
1427
|
client.deleteInboxNotification(inboxNotificationId).then(
|
|
822
1428
|
() => {
|
|
823
|
-
store.
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
...state,
|
|
828
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
829
|
-
(update) => update.id !== optimisticUpdateId
|
|
830
|
-
)
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
|
-
const { [inboxNotificationId]: _, ...inboxNotifications } = state.inboxNotifications;
|
|
834
|
-
return {
|
|
835
|
-
...state,
|
|
836
|
-
inboxNotifications,
|
|
837
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
838
|
-
(update) => update.id !== optimisticUpdateId
|
|
839
|
-
)
|
|
840
|
-
};
|
|
841
|
-
});
|
|
1429
|
+
store.deleteInboxNotification(
|
|
1430
|
+
inboxNotificationId,
|
|
1431
|
+
optimisticUpdateId
|
|
1432
|
+
);
|
|
842
1433
|
},
|
|
843
1434
|
() => {
|
|
844
|
-
store.
|
|
845
|
-
...state,
|
|
846
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
847
|
-
(update) => update.id !== optimisticUpdateId
|
|
848
|
-
)
|
|
849
|
-
}));
|
|
1435
|
+
store.removeOptimisticUpdate(optimisticUpdateId);
|
|
850
1436
|
}
|
|
851
1437
|
);
|
|
852
1438
|
},
|
|
@@ -856,30 +1442,17 @@ function useDeleteInboxNotification_withClient(client) {
|
|
|
856
1442
|
function useDeleteAllInboxNotifications_withClient(client) {
|
|
857
1443
|
return useCallback2(() => {
|
|
858
1444
|
const { store } = getExtrasForClient(client);
|
|
859
|
-
const optimisticUpdateId = nanoid();
|
|
860
1445
|
const deletedAt = /* @__PURE__ */ new Date();
|
|
861
|
-
store.
|
|
1446
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
862
1447
|
type: "delete-all-inbox-notifications",
|
|
863
|
-
id: optimisticUpdateId,
|
|
864
1448
|
deletedAt
|
|
865
1449
|
});
|
|
866
1450
|
client.deleteAllInboxNotifications().then(
|
|
867
1451
|
() => {
|
|
868
|
-
store.
|
|
869
|
-
...state,
|
|
870
|
-
inboxNotifications: {},
|
|
871
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
872
|
-
(update) => update.id !== optimisticUpdateId
|
|
873
|
-
)
|
|
874
|
-
}));
|
|
1452
|
+
store.deleteAllInboxNotifications(optimisticUpdateId);
|
|
875
1453
|
},
|
|
876
1454
|
() => {
|
|
877
|
-
store.
|
|
878
|
-
...state,
|
|
879
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
880
|
-
(update) => update.id !== optimisticUpdateId
|
|
881
|
-
)
|
|
882
|
-
}));
|
|
1455
|
+
store.removeOptimisticUpdate(optimisticUpdateId);
|
|
883
1456
|
}
|
|
884
1457
|
);
|
|
885
1458
|
}, [client]);
|
|
@@ -1077,11 +1650,89 @@ function LiveblocksProvider(props) {
|
|
|
1077
1650
|
function createLiveblocksContext(client) {
|
|
1078
1651
|
return getOrCreateContextBundle(client);
|
|
1079
1652
|
}
|
|
1080
|
-
function useUserThreads_experimental(
|
|
1081
|
-
|
|
1653
|
+
function useUserThreads_experimental(options = {
|
|
1654
|
+
query: {
|
|
1655
|
+
metadata: {}
|
|
1656
|
+
}
|
|
1657
|
+
}) {
|
|
1658
|
+
const queryKey = React2.useMemo(
|
|
1659
|
+
() => makeUserThreadsQueryKey(options.query),
|
|
1660
|
+
[options]
|
|
1661
|
+
);
|
|
1662
|
+
const client = useClient();
|
|
1663
|
+
const { store, incrementUserThreadsQuerySubscribers, getUserThreads } = getExtrasForClient(client);
|
|
1664
|
+
useEffect3(() => {
|
|
1665
|
+
void getUserThreads(queryKey, options);
|
|
1666
|
+
return incrementUserThreadsQuerySubscribers(queryKey);
|
|
1667
|
+
}, [queryKey, incrementUserThreadsQuerySubscribers, getUserThreads, options]);
|
|
1668
|
+
const selector = useCallback2(
|
|
1669
|
+
(state) => {
|
|
1670
|
+
const query = state.queries[queryKey];
|
|
1671
|
+
if (query === void 0 || query.isLoading) {
|
|
1672
|
+
return {
|
|
1673
|
+
isLoading: true
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1676
|
+
if (query.error !== void 0) {
|
|
1677
|
+
return {
|
|
1678
|
+
threads: [],
|
|
1679
|
+
error: query.error,
|
|
1680
|
+
isLoading: false
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
return {
|
|
1684
|
+
threads: selectUserThreads(state, options),
|
|
1685
|
+
isLoading: false
|
|
1686
|
+
};
|
|
1687
|
+
},
|
|
1688
|
+
[queryKey, options]
|
|
1689
|
+
);
|
|
1690
|
+
return useSyncExternalStoreWithSelector(
|
|
1691
|
+
store.subscribe,
|
|
1692
|
+
store.get,
|
|
1693
|
+
store.get,
|
|
1694
|
+
selector,
|
|
1695
|
+
shallow
|
|
1696
|
+
);
|
|
1082
1697
|
}
|
|
1083
|
-
function useUserThreadsSuspense_experimental(
|
|
1084
|
-
|
|
1698
|
+
function useUserThreadsSuspense_experimental(options = {
|
|
1699
|
+
query: {
|
|
1700
|
+
metadata: {}
|
|
1701
|
+
}
|
|
1702
|
+
}) {
|
|
1703
|
+
const queryKey = React2.useMemo(
|
|
1704
|
+
() => makeUserThreadsQueryKey(options.query),
|
|
1705
|
+
[options]
|
|
1706
|
+
);
|
|
1707
|
+
const client = useClient();
|
|
1708
|
+
const { store, getUserThreads } = getExtrasForClient(client);
|
|
1709
|
+
React2.useEffect(() => {
|
|
1710
|
+
const { incrementUserThreadsQuerySubscribers } = getExtrasForClient(client);
|
|
1711
|
+
return incrementUserThreadsQuerySubscribers(queryKey);
|
|
1712
|
+
}, [client, queryKey]);
|
|
1713
|
+
const query = store.get().queries[queryKey];
|
|
1714
|
+
if (query === void 0 || query.isLoading) {
|
|
1715
|
+
throw getUserThreads(queryKey, options);
|
|
1716
|
+
}
|
|
1717
|
+
if (query.error) {
|
|
1718
|
+
throw query.error;
|
|
1719
|
+
}
|
|
1720
|
+
const selector = useCallback2(
|
|
1721
|
+
(state) => {
|
|
1722
|
+
return {
|
|
1723
|
+
threads: selectUserThreads(state, options),
|
|
1724
|
+
isLoading: false
|
|
1725
|
+
};
|
|
1726
|
+
},
|
|
1727
|
+
[options]
|
|
1728
|
+
);
|
|
1729
|
+
return useSyncExternalStoreWithSelector(
|
|
1730
|
+
store.subscribe,
|
|
1731
|
+
store.get,
|
|
1732
|
+
store.get,
|
|
1733
|
+
selector,
|
|
1734
|
+
shallow
|
|
1735
|
+
);
|
|
1085
1736
|
}
|
|
1086
1737
|
function useInboxNotifications() {
|
|
1087
1738
|
return useInboxNotifications_withClient(useClient());
|
|
@@ -1132,6 +1783,7 @@ var _useUser = useUser;
|
|
|
1132
1783
|
var _useUserSuspense = useUserSuspense;
|
|
1133
1784
|
var _useUserThreads_experimental = useUserThreads_experimental;
|
|
1134
1785
|
var _useUserThreadsSuspense_experimental = useUserThreadsSuspense_experimental;
|
|
1786
|
+
var makeUserThreadsQueryKey = (options) => `${USER_THREADS_QUERY}:${stringify(options)}`;
|
|
1135
1787
|
|
|
1136
1788
|
// src/use-scroll-to-comment-on-load-effect.ts
|
|
1137
1789
|
import * as React3 from "react";
|
|
@@ -1196,6 +1848,22 @@ function alwaysNull() {
|
|
|
1196
1848
|
function selectorFor_useOthersConnectionIds(others) {
|
|
1197
1849
|
return others.map((user) => user.connectionId);
|
|
1198
1850
|
}
|
|
1851
|
+
function selectRoomThreads(roomId, state, options) {
|
|
1852
|
+
const result = applyOptimisticUpdates(state);
|
|
1853
|
+
let threads = Object.values(result.threads).filter(
|
|
1854
|
+
(thread) => !thread.deletedAt
|
|
1855
|
+
);
|
|
1856
|
+
threads = threads.filter((thread) => thread.roomId === roomId);
|
|
1857
|
+
const query = options.query;
|
|
1858
|
+
if (query) {
|
|
1859
|
+
threads = threads.filter(makeThreadsFilter(query));
|
|
1860
|
+
}
|
|
1861
|
+
return threads.sort(byFirstCreated);
|
|
1862
|
+
}
|
|
1863
|
+
function selectNotificationSettings(roomId, state) {
|
|
1864
|
+
const { notificationSettings } = applyOptimisticUpdates(state);
|
|
1865
|
+
return nn(notificationSettings[roomId]);
|
|
1866
|
+
}
|
|
1199
1867
|
function makeMutationContext(room) {
|
|
1200
1868
|
const cannotUseUntil = "This mutation cannot be used until";
|
|
1201
1869
|
const needsPresence = `${cannotUseUntil} connected to the Liveblocks room`;
|
|
@@ -1237,7 +1905,7 @@ function handleApiError(err) {
|
|
|
1237
1905
|
const message = `Request failed with status ${err.status}: ${err.message}`;
|
|
1238
1906
|
if (err.details?.error === "FORBIDDEN") {
|
|
1239
1907
|
const detailedMessage = [message, err.details.suggestion, err.details.docs].filter(Boolean).join("\n");
|
|
1240
|
-
|
|
1908
|
+
console3.error(detailedMessage);
|
|
1241
1909
|
}
|
|
1242
1910
|
return new Error(message);
|
|
1243
1911
|
}
|
|
@@ -1260,7 +1928,7 @@ function getExtrasForClient2(client) {
|
|
|
1260
1928
|
return extras;
|
|
1261
1929
|
}
|
|
1262
1930
|
function makeExtrasForClient2(client) {
|
|
1263
|
-
const store = client
|
|
1931
|
+
const store = getUmbrellaStoreForClient(client);
|
|
1264
1932
|
const DEFAULT_DEDUPING_INTERVAL = 2e3;
|
|
1265
1933
|
const lastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
1266
1934
|
const requestsByQuery = /* @__PURE__ */ new Map();
|
|
@@ -1283,7 +1951,7 @@ function makeExtrasForClient2(client) {
|
|
|
1283
1951
|
return () => {
|
|
1284
1952
|
const subscribers2 = subscribersByQuery.get(queryKey);
|
|
1285
1953
|
if (subscribers2 === void 0 || subscribers2 <= 0) {
|
|
1286
|
-
|
|
1954
|
+
console3.warn(
|
|
1287
1955
|
`Internal unexpected behavior. Cannot decrease subscriber count for query "${queryKey}"`
|
|
1288
1956
|
);
|
|
1289
1957
|
return;
|
|
@@ -1329,9 +1997,7 @@ function makeExtrasForClient2(client) {
|
|
|
1329
1997
|
if (existingRequest !== void 0) return existingRequest;
|
|
1330
1998
|
const request = room[kInternal2].listTextVersions();
|
|
1331
1999
|
requestsByQuery.set(queryKey, request);
|
|
1332
|
-
store.
|
|
1333
|
-
isLoading: true
|
|
1334
|
-
});
|
|
2000
|
+
store.setQueryLoading(queryKey);
|
|
1335
2001
|
try {
|
|
1336
2002
|
const result = await request;
|
|
1337
2003
|
const data = await result.json();
|
|
@@ -1350,10 +2016,7 @@ function makeExtrasForClient2(client) {
|
|
|
1350
2016
|
retryCount: retryCount + 1
|
|
1351
2017
|
});
|
|
1352
2018
|
}, retryCount);
|
|
1353
|
-
store.
|
|
1354
|
-
isLoading: false,
|
|
1355
|
-
error: err
|
|
1356
|
-
});
|
|
2019
|
+
store.setQueryError(queryKey, err);
|
|
1357
2020
|
}
|
|
1358
2021
|
return;
|
|
1359
2022
|
}
|
|
@@ -1362,9 +2025,7 @@ function makeExtrasForClient2(client) {
|
|
|
1362
2025
|
if (existingRequest !== void 0) return existingRequest;
|
|
1363
2026
|
const request = room.getThreads(options);
|
|
1364
2027
|
requestsByQuery.set(queryKey, request);
|
|
1365
|
-
store.
|
|
1366
|
-
isLoading: true
|
|
1367
|
-
});
|
|
2028
|
+
store.setQueryLoading(queryKey);
|
|
1368
2029
|
try {
|
|
1369
2030
|
const result = await request;
|
|
1370
2031
|
store.updateThreadsAndNotifications(
|
|
@@ -1387,10 +2048,7 @@ function makeExtrasForClient2(client) {
|
|
|
1387
2048
|
retryCount: retryCount + 1
|
|
1388
2049
|
});
|
|
1389
2050
|
}, retryCount);
|
|
1390
|
-
store.
|
|
1391
|
-
isLoading: false,
|
|
1392
|
-
error: err
|
|
1393
|
-
});
|
|
2051
|
+
store.setQueryError(queryKey, err);
|
|
1394
2052
|
}
|
|
1395
2053
|
return;
|
|
1396
2054
|
}
|
|
@@ -1400,9 +2058,7 @@ function makeExtrasForClient2(client) {
|
|
|
1400
2058
|
try {
|
|
1401
2059
|
const request = room.getNotificationSettings();
|
|
1402
2060
|
requestsByQuery.set(queryKey, request);
|
|
1403
|
-
store.
|
|
1404
|
-
isLoading: true
|
|
1405
|
-
});
|
|
2061
|
+
store.setQueryLoading(queryKey);
|
|
1406
2062
|
const settings = await request;
|
|
1407
2063
|
store.updateRoomInboxNotificationSettings(room.id, settings, queryKey);
|
|
1408
2064
|
} catch (err) {
|
|
@@ -1412,21 +2068,13 @@ function makeExtrasForClient2(client) {
|
|
|
1412
2068
|
retryCount: retryCount + 1
|
|
1413
2069
|
});
|
|
1414
2070
|
}, retryCount);
|
|
1415
|
-
store.
|
|
1416
|
-
isLoading: false,
|
|
1417
|
-
error: err
|
|
1418
|
-
});
|
|
2071
|
+
store.setQueryError(queryKey, err);
|
|
1419
2072
|
}
|
|
1420
2073
|
return;
|
|
1421
2074
|
}
|
|
1422
2075
|
const commentsErrorEventSource = makeEventSource();
|
|
1423
2076
|
function onMutationFailure(innerError, optimisticUpdateId, createPublicError) {
|
|
1424
|
-
store.
|
|
1425
|
-
...state,
|
|
1426
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
1427
|
-
(update) => update.id !== optimisticUpdateId
|
|
1428
|
-
)
|
|
1429
|
-
}));
|
|
2077
|
+
store.removeOptimisticUpdate(optimisticUpdateId);
|
|
1430
2078
|
if (innerError instanceof CommentsApiError) {
|
|
1431
2079
|
const error = handleApiError(innerError);
|
|
1432
2080
|
commentsErrorEventSource.notify(createPublicError(error));
|
|
@@ -1589,7 +2237,7 @@ function RoomProviderInner(props) {
|
|
|
1589
2237
|
"RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required"
|
|
1590
2238
|
);
|
|
1591
2239
|
}
|
|
1592
|
-
if (
|
|
2240
|
+
if (!isString(roomId)) {
|
|
1593
2241
|
throw new Error("RoomProvider id property should be a string.");
|
|
1594
2242
|
}
|
|
1595
2243
|
const majorReactVersion = parseInt(React4.version) || 1;
|
|
@@ -1620,12 +2268,12 @@ function RoomProviderInner(props) {
|
|
|
1620
2268
|
const { store } = getExtrasForClient2(client);
|
|
1621
2269
|
async function handleCommentEvent(message) {
|
|
1622
2270
|
if (message.type === ServerMsgCode.THREAD_DELETED) {
|
|
1623
|
-
store.deleteThread(message.threadId);
|
|
2271
|
+
store.deleteThread(message.threadId, null);
|
|
1624
2272
|
return;
|
|
1625
2273
|
}
|
|
1626
2274
|
const info = await room.getThread(message.threadId);
|
|
1627
2275
|
if (!info.thread) {
|
|
1628
|
-
store.deleteThread(message.threadId);
|
|
2276
|
+
store.deleteThread(message.threadId, null);
|
|
1629
2277
|
return;
|
|
1630
2278
|
}
|
|
1631
2279
|
const { thread, inboxNotification } = info;
|
|
@@ -1974,7 +2622,7 @@ function useThreads(options = {
|
|
|
1974
2622
|
};
|
|
1975
2623
|
}
|
|
1976
2624
|
return {
|
|
1977
|
-
threads:
|
|
2625
|
+
threads: selectRoomThreads(room.id, state2, options),
|
|
1978
2626
|
isLoading: false,
|
|
1979
2627
|
error: query.error
|
|
1980
2628
|
};
|
|
@@ -2029,26 +2677,15 @@ function useCreateThread() {
|
|
|
2029
2677
|
comments: [newComment],
|
|
2030
2678
|
resolved: false
|
|
2031
2679
|
};
|
|
2032
|
-
const optimisticUpdateId = nanoid2();
|
|
2033
2680
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2034
|
-
store.
|
|
2681
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2035
2682
|
type: "create-thread",
|
|
2036
2683
|
thread: newThread,
|
|
2037
|
-
id: optimisticUpdateId,
|
|
2038
2684
|
roomId: room.id
|
|
2039
2685
|
});
|
|
2040
2686
|
room.createThread({ threadId, commentId, body, metadata }).then(
|
|
2041
2687
|
(thread) => {
|
|
2042
|
-
store.
|
|
2043
|
-
...state,
|
|
2044
|
-
threads: {
|
|
2045
|
-
...state.threads,
|
|
2046
|
-
[threadId]: thread
|
|
2047
|
-
},
|
|
2048
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
2049
|
-
(update) => update.id !== optimisticUpdateId
|
|
2050
|
-
)
|
|
2051
|
-
}));
|
|
2688
|
+
store.createThread(optimisticUpdateId, thread);
|
|
2052
2689
|
},
|
|
2053
2690
|
(err) => onMutationFailure(
|
|
2054
2691
|
err,
|
|
@@ -2072,42 +2709,21 @@ function useDeleteThread() {
|
|
|
2072
2709
|
const room = useRoom();
|
|
2073
2710
|
return React4.useCallback(
|
|
2074
2711
|
(threadId) => {
|
|
2075
|
-
const optimisticUpdateId = nanoid2();
|
|
2076
2712
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2077
2713
|
const thread = store.get().threads[threadId];
|
|
2078
2714
|
const userId = getCurrentUserId(room);
|
|
2079
2715
|
if (thread?.comments?.[0]?.userId !== userId) {
|
|
2080
2716
|
throw new Error("Only the thread creator can delete the thread");
|
|
2081
2717
|
}
|
|
2082
|
-
store.
|
|
2718
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2083
2719
|
type: "delete-thread",
|
|
2084
|
-
id: optimisticUpdateId,
|
|
2085
2720
|
roomId: room.id,
|
|
2086
2721
|
threadId,
|
|
2087
2722
|
deletedAt: /* @__PURE__ */ new Date()
|
|
2088
2723
|
});
|
|
2089
2724
|
room.deleteThread(threadId).then(
|
|
2090
2725
|
() => {
|
|
2091
|
-
store.
|
|
2092
|
-
const existingThread = state.threads[threadId];
|
|
2093
|
-
if (existingThread === void 0) {
|
|
2094
|
-
return state;
|
|
2095
|
-
}
|
|
2096
|
-
return {
|
|
2097
|
-
...state,
|
|
2098
|
-
threads: {
|
|
2099
|
-
...state.threads,
|
|
2100
|
-
[threadId]: {
|
|
2101
|
-
...existingThread,
|
|
2102
|
-
updatedAt: /* @__PURE__ */ new Date(),
|
|
2103
|
-
deletedAt: /* @__PURE__ */ new Date()
|
|
2104
|
-
}
|
|
2105
|
-
},
|
|
2106
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
2107
|
-
(update) => update.id !== optimisticUpdateId
|
|
2108
|
-
)
|
|
2109
|
-
};
|
|
2110
|
-
});
|
|
2726
|
+
store.deleteThread(threadId, optimisticUpdateId);
|
|
2111
2727
|
},
|
|
2112
2728
|
(err) => onMutationFailure(
|
|
2113
2729
|
err,
|
|
@@ -2130,53 +2746,23 @@ function useEditThreadMetadata() {
|
|
|
2130
2746
|
const threadId = options.threadId;
|
|
2131
2747
|
const metadata = options.metadata;
|
|
2132
2748
|
const updatedAt = /* @__PURE__ */ new Date();
|
|
2133
|
-
const optimisticUpdateId = nanoid2();
|
|
2134
2749
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2135
|
-
store.
|
|
2750
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2136
2751
|
type: "edit-thread-metadata",
|
|
2137
2752
|
metadata,
|
|
2138
|
-
id: optimisticUpdateId,
|
|
2139
2753
|
threadId,
|
|
2140
2754
|
updatedAt
|
|
2141
2755
|
});
|
|
2142
|
-
room.editThreadMetadata({
|
|
2143
|
-
(metadata2) =>
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
)
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2153
|
-
};
|
|
2154
|
-
}
|
|
2155
|
-
if (existingThread.deletedAt !== void 0) {
|
|
2156
|
-
return {
|
|
2157
|
-
...state,
|
|
2158
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2159
|
-
};
|
|
2160
|
-
}
|
|
2161
|
-
if (existingThread.updatedAt && existingThread.updatedAt > updatedAt) {
|
|
2162
|
-
return {
|
|
2163
|
-
...state,
|
|
2164
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2165
|
-
};
|
|
2166
|
-
}
|
|
2167
|
-
return {
|
|
2168
|
-
...state,
|
|
2169
|
-
threads: {
|
|
2170
|
-
...state.threads,
|
|
2171
|
-
[threadId]: {
|
|
2172
|
-
...existingThread,
|
|
2173
|
-
metadata: metadata2
|
|
2174
|
-
}
|
|
2175
|
-
},
|
|
2176
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2177
|
-
};
|
|
2178
|
-
});
|
|
2179
|
-
},
|
|
2756
|
+
room.editThreadMetadata({ threadId, metadata }).then(
|
|
2757
|
+
(metadata2) => (
|
|
2758
|
+
// Replace the optimistic update by the real thing
|
|
2759
|
+
store.updateThread(
|
|
2760
|
+
threadId,
|
|
2761
|
+
optimisticUpdateId,
|
|
2762
|
+
(thread) => ({ ...thread, metadata: metadata2 }),
|
|
2763
|
+
updatedAt
|
|
2764
|
+
)
|
|
2765
|
+
),
|
|
2180
2766
|
(err) => onMutationFailure(
|
|
2181
2767
|
err,
|
|
2182
2768
|
optimisticUpdateId,
|
|
@@ -2208,50 +2794,14 @@ function useCreateComment() {
|
|
|
2208
2794
|
body,
|
|
2209
2795
|
reactions: []
|
|
2210
2796
|
};
|
|
2211
|
-
const optimisticUpdateId = nanoid2();
|
|
2212
2797
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2213
|
-
store.
|
|
2798
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2214
2799
|
type: "create-comment",
|
|
2215
|
-
comment
|
|
2216
|
-
id: optimisticUpdateId
|
|
2800
|
+
comment
|
|
2217
2801
|
});
|
|
2218
2802
|
room.createComment({ threadId, commentId, body }).then(
|
|
2219
2803
|
(newComment) => {
|
|
2220
|
-
store.
|
|
2221
|
-
const existingThread = state.threads[threadId];
|
|
2222
|
-
const updatedOptimisticUpdates = state.optimisticUpdates.filter(
|
|
2223
|
-
(update) => update.id !== optimisticUpdateId
|
|
2224
|
-
);
|
|
2225
|
-
if (existingThread === void 0) {
|
|
2226
|
-
return {
|
|
2227
|
-
...state,
|
|
2228
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2229
|
-
};
|
|
2230
|
-
}
|
|
2231
|
-
const inboxNotification = Object.values(
|
|
2232
|
-
state.inboxNotifications
|
|
2233
|
-
).find(
|
|
2234
|
-
(notification) => notification.kind === "thread" && notification.threadId === threadId
|
|
2235
|
-
);
|
|
2236
|
-
const updatedInboxNotifications = inboxNotification !== void 0 ? {
|
|
2237
|
-
...state.inboxNotifications,
|
|
2238
|
-
[inboxNotification.id]: {
|
|
2239
|
-
...inboxNotification,
|
|
2240
|
-
notifiedAt: newComment.createdAt,
|
|
2241
|
-
readAt: newComment.createdAt
|
|
2242
|
-
}
|
|
2243
|
-
} : state.inboxNotifications;
|
|
2244
|
-
return {
|
|
2245
|
-
...state,
|
|
2246
|
-
threads: {
|
|
2247
|
-
...state.threads,
|
|
2248
|
-
[threadId]: upsertComment(existingThread, newComment)
|
|
2249
|
-
// Upsert the new comment into the thread comments list (if applicable)
|
|
2250
|
-
},
|
|
2251
|
-
inboxNotifications: updatedInboxNotifications,
|
|
2252
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2253
|
-
};
|
|
2254
|
-
});
|
|
2804
|
+
store.createComment(newComment, optimisticUpdateId);
|
|
2255
2805
|
},
|
|
2256
2806
|
(err) => onMutationFailure(
|
|
2257
2807
|
err,
|
|
@@ -2275,11 +2825,10 @@ function useEditComment() {
|
|
|
2275
2825
|
return React4.useCallback(
|
|
2276
2826
|
({ threadId, commentId, body }) => {
|
|
2277
2827
|
const editedAt = /* @__PURE__ */ new Date();
|
|
2278
|
-
const optimisticUpdateId = nanoid2();
|
|
2279
2828
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2280
2829
|
const thread = store.get().threads[threadId];
|
|
2281
2830
|
if (thread === void 0) {
|
|
2282
|
-
|
|
2831
|
+
console3.warn(
|
|
2283
2832
|
`Internal unexpected behavior. Cannot edit comment in thread "${threadId}" because the thread does not exist in the cache.`
|
|
2284
2833
|
);
|
|
2285
2834
|
return;
|
|
@@ -2288,43 +2837,26 @@ function useEditComment() {
|
|
|
2288
2837
|
(comment2) => comment2.id === commentId
|
|
2289
2838
|
);
|
|
2290
2839
|
if (comment === void 0 || comment.deletedAt !== void 0) {
|
|
2291
|
-
|
|
2840
|
+
console3.warn(
|
|
2292
2841
|
`Internal unexpected behavior. Cannot edit comment "${commentId}" in thread "${threadId}" because the comment does not exist in the cache.`
|
|
2293
2842
|
);
|
|
2294
2843
|
return;
|
|
2295
2844
|
}
|
|
2296
|
-
store.
|
|
2845
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2297
2846
|
type: "edit-comment",
|
|
2298
2847
|
comment: {
|
|
2299
2848
|
...comment,
|
|
2300
2849
|
editedAt,
|
|
2301
2850
|
body
|
|
2302
|
-
}
|
|
2303
|
-
id: optimisticUpdateId
|
|
2851
|
+
}
|
|
2304
2852
|
});
|
|
2305
2853
|
room.editComment({ threadId, commentId, body }).then(
|
|
2306
2854
|
(editedComment) => {
|
|
2307
|
-
store.
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
if (existingThread === void 0) {
|
|
2313
|
-
return {
|
|
2314
|
-
...state,
|
|
2315
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2316
|
-
};
|
|
2317
|
-
}
|
|
2318
|
-
return {
|
|
2319
|
-
...state,
|
|
2320
|
-
threads: {
|
|
2321
|
-
...state.threads,
|
|
2322
|
-
[threadId]: upsertComment(existingThread, editedComment)
|
|
2323
|
-
// Upsert the edited comment into the thread comments list (if applicable)
|
|
2324
|
-
},
|
|
2325
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2326
|
-
};
|
|
2327
|
-
});
|
|
2855
|
+
store.updateThread(
|
|
2856
|
+
threadId,
|
|
2857
|
+
optimisticUpdateId,
|
|
2858
|
+
(thread2) => upsertComment(thread2, editedComment)
|
|
2859
|
+
);
|
|
2328
2860
|
},
|
|
2329
2861
|
(err) => onMutationFailure(
|
|
2330
2862
|
err,
|
|
@@ -2347,38 +2879,22 @@ function useDeleteComment() {
|
|
|
2347
2879
|
return React4.useCallback(
|
|
2348
2880
|
({ threadId, commentId }) => {
|
|
2349
2881
|
const deletedAt = /* @__PURE__ */ new Date();
|
|
2350
|
-
const optimisticUpdateId = nanoid2();
|
|
2351
2882
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2352
|
-
store.
|
|
2883
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2353
2884
|
type: "delete-comment",
|
|
2354
2885
|
threadId,
|
|
2355
2886
|
commentId,
|
|
2356
2887
|
deletedAt,
|
|
2357
|
-
id: optimisticUpdateId,
|
|
2358
2888
|
roomId: room.id
|
|
2359
2889
|
});
|
|
2360
2890
|
room.deleteComment({ threadId, commentId }).then(
|
|
2361
2891
|
() => {
|
|
2362
|
-
store.
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
return {
|
|
2369
|
-
...state,
|
|
2370
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2371
|
-
};
|
|
2372
|
-
}
|
|
2373
|
-
return {
|
|
2374
|
-
...state,
|
|
2375
|
-
threads: {
|
|
2376
|
-
...state.threads,
|
|
2377
|
-
[threadId]: deleteComment(existingThread, commentId, deletedAt)
|
|
2378
|
-
},
|
|
2379
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2380
|
-
};
|
|
2381
|
-
});
|
|
2892
|
+
store.updateThread(
|
|
2893
|
+
threadId,
|
|
2894
|
+
optimisticUpdateId,
|
|
2895
|
+
(thread) => deleteComment(thread, commentId, deletedAt),
|
|
2896
|
+
deletedAt
|
|
2897
|
+
);
|
|
2382
2898
|
},
|
|
2383
2899
|
(err) => onMutationFailure(
|
|
2384
2900
|
err,
|
|
@@ -2401,9 +2917,8 @@ function useAddReaction() {
|
|
|
2401
2917
|
({ threadId, commentId, emoji }) => {
|
|
2402
2918
|
const createdAt = /* @__PURE__ */ new Date();
|
|
2403
2919
|
const userId = getCurrentUserId(room);
|
|
2404
|
-
const optimisticUpdateId = nanoid2();
|
|
2405
2920
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2406
|
-
store.
|
|
2921
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2407
2922
|
type: "add-reaction",
|
|
2408
2923
|
threadId,
|
|
2409
2924
|
commentId,
|
|
@@ -2411,35 +2926,16 @@ function useAddReaction() {
|
|
|
2411
2926
|
emoji,
|
|
2412
2927
|
userId,
|
|
2413
2928
|
createdAt
|
|
2414
|
-
}
|
|
2415
|
-
id: optimisticUpdateId
|
|
2929
|
+
}
|
|
2416
2930
|
});
|
|
2417
2931
|
room.addReaction({ threadId, commentId, emoji }).then(
|
|
2418
2932
|
(addedReaction) => {
|
|
2419
|
-
store.
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
return {
|
|
2426
|
-
...state,
|
|
2427
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2428
|
-
};
|
|
2429
|
-
}
|
|
2430
|
-
return {
|
|
2431
|
-
...state,
|
|
2432
|
-
threads: {
|
|
2433
|
-
...state.threads,
|
|
2434
|
-
[threadId]: addReaction(
|
|
2435
|
-
existingThread,
|
|
2436
|
-
commentId,
|
|
2437
|
-
addedReaction
|
|
2438
|
-
)
|
|
2439
|
-
},
|
|
2440
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2441
|
-
};
|
|
2442
|
-
});
|
|
2933
|
+
store.updateThread(
|
|
2934
|
+
threadId,
|
|
2935
|
+
optimisticUpdateId,
|
|
2936
|
+
(thread) => addReaction(thread, commentId, addedReaction),
|
|
2937
|
+
createdAt
|
|
2938
|
+
);
|
|
2443
2939
|
},
|
|
2444
2940
|
(err) => onMutationFailure(
|
|
2445
2941
|
err,
|
|
@@ -2463,45 +2959,23 @@ function useRemoveReaction() {
|
|
|
2463
2959
|
({ threadId, commentId, emoji }) => {
|
|
2464
2960
|
const userId = getCurrentUserId(room);
|
|
2465
2961
|
const removedAt = /* @__PURE__ */ new Date();
|
|
2466
|
-
const optimisticUpdateId = nanoid2();
|
|
2467
2962
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2468
|
-
store.
|
|
2963
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2469
2964
|
type: "remove-reaction",
|
|
2470
2965
|
threadId,
|
|
2471
2966
|
commentId,
|
|
2472
2967
|
emoji,
|
|
2473
2968
|
userId,
|
|
2474
|
-
removedAt
|
|
2475
|
-
id: optimisticUpdateId
|
|
2969
|
+
removedAt
|
|
2476
2970
|
});
|
|
2477
2971
|
room.removeReaction({ threadId, commentId, emoji }).then(
|
|
2478
2972
|
() => {
|
|
2479
|
-
store.
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
return {
|
|
2486
|
-
...state,
|
|
2487
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2488
|
-
};
|
|
2489
|
-
}
|
|
2490
|
-
return {
|
|
2491
|
-
...state,
|
|
2492
|
-
threads: {
|
|
2493
|
-
...state.threads,
|
|
2494
|
-
[threadId]: removeReaction(
|
|
2495
|
-
existingThread,
|
|
2496
|
-
commentId,
|
|
2497
|
-
emoji,
|
|
2498
|
-
userId,
|
|
2499
|
-
removedAt
|
|
2500
|
-
)
|
|
2501
|
-
},
|
|
2502
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2503
|
-
};
|
|
2504
|
-
});
|
|
2973
|
+
store.updateThread(
|
|
2974
|
+
threadId,
|
|
2975
|
+
optimisticUpdateId,
|
|
2976
|
+
(thread) => removeReaction(thread, commentId, emoji, userId, removedAt),
|
|
2977
|
+
removedAt
|
|
2978
|
+
);
|
|
2505
2979
|
},
|
|
2506
2980
|
(err) => onMutationFailure(
|
|
2507
2981
|
err,
|
|
@@ -2530,29 +3004,19 @@ function useMarkThreadAsRead() {
|
|
|
2530
3004
|
(inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
|
|
2531
3005
|
);
|
|
2532
3006
|
if (!inboxNotification) return;
|
|
2533
|
-
const optimisticUpdateId = nanoid2();
|
|
2534
3007
|
const now = /* @__PURE__ */ new Date();
|
|
2535
|
-
store.
|
|
3008
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2536
3009
|
type: "mark-inbox-notification-as-read",
|
|
2537
|
-
id: optimisticUpdateId,
|
|
2538
3010
|
inboxNotificationId: inboxNotification.id,
|
|
2539
3011
|
readAt: now
|
|
2540
3012
|
});
|
|
2541
3013
|
room.markInboxNotificationAsRead(inboxNotification.id).then(
|
|
2542
3014
|
() => {
|
|
2543
|
-
store.
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
...inboxNotification,
|
|
2549
|
-
readAt: now
|
|
2550
|
-
}
|
|
2551
|
-
},
|
|
2552
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
2553
|
-
(update) => update.id !== optimisticUpdateId
|
|
2554
|
-
)
|
|
2555
|
-
}));
|
|
3015
|
+
store.updateInboxNotification(
|
|
3016
|
+
inboxNotification.id,
|
|
3017
|
+
optimisticUpdateId,
|
|
3018
|
+
(inboxNotification2) => ({ ...inboxNotification2, readAt: now })
|
|
3019
|
+
);
|
|
2556
3020
|
},
|
|
2557
3021
|
(err) => {
|
|
2558
3022
|
onMutationFailure(
|
|
@@ -2574,52 +3038,21 @@ function useMarkThreadAsResolved() {
|
|
|
2574
3038
|
const room = useRoom();
|
|
2575
3039
|
return React4.useCallback(
|
|
2576
3040
|
(threadId) => {
|
|
2577
|
-
const optimisticUpdateId = nanoid2();
|
|
2578
3041
|
const updatedAt = /* @__PURE__ */ new Date();
|
|
2579
3042
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2580
|
-
store.
|
|
3043
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2581
3044
|
type: "mark-thread-as-resolved",
|
|
2582
|
-
id: optimisticUpdateId,
|
|
2583
3045
|
threadId,
|
|
2584
3046
|
updatedAt
|
|
2585
3047
|
});
|
|
2586
3048
|
room.markThreadAsResolved(threadId).then(
|
|
2587
3049
|
() => {
|
|
2588
|
-
store.
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
return {
|
|
2595
|
-
...state,
|
|
2596
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2597
|
-
};
|
|
2598
|
-
}
|
|
2599
|
-
if (existingThread.deletedAt !== void 0) {
|
|
2600
|
-
return {
|
|
2601
|
-
...state,
|
|
2602
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2603
|
-
};
|
|
2604
|
-
}
|
|
2605
|
-
if (existingThread.updatedAt && existingThread.updatedAt > updatedAt) {
|
|
2606
|
-
return {
|
|
2607
|
-
...state,
|
|
2608
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2609
|
-
};
|
|
2610
|
-
}
|
|
2611
|
-
return {
|
|
2612
|
-
...state,
|
|
2613
|
-
threads: {
|
|
2614
|
-
...state.threads,
|
|
2615
|
-
[threadId]: {
|
|
2616
|
-
...existingThread,
|
|
2617
|
-
resolved: true
|
|
2618
|
-
}
|
|
2619
|
-
},
|
|
2620
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2621
|
-
};
|
|
2622
|
-
});
|
|
3050
|
+
store.updateThread(
|
|
3051
|
+
threadId,
|
|
3052
|
+
optimisticUpdateId,
|
|
3053
|
+
(thread) => ({ ...thread, resolved: true }),
|
|
3054
|
+
updatedAt
|
|
3055
|
+
);
|
|
2623
3056
|
},
|
|
2624
3057
|
(err) => onMutationFailure(
|
|
2625
3058
|
err,
|
|
@@ -2639,52 +3072,21 @@ function useMarkThreadAsUnresolved() {
|
|
|
2639
3072
|
const room = useRoom();
|
|
2640
3073
|
return React4.useCallback(
|
|
2641
3074
|
(threadId) => {
|
|
2642
|
-
const optimisticUpdateId = nanoid2();
|
|
2643
3075
|
const updatedAt = /* @__PURE__ */ new Date();
|
|
2644
3076
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2645
|
-
store.
|
|
3077
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2646
3078
|
type: "mark-thread-as-unresolved",
|
|
2647
|
-
id: optimisticUpdateId,
|
|
2648
3079
|
threadId,
|
|
2649
3080
|
updatedAt
|
|
2650
3081
|
});
|
|
2651
3082
|
room.markThreadAsUnresolved(threadId).then(
|
|
2652
3083
|
() => {
|
|
2653
|
-
store.
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
return {
|
|
2660
|
-
...state,
|
|
2661
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2662
|
-
};
|
|
2663
|
-
}
|
|
2664
|
-
if (existingThread.deletedAt !== void 0) {
|
|
2665
|
-
return {
|
|
2666
|
-
...state,
|
|
2667
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2668
|
-
};
|
|
2669
|
-
}
|
|
2670
|
-
if (existingThread.updatedAt && existingThread.updatedAt > updatedAt) {
|
|
2671
|
-
return {
|
|
2672
|
-
...state,
|
|
2673
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2674
|
-
};
|
|
2675
|
-
}
|
|
2676
|
-
return {
|
|
2677
|
-
...state,
|
|
2678
|
-
threads: {
|
|
2679
|
-
...state.threads,
|
|
2680
|
-
[threadId]: {
|
|
2681
|
-
...existingThread,
|
|
2682
|
-
resolved: false
|
|
2683
|
-
}
|
|
2684
|
-
},
|
|
2685
|
-
optimisticUpdates: updatedOptimisticUpdates
|
|
2686
|
-
};
|
|
2687
|
-
});
|
|
3084
|
+
store.updateThread(
|
|
3085
|
+
threadId,
|
|
3086
|
+
optimisticUpdateId,
|
|
3087
|
+
(thread) => ({ ...thread, resolved: false }),
|
|
3088
|
+
updatedAt
|
|
3089
|
+
);
|
|
2688
3090
|
},
|
|
2689
3091
|
(err) => onMutationFailure(
|
|
2690
3092
|
err,
|
|
@@ -2704,7 +3106,7 @@ function useThreadSubscription(threadId) {
|
|
|
2704
3106
|
const { store } = getExtrasForClient2(client);
|
|
2705
3107
|
const selector = React4.useCallback(
|
|
2706
3108
|
(state) => {
|
|
2707
|
-
const inboxNotification =
|
|
3109
|
+
const inboxNotification = selectInboxNotifications(state).find(
|
|
2708
3110
|
(inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
|
|
2709
3111
|
);
|
|
2710
3112
|
const thread = state.threads[threadId];
|
|
@@ -2830,25 +3232,19 @@ function useUpdateRoomNotificationSettings() {
|
|
|
2830
3232
|
const room = useRoom();
|
|
2831
3233
|
return React4.useCallback(
|
|
2832
3234
|
(settings) => {
|
|
2833
|
-
const optimisticUpdateId = nanoid2();
|
|
2834
3235
|
const { store, onMutationFailure } = getExtrasForClient2(client);
|
|
2835
|
-
store.
|
|
2836
|
-
id: optimisticUpdateId,
|
|
3236
|
+
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2837
3237
|
type: "update-notification-settings",
|
|
2838
3238
|
roomId: room.id,
|
|
2839
3239
|
settings
|
|
2840
3240
|
});
|
|
2841
3241
|
room.updateNotificationSettings(settings).then(
|
|
2842
3242
|
(settings2) => {
|
|
2843
|
-
store.
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
optimisticUpdates: state.optimisticUpdates.filter(
|
|
2849
|
-
(update) => update.id !== optimisticUpdateId
|
|
2850
|
-
)
|
|
2851
|
-
}));
|
|
3243
|
+
store.updateRoomInboxNotificationSettings2(
|
|
3244
|
+
room.id,
|
|
3245
|
+
optimisticUpdateId,
|
|
3246
|
+
settings2
|
|
3247
|
+
);
|
|
2852
3248
|
},
|
|
2853
3249
|
(err) => onMutationFailure(
|
|
2854
3250
|
err,
|
|
@@ -2937,7 +3333,7 @@ function useThreadsSuspense(options = {
|
|
|
2937
3333
|
const selector = React4.useCallback(
|
|
2938
3334
|
(state2) => {
|
|
2939
3335
|
return {
|
|
2940
|
-
threads:
|
|
3336
|
+
threads: selectRoomThreads(room.id, state2, options),
|
|
2941
3337
|
isLoading: false
|
|
2942
3338
|
};
|
|
2943
3339
|
},
|
|
@@ -3026,7 +3422,7 @@ function createRoomContext(client) {
|
|
|
3026
3422
|
return getOrCreateRoomContextBundle(client);
|
|
3027
3423
|
}
|
|
3028
3424
|
function generateQueryKey(roomId, options) {
|
|
3029
|
-
return `${roomId}-${
|
|
3425
|
+
return `${roomId}-${stringify2(options ?? {})}`;
|
|
3030
3426
|
}
|
|
3031
3427
|
function getVersionsQueryKey(roomId) {
|
|
3032
3428
|
return `${roomId}-VERSIONS`;
|
|
@@ -3073,8 +3469,8 @@ export {
|
|
|
3073
3469
|
PKG_VERSION,
|
|
3074
3470
|
PKG_FORMAT,
|
|
3075
3471
|
ClientSideSuspense,
|
|
3076
|
-
selectedThreads,
|
|
3077
3472
|
CreateThreadError,
|
|
3473
|
+
selectRoomThreads,
|
|
3078
3474
|
RoomContext,
|
|
3079
3475
|
useStatus,
|
|
3080
3476
|
useStorageStatus,
|
|
@@ -3131,6 +3527,7 @@ export {
|
|
|
3131
3527
|
_useStorageRoot,
|
|
3132
3528
|
_useUpdateMyPresence,
|
|
3133
3529
|
ClientContext,
|
|
3530
|
+
getUmbrellaStoreForClient,
|
|
3134
3531
|
useClient,
|
|
3135
3532
|
LiveblocksProvider,
|
|
3136
3533
|
createLiveblocksContext,
|
|
@@ -3150,4 +3547,4 @@ export {
|
|
|
3150
3547
|
_useUserThreads_experimental,
|
|
3151
3548
|
_useUserThreadsSuspense_experimental
|
|
3152
3549
|
};
|
|
3153
|
-
//# sourceMappingURL=chunk-
|
|
3550
|
+
//# sourceMappingURL=chunk-OKR7ROQ5.mjs.map
|