@liveblocks/react 2.14.0 → 2.15.0-debug1
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/_private.d.mts +10 -4
- package/dist/_private.d.ts +10 -4
- package/dist/_private.js +27 -14
- package/dist/_private.js.map +1 -1
- package/dist/_private.mjs +30 -17
- package/dist/_private.mjs.map +1 -1
- package/dist/chunk-A4ABDZ5E.mjs +23 -0
- package/dist/chunk-A4ABDZ5E.mjs.map +1 -0
- package/dist/{chunk-X4DDEZYL.js → chunk-KY7WMVMG.js} +673 -458
- package/dist/chunk-KY7WMVMG.js.map +1 -0
- package/dist/chunk-MI7M3UBZ.js +23 -0
- package/dist/chunk-MI7M3UBZ.js.map +1 -0
- package/dist/{chunk-BRCWZCNY.mjs → chunk-UJLD6FYC.mjs} +682 -467
- package/dist/chunk-UJLD6FYC.mjs.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/index.mjs +2 -2
- package/dist/{room-Rl_QnQMY.d.mts → room-C_NzlTZP.d.mts} +69 -90
- package/dist/{room-Rl_QnQMY.d.ts → room-C_NzlTZP.d.ts} +69 -90
- package/dist/suspense.d.mts +2 -1
- package/dist/suspense.d.ts +2 -1
- package/dist/suspense.js +4 -4
- package/dist/suspense.mjs +2 -2
- package/package.json +4 -6
- package/dist/chunk-BRCWZCNY.mjs.map +0 -1
- package/dist/chunk-IQJWVOHM.mjs +0 -22
- package/dist/chunk-IQJWVOHM.mjs.map +0 -1
- package/dist/chunk-L2RWXPYA.js +0 -22
- package/dist/chunk-L2RWXPYA.js.map +0 -1
- package/dist/chunk-X4DDEZYL.js.map +0 -1
|
@@ -1,14 +1,90 @@
|
|
|
1
1
|
// src/contexts.ts
|
|
2
|
-
import
|
|
3
|
-
var RoomContext =
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
var RoomContext = createContext(null);
|
|
4
4
|
function useRoomOrNull() {
|
|
5
|
-
return
|
|
5
|
+
return useContext(RoomContext);
|
|
6
6
|
}
|
|
7
7
|
function useIsInsideRoom() {
|
|
8
8
|
const room = useRoomOrNull();
|
|
9
9
|
return room !== null;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
// src/use-sync-external-store-with-selector.ts
|
|
13
|
+
import {
|
|
14
|
+
useDebugValue,
|
|
15
|
+
useEffect,
|
|
16
|
+
useMemo,
|
|
17
|
+
useRef,
|
|
18
|
+
useSyncExternalStore
|
|
19
|
+
} from "react";
|
|
20
|
+
function is(x, y) {
|
|
21
|
+
return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y;
|
|
22
|
+
}
|
|
23
|
+
function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnapshot, selector, isEqual) {
|
|
24
|
+
const instRef = useRef(null);
|
|
25
|
+
let inst;
|
|
26
|
+
if (instRef.current === null) {
|
|
27
|
+
inst = {
|
|
28
|
+
hasValue: false,
|
|
29
|
+
value: null
|
|
30
|
+
};
|
|
31
|
+
instRef.current = inst;
|
|
32
|
+
} else {
|
|
33
|
+
inst = instRef.current;
|
|
34
|
+
}
|
|
35
|
+
const [getSelection, getServerSelection] = useMemo(() => {
|
|
36
|
+
let hasMemo = false;
|
|
37
|
+
let memoizedSnapshot;
|
|
38
|
+
let memoizedSelection;
|
|
39
|
+
const memoizedSelector = (nextSnapshot) => {
|
|
40
|
+
if (!hasMemo) {
|
|
41
|
+
hasMemo = true;
|
|
42
|
+
memoizedSnapshot = nextSnapshot;
|
|
43
|
+
const nextSelection2 = selector(nextSnapshot);
|
|
44
|
+
if (isEqual !== void 0) {
|
|
45
|
+
if (inst.hasValue) {
|
|
46
|
+
const currentSelection = inst.value;
|
|
47
|
+
if (isEqual(currentSelection, nextSelection2)) {
|
|
48
|
+
memoizedSelection = currentSelection;
|
|
49
|
+
return currentSelection;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
memoizedSelection = nextSelection2;
|
|
54
|
+
return nextSelection2;
|
|
55
|
+
}
|
|
56
|
+
const prevSnapshot = memoizedSnapshot;
|
|
57
|
+
const prevSelection = memoizedSelection;
|
|
58
|
+
if (is(prevSnapshot, nextSnapshot)) {
|
|
59
|
+
return prevSelection;
|
|
60
|
+
}
|
|
61
|
+
const nextSelection = selector(nextSnapshot);
|
|
62
|
+
if (isEqual !== void 0 && isEqual(prevSelection, nextSelection)) {
|
|
63
|
+
memoizedSnapshot = nextSnapshot;
|
|
64
|
+
return prevSelection;
|
|
65
|
+
}
|
|
66
|
+
memoizedSnapshot = nextSnapshot;
|
|
67
|
+
memoizedSelection = nextSelection;
|
|
68
|
+
return nextSelection;
|
|
69
|
+
};
|
|
70
|
+
const maybeGetServerSnapshot = getServerSnapshot === void 0 ? null : getServerSnapshot;
|
|
71
|
+
const getSnapshotWithSelector = () => memoizedSelector(getSnapshot());
|
|
72
|
+
const getServerSnapshotWithSelector = maybeGetServerSnapshot === null ? void 0 : () => memoizedSelector(maybeGetServerSnapshot());
|
|
73
|
+
return [getSnapshotWithSelector, getServerSnapshotWithSelector];
|
|
74
|
+
}, [getSnapshot, getServerSnapshot, selector, isEqual]);
|
|
75
|
+
const value = useSyncExternalStore(
|
|
76
|
+
subscribe,
|
|
77
|
+
getSelection,
|
|
78
|
+
getServerSelection
|
|
79
|
+
);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
inst.hasValue = true;
|
|
82
|
+
inst.value = value;
|
|
83
|
+
}, [value]);
|
|
84
|
+
useDebugValue(value);
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
|
|
12
88
|
// src/liveblocks.tsx
|
|
13
89
|
import {
|
|
14
90
|
assert,
|
|
@@ -18,15 +94,15 @@ import {
|
|
|
18
94
|
raise,
|
|
19
95
|
shallow as shallow3
|
|
20
96
|
} from "@liveblocks/core";
|
|
21
|
-
import
|
|
97
|
+
import {
|
|
22
98
|
createContext as createContext2,
|
|
23
99
|
useCallback as useCallback2,
|
|
24
100
|
useContext as useContext2,
|
|
25
|
-
useEffect as
|
|
26
|
-
useMemo
|
|
101
|
+
useEffect as useEffect3,
|
|
102
|
+
useMemo as useMemo2,
|
|
103
|
+
useState,
|
|
104
|
+
useSyncExternalStore as useSyncExternalStore2
|
|
27
105
|
} from "react";
|
|
28
|
-
import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
|
|
29
|
-
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/shim/with-selector.js";
|
|
30
106
|
|
|
31
107
|
// src/config.ts
|
|
32
108
|
var SECONDS = 1e3;
|
|
@@ -64,10 +140,10 @@ function shallow2(a, b) {
|
|
|
64
140
|
import { useCallback, useReducer } from "react";
|
|
65
141
|
|
|
66
142
|
// src/lib/use-latest.ts
|
|
67
|
-
import { useEffect, useRef } from "react";
|
|
143
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
68
144
|
function useLatest(value) {
|
|
69
|
-
const ref =
|
|
70
|
-
|
|
145
|
+
const ref = useRef2(value);
|
|
146
|
+
useEffect2(() => {
|
|
71
147
|
ref.current = value;
|
|
72
148
|
}, [value]);
|
|
73
149
|
return ref;
|
|
@@ -120,15 +196,17 @@ var use = (
|
|
|
120
196
|
// src/umbrella-store.ts
|
|
121
197
|
import {
|
|
122
198
|
autoRetry,
|
|
199
|
+
batch,
|
|
123
200
|
compactObject,
|
|
124
201
|
console as console2,
|
|
125
|
-
|
|
202
|
+
DerivedSignal,
|
|
126
203
|
HttpError,
|
|
127
204
|
kInternal,
|
|
128
205
|
makeEventSource,
|
|
129
206
|
mapValues,
|
|
130
207
|
nanoid,
|
|
131
208
|
nn,
|
|
209
|
+
Signal,
|
|
132
210
|
stringify
|
|
133
211
|
} from "@liveblocks/core";
|
|
134
212
|
|
|
@@ -150,7 +228,7 @@ function autobind(self) {
|
|
|
150
228
|
}
|
|
151
229
|
|
|
152
230
|
// src/ThreadDB.ts
|
|
153
|
-
import { SortedList } from "@liveblocks/core";
|
|
231
|
+
import { MutableSignal, SortedList } from "@liveblocks/core";
|
|
154
232
|
|
|
155
233
|
// src/lib/guards.ts
|
|
156
234
|
import { isPlainObject as isPlainObject2 } from "@liveblocks/core";
|
|
@@ -202,36 +280,35 @@ function sanitizeThread(thread) {
|
|
|
202
280
|
return thread;
|
|
203
281
|
}
|
|
204
282
|
var ThreadDB = class _ThreadDB {
|
|
205
|
-
|
|
283
|
+
#byId;
|
|
284
|
+
#asc;
|
|
285
|
+
#desc;
|
|
286
|
+
// This signal will be notified on every mutation
|
|
287
|
+
signal;
|
|
206
288
|
constructor() {
|
|
207
|
-
this
|
|
289
|
+
this.#asc = SortedList.from([], (t1, t2) => {
|
|
208
290
|
const d1 = t1.createdAt;
|
|
209
291
|
const d2 = t2.createdAt;
|
|
210
292
|
return d1 < d2 ? true : d1 === d2 ? t1.id < t2.id : false;
|
|
211
293
|
});
|
|
212
|
-
this
|
|
294
|
+
this.#desc = SortedList.from([], (t1, t2) => {
|
|
213
295
|
const d2 = t2.updatedAt;
|
|
214
296
|
const d1 = t1.updatedAt;
|
|
215
297
|
return d2 < d1 ? true : d2 === d1 ? t2.id < t1.id : false;
|
|
216
298
|
});
|
|
217
|
-
this
|
|
218
|
-
this.
|
|
299
|
+
this.#byId = /* @__PURE__ */ new Map();
|
|
300
|
+
this.signal = new MutableSignal(this);
|
|
219
301
|
}
|
|
220
302
|
//
|
|
221
303
|
// Public APIs
|
|
222
304
|
//
|
|
223
305
|
clone() {
|
|
224
306
|
const newPool = new _ThreadDB();
|
|
225
|
-
newPool
|
|
226
|
-
newPool
|
|
227
|
-
newPool
|
|
228
|
-
newPool._version = this._version;
|
|
307
|
+
newPool.#byId = new Map(this.#byId);
|
|
308
|
+
newPool.#asc = this.#asc.clone();
|
|
309
|
+
newPool.#desc = this.#desc.clone();
|
|
229
310
|
return newPool;
|
|
230
311
|
}
|
|
231
|
-
/** Gets the transaction count for this DB. Increments any time the DB is modified. */
|
|
232
|
-
get version() {
|
|
233
|
-
return this._version;
|
|
234
|
-
}
|
|
235
312
|
/** Returns an existing thread by ID. Will never return a deleted thread. */
|
|
236
313
|
get(threadId) {
|
|
237
314
|
const thread = this.getEvenIfDeleted(threadId);
|
|
@@ -239,24 +316,26 @@ var ThreadDB = class _ThreadDB {
|
|
|
239
316
|
}
|
|
240
317
|
/** Returns the (possibly deleted) thread by ID. */
|
|
241
318
|
getEvenIfDeleted(threadId) {
|
|
242
|
-
return this.
|
|
319
|
+
return this.#byId.get(threadId);
|
|
243
320
|
}
|
|
244
321
|
/** Adds or updates a thread in the DB. If the newly given thread is a deleted one, it will get deleted. */
|
|
245
322
|
upsert(thread) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (toRemove
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
323
|
+
this.signal.mutate(() => {
|
|
324
|
+
thread = sanitizeThread(thread);
|
|
325
|
+
const id = thread.id;
|
|
326
|
+
const toRemove = this.#byId.get(id);
|
|
327
|
+
if (toRemove) {
|
|
328
|
+
if (toRemove.deletedAt) return false;
|
|
329
|
+
this.#asc.remove(toRemove);
|
|
330
|
+
this.#desc.remove(toRemove);
|
|
331
|
+
}
|
|
332
|
+
if (!thread.deletedAt) {
|
|
333
|
+
this.#asc.add(thread);
|
|
334
|
+
this.#desc.add(thread);
|
|
335
|
+
}
|
|
336
|
+
this.#byId.set(id, thread);
|
|
337
|
+
return true;
|
|
338
|
+
});
|
|
260
339
|
}
|
|
261
340
|
/** Like .upsert(), except it won't update if a thread by this ID already exists. */
|
|
262
341
|
// TODO Consider renaming this to just .upsert(). I'm not sure if we really
|
|
@@ -272,7 +351,7 @@ var ThreadDB = class _ThreadDB {
|
|
|
272
351
|
* queries, but it can still be accessed via `.getEvenIfDeleted()`.
|
|
273
352
|
*/
|
|
274
353
|
delete(threadId, deletedAt) {
|
|
275
|
-
const existing = this.
|
|
354
|
+
const existing = this.#byId.get(threadId);
|
|
276
355
|
if (existing && !existing.deletedAt) {
|
|
277
356
|
this.upsert({ ...existing, deletedAt, updatedAt: deletedAt });
|
|
278
357
|
}
|
|
@@ -289,7 +368,7 @@ var ThreadDB = class _ThreadDB {
|
|
|
289
368
|
* Will never return deleted threads in the result.
|
|
290
369
|
*/
|
|
291
370
|
findMany(roomId, query, direction) {
|
|
292
|
-
const index = direction === "desc" ? this
|
|
371
|
+
const index = direction === "desc" ? this.#desc : this.#asc;
|
|
293
372
|
const crit = [];
|
|
294
373
|
if (roomId !== void 0) {
|
|
295
374
|
crit.push((t) => t.roomId === roomId);
|
|
@@ -297,12 +376,6 @@ var ThreadDB = class _ThreadDB {
|
|
|
297
376
|
crit.push(makeThreadsFilter(query));
|
|
298
377
|
return Array.from(index.filter((t) => crit.every((pred) => pred(t))));
|
|
299
378
|
}
|
|
300
|
-
//
|
|
301
|
-
// Private APIs
|
|
302
|
-
//
|
|
303
|
-
touch() {
|
|
304
|
-
++this._version;
|
|
305
|
-
}
|
|
306
379
|
};
|
|
307
380
|
|
|
308
381
|
// src/umbrella-store.ts
|
|
@@ -339,62 +412,67 @@ function usify(promise) {
|
|
|
339
412
|
var noop2 = Promise.resolve();
|
|
340
413
|
var ASYNC_LOADING = Object.freeze({ isLoading: true });
|
|
341
414
|
var PaginatedResource = class {
|
|
415
|
+
observable;
|
|
416
|
+
#eventSource;
|
|
417
|
+
#fetchPage;
|
|
418
|
+
#paginationState;
|
|
419
|
+
// Should be null while in loading or error state!
|
|
420
|
+
#pendingFetchMore;
|
|
342
421
|
constructor(fetchPage) {
|
|
343
|
-
this
|
|
344
|
-
this
|
|
345
|
-
this
|
|
346
|
-
this
|
|
347
|
-
this.
|
|
348
|
-
this.observable = this._eventSource.observable;
|
|
422
|
+
this.#paginationState = null;
|
|
423
|
+
this.#fetchPage = fetchPage;
|
|
424
|
+
this.#eventSource = makeEventSource();
|
|
425
|
+
this.#pendingFetchMore = null;
|
|
426
|
+
this.observable = this.#eventSource.observable;
|
|
349
427
|
autobind(this);
|
|
350
428
|
}
|
|
351
|
-
patchPaginationState(patch) {
|
|
352
|
-
const state = this
|
|
429
|
+
#patchPaginationState(patch) {
|
|
430
|
+
const state = this.#paginationState;
|
|
353
431
|
if (state === null) return;
|
|
354
|
-
this
|
|
355
|
-
this.
|
|
432
|
+
this.#paginationState = { ...state, ...patch };
|
|
433
|
+
this.#eventSource.notify();
|
|
356
434
|
}
|
|
357
|
-
async
|
|
358
|
-
const state = this
|
|
435
|
+
async #fetchMore() {
|
|
436
|
+
const state = this.#paginationState;
|
|
359
437
|
if (!state?.cursor) {
|
|
360
438
|
return;
|
|
361
439
|
}
|
|
362
|
-
this
|
|
440
|
+
this.#patchPaginationState({ isFetchingMore: true });
|
|
363
441
|
try {
|
|
364
|
-
const nextCursor = await this
|
|
365
|
-
this
|
|
442
|
+
const nextCursor = await this.#fetchPage(state.cursor);
|
|
443
|
+
this.#patchPaginationState({
|
|
366
444
|
cursor: nextCursor,
|
|
367
445
|
fetchMoreError: void 0,
|
|
368
446
|
isFetchingMore: false
|
|
369
447
|
});
|
|
370
448
|
} catch (err) {
|
|
371
|
-
this
|
|
449
|
+
this.#patchPaginationState({
|
|
372
450
|
isFetchingMore: false,
|
|
373
451
|
fetchMoreError: err
|
|
374
452
|
});
|
|
375
453
|
}
|
|
376
454
|
}
|
|
377
455
|
fetchMore() {
|
|
378
|
-
const state = this
|
|
456
|
+
const state = this.#paginationState;
|
|
379
457
|
if (state?.cursor === null) {
|
|
380
458
|
return noop2;
|
|
381
459
|
}
|
|
382
|
-
if (!this
|
|
383
|
-
this
|
|
384
|
-
this
|
|
460
|
+
if (!this.#pendingFetchMore) {
|
|
461
|
+
this.#pendingFetchMore = this.#fetchMore().finally(() => {
|
|
462
|
+
this.#pendingFetchMore = null;
|
|
385
463
|
});
|
|
386
464
|
}
|
|
387
|
-
return this
|
|
465
|
+
return this.#pendingFetchMore;
|
|
388
466
|
}
|
|
389
467
|
get() {
|
|
390
|
-
const usable = this
|
|
468
|
+
const usable = this.#cachedPromise;
|
|
391
469
|
if (usable === null || usable.status === "pending") {
|
|
392
470
|
return ASYNC_LOADING;
|
|
393
471
|
}
|
|
394
472
|
if (usable.status === "rejected") {
|
|
395
473
|
return { isLoading: false, error: usable.reason };
|
|
396
474
|
}
|
|
397
|
-
const state = this
|
|
475
|
+
const state = this.#paginationState;
|
|
398
476
|
return {
|
|
399
477
|
isLoading: false,
|
|
400
478
|
data: {
|
|
@@ -405,12 +483,13 @@ var PaginatedResource = class {
|
|
|
405
483
|
}
|
|
406
484
|
};
|
|
407
485
|
}
|
|
486
|
+
#cachedPromise = null;
|
|
408
487
|
waitUntilLoaded() {
|
|
409
|
-
if (this
|
|
410
|
-
return this
|
|
488
|
+
if (this.#cachedPromise) {
|
|
489
|
+
return this.#cachedPromise;
|
|
411
490
|
}
|
|
412
491
|
const initialFetcher = autoRetry(
|
|
413
|
-
() => this
|
|
492
|
+
() => this.#fetchPage(
|
|
414
493
|
/* cursor */
|
|
415
494
|
void 0
|
|
416
495
|
),
|
|
@@ -419,7 +498,7 @@ var PaginatedResource = class {
|
|
|
419
498
|
);
|
|
420
499
|
const promise = usify(
|
|
421
500
|
initialFetcher.then((cursor) => {
|
|
422
|
-
this
|
|
501
|
+
this.#paginationState = {
|
|
423
502
|
cursor,
|
|
424
503
|
isFetchingMore: false,
|
|
425
504
|
fetchMoreError: void 0
|
|
@@ -427,29 +506,31 @@ var PaginatedResource = class {
|
|
|
427
506
|
})
|
|
428
507
|
);
|
|
429
508
|
promise.then(
|
|
430
|
-
() => this.
|
|
509
|
+
() => this.#eventSource.notify(),
|
|
431
510
|
() => {
|
|
432
|
-
this.
|
|
511
|
+
this.#eventSource.notify();
|
|
433
512
|
setTimeout(() => {
|
|
434
|
-
this
|
|
435
|
-
this.
|
|
513
|
+
this.#cachedPromise = null;
|
|
514
|
+
this.#eventSource.notify();
|
|
436
515
|
}, 5e3);
|
|
437
516
|
}
|
|
438
517
|
);
|
|
439
|
-
this
|
|
518
|
+
this.#cachedPromise = promise;
|
|
440
519
|
return promise;
|
|
441
520
|
}
|
|
442
521
|
};
|
|
443
522
|
var SinglePageResource = class {
|
|
523
|
+
observable;
|
|
524
|
+
#eventSource;
|
|
525
|
+
#fetchPage;
|
|
444
526
|
constructor(fetchPage) {
|
|
445
|
-
this
|
|
446
|
-
this
|
|
447
|
-
this.
|
|
448
|
-
this.observable = this._eventSource.observable;
|
|
527
|
+
this.#fetchPage = fetchPage;
|
|
528
|
+
this.#eventSource = makeEventSource();
|
|
529
|
+
this.observable = this.#eventSource.observable;
|
|
449
530
|
autobind(this);
|
|
450
531
|
}
|
|
451
532
|
get() {
|
|
452
|
-
const usable = this
|
|
533
|
+
const usable = this.#cachedPromise;
|
|
453
534
|
if (usable === null || usable.status === "pending") {
|
|
454
535
|
return ASYNC_LOADING;
|
|
455
536
|
}
|
|
@@ -461,95 +542,187 @@ var SinglePageResource = class {
|
|
|
461
542
|
data: void 0
|
|
462
543
|
};
|
|
463
544
|
}
|
|
545
|
+
#cachedPromise = null;
|
|
464
546
|
waitUntilLoaded() {
|
|
465
|
-
if (this
|
|
466
|
-
return this
|
|
547
|
+
if (this.#cachedPromise) {
|
|
548
|
+
return this.#cachedPromise;
|
|
467
549
|
}
|
|
468
550
|
const initialFetcher = autoRetry(
|
|
469
|
-
() => this
|
|
551
|
+
() => this.#fetchPage(),
|
|
470
552
|
5,
|
|
471
553
|
[5e3, 5e3, 1e4, 15e3]
|
|
472
554
|
);
|
|
473
555
|
const promise = usify(initialFetcher);
|
|
474
556
|
promise.then(
|
|
475
|
-
() => this.
|
|
557
|
+
() => this.#eventSource.notify(),
|
|
476
558
|
() => {
|
|
477
|
-
this.
|
|
559
|
+
this.#eventSource.notify();
|
|
478
560
|
setTimeout(() => {
|
|
479
|
-
this
|
|
480
|
-
this.
|
|
561
|
+
this.#cachedPromise = null;
|
|
562
|
+
this.#eventSource.notify();
|
|
481
563
|
}, 5e3);
|
|
482
564
|
}
|
|
483
565
|
);
|
|
484
|
-
this
|
|
566
|
+
this.#cachedPromise = promise;
|
|
485
567
|
return promise;
|
|
486
568
|
}
|
|
487
569
|
};
|
|
488
570
|
var UmbrellaStore = class {
|
|
571
|
+
#client;
|
|
572
|
+
#syncSource;
|
|
573
|
+
//
|
|
574
|
+
// Internally, the UmbrellaStore keeps track of a few source signals that can
|
|
575
|
+
// be set and mutated individually. When any of those are mutated then the
|
|
576
|
+
// clean "external state" is recomputed.
|
|
577
|
+
//
|
|
578
|
+
// Mutate inputs... ...observe clean/consistent output!
|
|
579
|
+
//
|
|
580
|
+
// .-> Base ThreadDB ---------+ +----> Clean threads by ID (Part 1)
|
|
581
|
+
// / | |
|
|
582
|
+
// mutate ----> Base Notifications --+ | | +--> Clean notifications (Part 1)
|
|
583
|
+
// \ | | | | & notifications by ID
|
|
584
|
+
// | \ | | Apply | |
|
|
585
|
+
// | `-> OptimisticUpdates --+--+--> Optimistic --+-+--> Notification Settings (Part 2)
|
|
586
|
+
// \ | Updates |
|
|
587
|
+
// `------- etc etc ---------+ +--> History Versions (Part 3)
|
|
588
|
+
// ^
|
|
589
|
+
// |
|
|
590
|
+
// | ^ ^
|
|
591
|
+
// Signal | |
|
|
592
|
+
// or DerivedSignal DerivedSignals
|
|
593
|
+
// MutableSignal
|
|
594
|
+
//
|
|
595
|
+
//
|
|
596
|
+
// Input signals.
|
|
597
|
+
// (Can be mutated directly.)
|
|
598
|
+
//
|
|
599
|
+
baseThreadsDB;
|
|
600
|
+
// Exposes its signal under `.signal` prop
|
|
601
|
+
baseNotificationsById;
|
|
602
|
+
baseSettingsByRoomId;
|
|
603
|
+
optimisticUpdates;
|
|
604
|
+
baseVersionsByRoomId;
|
|
605
|
+
permissionHintsByRoomId;
|
|
606
|
+
//
|
|
607
|
+
// Output signals.
|
|
608
|
+
// (Readonly, clean, consistent. With optimistic updates applied.)
|
|
609
|
+
//
|
|
610
|
+
// Note that the output of threadifications signal is the same as the ones for
|
|
611
|
+
// threads and notifications separately, but the threadifications signal will
|
|
612
|
+
// be updated whenever either of them change.
|
|
613
|
+
//
|
|
614
|
+
// TODO(vincent+nimesh) APIs like getRoomThreadsLoadingState should really also be modeled as output signals.
|
|
615
|
+
//
|
|
616
|
+
outputs;
|
|
617
|
+
// Notifications
|
|
618
|
+
#notificationsLastRequestedAt = null;
|
|
619
|
+
// Keeps track of when we successfully requested an inbox notifications update for the last time. Will be `null` as long as the first successful fetch hasn't happened yet.
|
|
620
|
+
#notifications;
|
|
621
|
+
// Room Threads
|
|
622
|
+
#roomThreadsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
623
|
+
#roomThreads = /* @__PURE__ */ new Map();
|
|
624
|
+
// User Threads
|
|
625
|
+
#userThreadsLastRequestedAt = null;
|
|
626
|
+
#userThreads = /* @__PURE__ */ new Map();
|
|
627
|
+
// Room versions
|
|
628
|
+
#roomVersions = /* @__PURE__ */ new Map();
|
|
629
|
+
#roomVersionsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
630
|
+
// Room notification settings
|
|
631
|
+
#roomNotificationSettings = /* @__PURE__ */ new Map();
|
|
489
632
|
constructor(client) {
|
|
490
|
-
this
|
|
491
|
-
this
|
|
492
|
-
this._stateCached = null;
|
|
493
|
-
// Notifications
|
|
494
|
-
this._notificationsLastRequestedAt = null;
|
|
495
|
-
// Room Threads
|
|
496
|
-
this._roomThreadsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
497
|
-
this._roomThreads = /* @__PURE__ */ new Map();
|
|
498
|
-
// User Threads
|
|
499
|
-
this._userThreadsLastRequestedAt = null;
|
|
500
|
-
this._userThreads = /* @__PURE__ */ new Map();
|
|
501
|
-
// Room versions
|
|
502
|
-
this._roomVersions = /* @__PURE__ */ new Map();
|
|
503
|
-
this._roomVersionsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
504
|
-
// Room notification settings
|
|
505
|
-
this._roomNotificationSettings = /* @__PURE__ */ new Map();
|
|
506
|
-
this._client = client[kInternal].as();
|
|
507
|
-
this._syncSource = this._client[kInternal].createSyncSource();
|
|
633
|
+
this.#client = client[kInternal].as();
|
|
634
|
+
this.#syncSource = this.#client[kInternal].createSyncSource();
|
|
508
635
|
const inboxFetcher = async (cursor) => {
|
|
509
|
-
const result = await this.
|
|
636
|
+
const result = await this.#client.getInboxNotifications({ cursor });
|
|
510
637
|
this.updateThreadsAndNotifications(
|
|
511
638
|
result.threads,
|
|
512
639
|
result.inboxNotifications
|
|
513
640
|
);
|
|
514
|
-
if (this
|
|
515
|
-
this
|
|
641
|
+
if (this.#notificationsLastRequestedAt === null) {
|
|
642
|
+
this.#notificationsLastRequestedAt = result.requestedAt;
|
|
516
643
|
}
|
|
517
644
|
const nextCursor = result.nextCursor;
|
|
518
645
|
return nextCursor;
|
|
519
646
|
};
|
|
520
|
-
this
|
|
521
|
-
this.
|
|
647
|
+
this.#notifications = new PaginatedResource(inboxFetcher);
|
|
648
|
+
this.#notifications.observable.subscribe(
|
|
522
649
|
() => (
|
|
523
650
|
// Note that the store itself does not change, but it's only vehicle at
|
|
524
651
|
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
525
|
-
this.
|
|
652
|
+
this.invalidateEntireStore()
|
|
653
|
+
)
|
|
654
|
+
);
|
|
655
|
+
this.baseThreadsDB = new ThreadDB();
|
|
656
|
+
this.optimisticUpdates = new Signal([]);
|
|
657
|
+
this.baseVersionsByRoomId = new Signal({});
|
|
658
|
+
this.baseNotificationsById = new Signal({});
|
|
659
|
+
this.baseSettingsByRoomId = new Signal({});
|
|
660
|
+
this.permissionHintsByRoomId = new Signal({});
|
|
661
|
+
const threadifications = DerivedSignal.from(
|
|
662
|
+
this.baseThreadsDB.signal,
|
|
663
|
+
this.baseNotificationsById,
|
|
664
|
+
this.optimisticUpdates,
|
|
665
|
+
(ts, ns, updates) => applyOptimisticUpdates_forThreadifications(ts, ns, updates)
|
|
666
|
+
);
|
|
667
|
+
const threads = DerivedSignal.from(threadifications, (s) => ({
|
|
668
|
+
threadsDB: s.threadsDB
|
|
669
|
+
}));
|
|
670
|
+
const notifications = DerivedSignal.from(threadifications, (s) => ({
|
|
671
|
+
sortedNotifications: s.sortedNotifications,
|
|
672
|
+
notificationsById: s.notificationsById
|
|
673
|
+
}));
|
|
674
|
+
const settingsByRoomId = DerivedSignal.from(
|
|
675
|
+
this.baseSettingsByRoomId,
|
|
676
|
+
this.optimisticUpdates,
|
|
677
|
+
(settings, updates) => applyOptimisticUpdates_forSettings(settings, updates)
|
|
678
|
+
);
|
|
679
|
+
const versionsByRoomId = DerivedSignal.from(
|
|
680
|
+
this.baseVersionsByRoomId,
|
|
681
|
+
(hv) => hv
|
|
682
|
+
);
|
|
683
|
+
this.outputs = {
|
|
684
|
+
threadifications,
|
|
685
|
+
threads,
|
|
686
|
+
notifications,
|
|
687
|
+
settingsByRoomId,
|
|
688
|
+
versionsByRoomId
|
|
689
|
+
};
|
|
690
|
+
this.optimisticUpdates.subscribe(
|
|
691
|
+
() => this.#syncSource.setSyncStatus(
|
|
692
|
+
this.optimisticUpdates.get().length > 0 ? "synchronizing" : "synchronized"
|
|
526
693
|
)
|
|
527
694
|
);
|
|
528
|
-
this._rawThreadsDB = new ThreadDB();
|
|
529
|
-
this._store = createStore({
|
|
530
|
-
optimisticUpdates: [],
|
|
531
|
-
permissionsByRoom: {},
|
|
532
|
-
notificationsById: {},
|
|
533
|
-
settingsByRoomId: {},
|
|
534
|
-
versionsByRoomId: {}
|
|
535
|
-
});
|
|
536
695
|
autobind(this);
|
|
537
696
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
if (this._prevVersion !== this._rawThreadsDB.version || // Note: Version check is only needed temporarily, until we can get rid of the Zustand-like update model
|
|
541
|
-
this._prevState !== rawState || this._stateCached === null) {
|
|
542
|
-
this._stateCached = internalToExternalState(rawState, this._rawThreadsDB);
|
|
543
|
-
this._prevState = rawState;
|
|
544
|
-
this._prevVersion = this._rawThreadsDB.version;
|
|
545
|
-
}
|
|
546
|
-
return this._stateCached;
|
|
697
|
+
get1_both() {
|
|
698
|
+
return this.outputs.threadifications.get();
|
|
547
699
|
}
|
|
548
|
-
|
|
549
|
-
return this.
|
|
700
|
+
subscribe1_both(callback) {
|
|
701
|
+
return this.outputs.threadifications.subscribe(callback);
|
|
550
702
|
}
|
|
551
|
-
|
|
552
|
-
return this.get();
|
|
703
|
+
get1_threads() {
|
|
704
|
+
return this.outputs.threads.get();
|
|
705
|
+
}
|
|
706
|
+
subscribe1_threads(callback) {
|
|
707
|
+
return this.outputs.threads.subscribe(callback);
|
|
708
|
+
}
|
|
709
|
+
get1_notifications() {
|
|
710
|
+
return this.outputs.notifications.get();
|
|
711
|
+
}
|
|
712
|
+
subscribe1_notifications(callback) {
|
|
713
|
+
return this.outputs.notifications.subscribe(callback);
|
|
714
|
+
}
|
|
715
|
+
get2() {
|
|
716
|
+
return this.outputs.settingsByRoomId.get();
|
|
717
|
+
}
|
|
718
|
+
subscribe2(callback) {
|
|
719
|
+
return this.outputs.settingsByRoomId.subscribe(callback);
|
|
720
|
+
}
|
|
721
|
+
get3() {
|
|
722
|
+
return this.outputs.versionsByRoomId.get();
|
|
723
|
+
}
|
|
724
|
+
subscribe3(callback) {
|
|
725
|
+
return this.outputs.versionsByRoomId.subscribe(callback);
|
|
553
726
|
}
|
|
554
727
|
/**
|
|
555
728
|
* Returns the async result of the given query and room id. If the query is success,
|
|
@@ -558,7 +731,7 @@ var UmbrellaStore = class {
|
|
|
558
731
|
*/
|
|
559
732
|
getRoomThreadsLoadingState(roomId, query) {
|
|
560
733
|
const queryKey = makeRoomThreadsQueryKey(roomId, query);
|
|
561
|
-
const paginatedResource = this.
|
|
734
|
+
const paginatedResource = this.#roomThreads.get(queryKey);
|
|
562
735
|
if (paginatedResource === void 0) {
|
|
563
736
|
return ASYNC_LOADING;
|
|
564
737
|
}
|
|
@@ -566,7 +739,7 @@ var UmbrellaStore = class {
|
|
|
566
739
|
if (asyncResult.isLoading || asyncResult.error) {
|
|
567
740
|
return asyncResult;
|
|
568
741
|
}
|
|
569
|
-
const threads = this.
|
|
742
|
+
const threads = this.get1_threads().threadsDB.findMany(
|
|
570
743
|
roomId,
|
|
571
744
|
query ?? {},
|
|
572
745
|
"asc"
|
|
@@ -583,7 +756,7 @@ var UmbrellaStore = class {
|
|
|
583
756
|
}
|
|
584
757
|
getUserThreadsLoadingState(query) {
|
|
585
758
|
const queryKey = makeUserThreadsQueryKey(query);
|
|
586
|
-
const paginatedResource = this.
|
|
759
|
+
const paginatedResource = this.#userThreads.get(queryKey);
|
|
587
760
|
if (paginatedResource === void 0) {
|
|
588
761
|
return ASYNC_LOADING;
|
|
589
762
|
}
|
|
@@ -591,7 +764,7 @@ var UmbrellaStore = class {
|
|
|
591
764
|
if (asyncResult.isLoading || asyncResult.error) {
|
|
592
765
|
return asyncResult;
|
|
593
766
|
}
|
|
594
|
-
const threads = this.
|
|
767
|
+
const threads = this.get1_threads().threadsDB.findMany(
|
|
595
768
|
void 0,
|
|
596
769
|
// Do _not_ filter by roomId
|
|
597
770
|
query ?? {},
|
|
@@ -609,14 +782,14 @@ var UmbrellaStore = class {
|
|
|
609
782
|
}
|
|
610
783
|
// NOTE: This will read the async result, but WILL NOT start loading at the moment!
|
|
611
784
|
getInboxNotificationsLoadingState() {
|
|
612
|
-
const asyncResult = this.
|
|
785
|
+
const asyncResult = this.#notifications.get();
|
|
613
786
|
if (asyncResult.isLoading || asyncResult.error) {
|
|
614
787
|
return asyncResult;
|
|
615
788
|
}
|
|
616
789
|
const page = asyncResult.data;
|
|
617
790
|
return {
|
|
618
791
|
isLoading: false,
|
|
619
|
-
inboxNotifications: this.
|
|
792
|
+
inboxNotifications: this.get1_notifications().sortedNotifications,
|
|
620
793
|
hasFetchedAll: page.hasFetchedAll,
|
|
621
794
|
isFetchingMore: page.isFetchingMore,
|
|
622
795
|
fetchMoreError: page.fetchMoreError,
|
|
@@ -624,9 +797,10 @@ var UmbrellaStore = class {
|
|
|
624
797
|
};
|
|
625
798
|
}
|
|
626
799
|
// NOTE: This will read the async result, but WILL NOT start loading at the moment!
|
|
800
|
+
// TODO(vincent+nimesh) This should really be a derived Signal!
|
|
627
801
|
getNotificationSettingsLoadingState(roomId) {
|
|
628
802
|
const queryKey = makeNotificationSettingsQueryKey(roomId);
|
|
629
|
-
const resource = this.
|
|
803
|
+
const resource = this.#roomNotificationSettings.get(queryKey);
|
|
630
804
|
if (resource === void 0) {
|
|
631
805
|
return ASYNC_LOADING;
|
|
632
806
|
}
|
|
@@ -636,12 +810,12 @@ var UmbrellaStore = class {
|
|
|
636
810
|
}
|
|
637
811
|
return {
|
|
638
812
|
isLoading: false,
|
|
639
|
-
settings: nn(this.
|
|
813
|
+
settings: nn(this.get2()[roomId])
|
|
640
814
|
};
|
|
641
815
|
}
|
|
642
816
|
getRoomVersionsLoadingState(roomId) {
|
|
643
817
|
const queryKey = makeVersionsQueryKey(roomId);
|
|
644
|
-
const resource = this.
|
|
818
|
+
const resource = this.#roomVersions.get(queryKey);
|
|
645
819
|
if (resource === void 0) {
|
|
646
820
|
return ASYNC_LOADING;
|
|
647
821
|
}
|
|
@@ -651,70 +825,53 @@ var UmbrellaStore = class {
|
|
|
651
825
|
}
|
|
652
826
|
return {
|
|
653
827
|
isLoading: false,
|
|
654
|
-
versions: Object.values(this.
|
|
828
|
+
versions: Object.values(this.get3()[roomId] ?? {})
|
|
655
829
|
};
|
|
656
830
|
}
|
|
657
|
-
subscribe(callback) {
|
|
658
|
-
return this._store.subscribe(callback);
|
|
659
|
-
}
|
|
660
|
-
_getPermissions(roomId) {
|
|
661
|
-
return this._store.get().permissionsByRoom[roomId];
|
|
662
|
-
}
|
|
663
831
|
// Direct low-level cache mutations ------------------------------------------------- {{{
|
|
664
|
-
mutateThreadsDB(mutate) {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
mutate(db);
|
|
668
|
-
if (old !== db.version) {
|
|
669
|
-
this._store.set((state) => ({ ...state }));
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
updateInboxNotificationsCache(mapFn) {
|
|
673
|
-
this._store.set((state) => {
|
|
674
|
-
const inboxNotifications = mapFn(state.notificationsById);
|
|
675
|
-
return inboxNotifications !== state.notificationsById ? { ...state, notificationsById: inboxNotifications } : state;
|
|
832
|
+
#mutateThreadsDB(mutate) {
|
|
833
|
+
batch(() => {
|
|
834
|
+
mutate(this.baseThreadsDB);
|
|
676
835
|
});
|
|
677
836
|
}
|
|
678
|
-
|
|
679
|
-
this.
|
|
837
|
+
#updateInboxNotificationsCache(mapFn) {
|
|
838
|
+
this.baseNotificationsById.set((prev) => mapFn(prev));
|
|
839
|
+
}
|
|
840
|
+
#setNotificationSettings(roomId, settings) {
|
|
841
|
+
this.baseSettingsByRoomId.set((state) => ({
|
|
680
842
|
...state,
|
|
681
|
-
|
|
682
|
-
...state.settingsByRoomId,
|
|
683
|
-
[roomId]: settings
|
|
684
|
-
}
|
|
843
|
+
[roomId]: settings
|
|
685
844
|
}));
|
|
686
845
|
}
|
|
687
|
-
updateRoomVersions(roomId, versions) {
|
|
688
|
-
this.
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
|
|
846
|
+
#updateRoomVersions(roomId, versions) {
|
|
847
|
+
this.baseVersionsByRoomId.set((prev) => {
|
|
848
|
+
const newVersions = { ...prev[roomId] };
|
|
849
|
+
for (const version of versions) {
|
|
850
|
+
newVersions[version.id] = version;
|
|
851
|
+
}
|
|
692
852
|
return {
|
|
693
|
-
...
|
|
694
|
-
|
|
695
|
-
...state.versionsByRoomId,
|
|
696
|
-
[roomId]: {
|
|
697
|
-
// Merge with existing versions for the room, or start with an empty object
|
|
698
|
-
...state.versionsByRoomId[roomId] ?? {},
|
|
699
|
-
...versionsById
|
|
700
|
-
}
|
|
701
|
-
}
|
|
853
|
+
...prev,
|
|
854
|
+
[roomId]: newVersions
|
|
702
855
|
};
|
|
703
856
|
});
|
|
704
857
|
}
|
|
705
|
-
updateOptimisticUpdatesCache(mapFn) {
|
|
706
|
-
this.
|
|
707
|
-
const optimisticUpdates = mapFn(state.optimisticUpdates);
|
|
708
|
-
this._syncSource.setSyncStatus(
|
|
709
|
-
optimisticUpdates.length > 0 ? "synchronizing" : "synchronized"
|
|
710
|
-
);
|
|
711
|
-
return { ...state, optimisticUpdates };
|
|
712
|
-
});
|
|
858
|
+
#updateOptimisticUpdatesCache(mapFn) {
|
|
859
|
+
this.optimisticUpdates.set(mapFn);
|
|
713
860
|
}
|
|
714
861
|
// ---------------------------------------------------------------------------------- }}}
|
|
715
862
|
/** @internal - Only call this method from unit tests. */
|
|
716
|
-
|
|
717
|
-
|
|
863
|
+
force_set_versions(callback) {
|
|
864
|
+
batch(() => {
|
|
865
|
+
this.baseVersionsByRoomId.set(callback);
|
|
866
|
+
this.invalidateEntireStore();
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
/** @internal - Only call this method from unit tests. */
|
|
870
|
+
force_set_notifications(callback) {
|
|
871
|
+
batch(() => {
|
|
872
|
+
this.baseNotificationsById.set(callback);
|
|
873
|
+
this.invalidateEntireStore();
|
|
874
|
+
});
|
|
718
875
|
}
|
|
719
876
|
/**
|
|
720
877
|
* Updates an existing inbox notification with a new value, replacing the
|
|
@@ -724,18 +881,17 @@ var UmbrellaStore = class {
|
|
|
724
881
|
* the cache.
|
|
725
882
|
*/
|
|
726
883
|
updateInboxNotification(inboxNotificationId, optimisticUpdateId, callback) {
|
|
727
|
-
|
|
884
|
+
batch(() => {
|
|
728
885
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
729
|
-
this
|
|
886
|
+
this.#updateInboxNotificationsCache((cache) => {
|
|
730
887
|
const existing = cache[inboxNotificationId];
|
|
731
888
|
if (!existing) {
|
|
732
889
|
return cache;
|
|
733
890
|
}
|
|
734
|
-
|
|
891
|
+
return {
|
|
735
892
|
...cache,
|
|
736
893
|
[inboxNotificationId]: callback(existing)
|
|
737
894
|
};
|
|
738
|
-
return inboxNotifications;
|
|
739
895
|
});
|
|
740
896
|
});
|
|
741
897
|
}
|
|
@@ -744,9 +900,9 @@ var UmbrellaStore = class {
|
|
|
744
900
|
* them, replacing the corresponding optimistic update.
|
|
745
901
|
*/
|
|
746
902
|
updateAllInboxNotifications(optimisticUpdateId, mapFn) {
|
|
747
|
-
|
|
903
|
+
batch(() => {
|
|
748
904
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
749
|
-
this
|
|
905
|
+
this.#updateInboxNotificationsCache((cache) => mapValues(cache, mapFn));
|
|
750
906
|
});
|
|
751
907
|
}
|
|
752
908
|
/**
|
|
@@ -754,9 +910,9 @@ var UmbrellaStore = class {
|
|
|
754
910
|
* optimistic update.
|
|
755
911
|
*/
|
|
756
912
|
deleteInboxNotification(inboxNotificationId, optimisticUpdateId) {
|
|
757
|
-
|
|
913
|
+
batch(() => {
|
|
758
914
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
759
|
-
this
|
|
915
|
+
this.#updateInboxNotificationsCache((cache) => {
|
|
760
916
|
const { [inboxNotificationId]: removed, ...newCache } = cache;
|
|
761
917
|
return removed === void 0 ? cache : newCache;
|
|
762
918
|
});
|
|
@@ -767,18 +923,18 @@ var UmbrellaStore = class {
|
|
|
767
923
|
* update.
|
|
768
924
|
*/
|
|
769
925
|
deleteAllInboxNotifications(optimisticUpdateId) {
|
|
770
|
-
|
|
926
|
+
batch(() => {
|
|
771
927
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
772
|
-
this
|
|
928
|
+
this.#updateInboxNotificationsCache(() => ({}));
|
|
773
929
|
});
|
|
774
930
|
}
|
|
775
931
|
/**
|
|
776
932
|
* Creates an new thread, replacing the corresponding optimistic update.
|
|
777
933
|
*/
|
|
778
934
|
createThread(optimisticUpdateId, thread) {
|
|
779
|
-
|
|
935
|
+
batch(() => {
|
|
780
936
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
781
|
-
this
|
|
937
|
+
this.#mutateThreadsDB((db) => db.upsert(thread));
|
|
782
938
|
});
|
|
783
939
|
}
|
|
784
940
|
/**
|
|
@@ -791,12 +947,12 @@ var UmbrellaStore = class {
|
|
|
791
947
|
* - The thread ID in the cache was updated more recently than the optimistic
|
|
792
948
|
* update's timestamp (if given)
|
|
793
949
|
*/
|
|
794
|
-
updateThread(threadId, optimisticUpdateId, callback, updatedAt) {
|
|
795
|
-
|
|
950
|
+
#updateThread(threadId, optimisticUpdateId, callback, updatedAt) {
|
|
951
|
+
batch(() => {
|
|
796
952
|
if (optimisticUpdateId !== null) {
|
|
797
953
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
798
954
|
}
|
|
799
|
-
this
|
|
955
|
+
this.#mutateThreadsDB((db) => {
|
|
800
956
|
const existing = db.get(threadId);
|
|
801
957
|
if (!existing) return;
|
|
802
958
|
if (!!updatedAt && existing.updatedAt > updatedAt) return;
|
|
@@ -805,7 +961,7 @@ var UmbrellaStore = class {
|
|
|
805
961
|
});
|
|
806
962
|
}
|
|
807
963
|
patchThread(threadId, optimisticUpdateId, patch, updatedAt) {
|
|
808
|
-
return this
|
|
964
|
+
return this.#updateThread(
|
|
809
965
|
threadId,
|
|
810
966
|
optimisticUpdateId,
|
|
811
967
|
(thread) => ({ ...thread, ...compactObject(patch) }),
|
|
@@ -813,7 +969,7 @@ var UmbrellaStore = class {
|
|
|
813
969
|
);
|
|
814
970
|
}
|
|
815
971
|
addReaction(threadId, optimisticUpdateId, commentId, reaction, createdAt) {
|
|
816
|
-
this
|
|
972
|
+
this.#updateThread(
|
|
817
973
|
threadId,
|
|
818
974
|
optimisticUpdateId,
|
|
819
975
|
(thread) => applyAddReaction(thread, commentId, reaction),
|
|
@@ -821,7 +977,7 @@ var UmbrellaStore = class {
|
|
|
821
977
|
);
|
|
822
978
|
}
|
|
823
979
|
removeReaction(threadId, optimisticUpdateId, commentId, emoji, userId, removedAt) {
|
|
824
|
-
this
|
|
980
|
+
this.#updateThread(
|
|
825
981
|
threadId,
|
|
826
982
|
optimisticUpdateId,
|
|
827
983
|
(thread) => applyRemoveReaction(thread, commentId, emoji, userId, removedAt),
|
|
@@ -837,7 +993,7 @@ var UmbrellaStore = class {
|
|
|
837
993
|
* - The thread ID was already deleted from the cache
|
|
838
994
|
*/
|
|
839
995
|
deleteThread(threadId, optimisticUpdateId) {
|
|
840
|
-
return this
|
|
996
|
+
return this.#updateThread(
|
|
841
997
|
threadId,
|
|
842
998
|
optimisticUpdateId,
|
|
843
999
|
// A deletion is actually an update of the deletedAt property internally
|
|
@@ -849,16 +1005,16 @@ var UmbrellaStore = class {
|
|
|
849
1005
|
* updated correctly, replacing the corresponding optimistic update.
|
|
850
1006
|
*/
|
|
851
1007
|
createComment(newComment, optimisticUpdateId) {
|
|
852
|
-
|
|
1008
|
+
batch(() => {
|
|
853
1009
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
854
|
-
const existingThread = this.
|
|
1010
|
+
const existingThread = this.baseThreadsDB.get(newComment.threadId);
|
|
855
1011
|
if (!existingThread) {
|
|
856
1012
|
return;
|
|
857
1013
|
}
|
|
858
|
-
this
|
|
1014
|
+
this.#mutateThreadsDB(
|
|
859
1015
|
(db) => db.upsert(applyUpsertComment(existingThread, newComment))
|
|
860
1016
|
);
|
|
861
|
-
this
|
|
1017
|
+
this.#updateInboxNotificationsCache((cache) => {
|
|
862
1018
|
const existingNotification = Object.values(cache).find(
|
|
863
1019
|
(notification) => notification.kind === "thread" && notification.threadId === newComment.threadId
|
|
864
1020
|
);
|
|
@@ -877,14 +1033,14 @@ var UmbrellaStore = class {
|
|
|
877
1033
|
});
|
|
878
1034
|
}
|
|
879
1035
|
editComment(threadId, optimisticUpdateId, editedComment) {
|
|
880
|
-
return this
|
|
1036
|
+
return this.#updateThread(
|
|
881
1037
|
threadId,
|
|
882
1038
|
optimisticUpdateId,
|
|
883
1039
|
(thread) => applyUpsertComment(thread, editedComment)
|
|
884
1040
|
);
|
|
885
1041
|
}
|
|
886
1042
|
deleteComment(threadId, optimisticUpdateId, commentId, deletedAt) {
|
|
887
|
-
return this
|
|
1043
|
+
return this.#updateThread(
|
|
888
1044
|
threadId,
|
|
889
1045
|
optimisticUpdateId,
|
|
890
1046
|
(thread) => applyDeleteComment(thread, commentId, deletedAt),
|
|
@@ -892,10 +1048,10 @@ var UmbrellaStore = class {
|
|
|
892
1048
|
);
|
|
893
1049
|
}
|
|
894
1050
|
updateThreadAndNotification(thread, inboxNotification) {
|
|
895
|
-
|
|
896
|
-
this
|
|
1051
|
+
batch(() => {
|
|
1052
|
+
this.#mutateThreadsDB((db) => db.upsertIfNewer(thread));
|
|
897
1053
|
if (inboxNotification !== void 0) {
|
|
898
|
-
this
|
|
1054
|
+
this.#updateInboxNotificationsCache((cache) => ({
|
|
899
1055
|
...cache,
|
|
900
1056
|
[inboxNotification.id]: inboxNotification
|
|
901
1057
|
}));
|
|
@@ -903,11 +1059,11 @@ var UmbrellaStore = class {
|
|
|
903
1059
|
});
|
|
904
1060
|
}
|
|
905
1061
|
updateThreadsAndNotifications(threads, inboxNotifications, deletedThreads = [], deletedInboxNotifications = []) {
|
|
906
|
-
|
|
907
|
-
this
|
|
1062
|
+
batch(() => {
|
|
1063
|
+
this.#mutateThreadsDB(
|
|
908
1064
|
(db) => applyThreadDeltaUpdates(db, { newThreads: threads, deletedThreads })
|
|
909
1065
|
);
|
|
910
|
-
this
|
|
1066
|
+
this.#updateInboxNotificationsCache(
|
|
911
1067
|
(cache) => applyNotificationsUpdates(cache, {
|
|
912
1068
|
newInboxNotifications: inboxNotifications,
|
|
913
1069
|
deletedNotifications: deletedInboxNotifications
|
|
@@ -920,33 +1076,33 @@ var UmbrellaStore = class {
|
|
|
920
1076
|
* replacing the corresponding optimistic update.
|
|
921
1077
|
*/
|
|
922
1078
|
updateRoomNotificationSettings_confirmOptimisticUpdate(roomId, optimisticUpdateId, settings) {
|
|
923
|
-
|
|
1079
|
+
batch(() => {
|
|
924
1080
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
925
|
-
this
|
|
1081
|
+
this.#setNotificationSettings(roomId, settings);
|
|
926
1082
|
});
|
|
927
1083
|
}
|
|
928
1084
|
addOptimisticUpdate(optimisticUpdate) {
|
|
929
1085
|
const id = nanoid();
|
|
930
1086
|
const newUpdate = { ...optimisticUpdate, id };
|
|
931
|
-
this
|
|
1087
|
+
this.#updateOptimisticUpdatesCache((cache) => [...cache, newUpdate]);
|
|
932
1088
|
return id;
|
|
933
1089
|
}
|
|
934
1090
|
removeOptimisticUpdate(optimisticUpdateId) {
|
|
935
|
-
this
|
|
1091
|
+
this.#updateOptimisticUpdatesCache(
|
|
936
1092
|
(cache) => cache.filter((ou) => ou.id !== optimisticUpdateId)
|
|
937
1093
|
);
|
|
938
1094
|
}
|
|
939
1095
|
async fetchNotificationsDeltaUpdate(signal) {
|
|
940
|
-
const lastRequestedAt = this
|
|
1096
|
+
const lastRequestedAt = this.#notificationsLastRequestedAt;
|
|
941
1097
|
if (lastRequestedAt === null) {
|
|
942
1098
|
return;
|
|
943
1099
|
}
|
|
944
|
-
const result = await this.
|
|
1100
|
+
const result = await this.#client.getInboxNotificationsSince({
|
|
945
1101
|
since: lastRequestedAt,
|
|
946
1102
|
signal
|
|
947
1103
|
});
|
|
948
1104
|
if (lastRequestedAt < result.requestedAt) {
|
|
949
|
-
this
|
|
1105
|
+
this.#notificationsLastRequestedAt = result.requestedAt;
|
|
950
1106
|
}
|
|
951
1107
|
this.updateThreadsAndNotifications(
|
|
952
1108
|
result.threads.updated,
|
|
@@ -956,25 +1112,24 @@ var UmbrellaStore = class {
|
|
|
956
1112
|
);
|
|
957
1113
|
}
|
|
958
1114
|
waitUntilNotificationsLoaded() {
|
|
959
|
-
return this.
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
(permission
|
|
967
|
-
|
|
968
|
-
|
|
1115
|
+
return this.#notifications.waitUntilLoaded();
|
|
1116
|
+
}
|
|
1117
|
+
#updatePermissionHints(newHints) {
|
|
1118
|
+
this.permissionHintsByRoomId.set((prev) => {
|
|
1119
|
+
const permissionsByRoom = { ...prev };
|
|
1120
|
+
for (const [roomId, newPermissions] of Object.entries(newHints)) {
|
|
1121
|
+
const existing = permissionsByRoom[roomId] ?? /* @__PURE__ */ new Set();
|
|
1122
|
+
for (const permission of newPermissions) {
|
|
1123
|
+
existing.add(permission);
|
|
1124
|
+
}
|
|
1125
|
+
permissionsByRoom[roomId] = existing;
|
|
1126
|
+
}
|
|
1127
|
+
return permissionsByRoom;
|
|
969
1128
|
});
|
|
970
|
-
this._store.set((state) => ({
|
|
971
|
-
...state,
|
|
972
|
-
permissionsByRoom
|
|
973
|
-
}));
|
|
974
1129
|
}
|
|
975
1130
|
waitUntilRoomThreadsLoaded(roomId, query) {
|
|
976
1131
|
const threadsFetcher = async (cursor) => {
|
|
977
|
-
const result = await this
|
|
1132
|
+
const result = await this.#client[kInternal].httpClient.getThreads({
|
|
978
1133
|
roomId,
|
|
979
1134
|
cursor,
|
|
980
1135
|
query
|
|
@@ -983,15 +1138,15 @@ var UmbrellaStore = class {
|
|
|
983
1138
|
result.threads,
|
|
984
1139
|
result.inboxNotifications
|
|
985
1140
|
);
|
|
986
|
-
this
|
|
987
|
-
const lastRequestedAt = this.
|
|
1141
|
+
this.#updatePermissionHints(result.permissionHints);
|
|
1142
|
+
const lastRequestedAt = this.#roomThreadsLastRequestedAtByRoom.get(roomId);
|
|
988
1143
|
if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
|
|
989
|
-
this.
|
|
1144
|
+
this.#roomThreadsLastRequestedAtByRoom.set(roomId, result.requestedAt);
|
|
990
1145
|
}
|
|
991
1146
|
return result.nextCursor;
|
|
992
1147
|
};
|
|
993
1148
|
const queryKey = makeRoomThreadsQueryKey(roomId, query);
|
|
994
|
-
let paginatedResource = this.
|
|
1149
|
+
let paginatedResource = this.#roomThreads.get(queryKey);
|
|
995
1150
|
if (paginatedResource === void 0) {
|
|
996
1151
|
paginatedResource = new PaginatedResource(threadsFetcher);
|
|
997
1152
|
}
|
|
@@ -999,18 +1154,18 @@ var UmbrellaStore = class {
|
|
|
999
1154
|
() => (
|
|
1000
1155
|
// Note that the store itself does not change, but it's only vehicle at
|
|
1001
1156
|
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
1002
|
-
this.
|
|
1157
|
+
this.invalidateEntireStore()
|
|
1003
1158
|
)
|
|
1004
1159
|
);
|
|
1005
|
-
this.
|
|
1160
|
+
this.#roomThreads.set(queryKey, paginatedResource);
|
|
1006
1161
|
return paginatedResource.waitUntilLoaded();
|
|
1007
1162
|
}
|
|
1008
1163
|
async fetchRoomThreadsDeltaUpdate(roomId, signal) {
|
|
1009
|
-
const lastRequestedAt = this.
|
|
1164
|
+
const lastRequestedAt = this.#roomThreadsLastRequestedAtByRoom.get(roomId);
|
|
1010
1165
|
if (lastRequestedAt === void 0) {
|
|
1011
1166
|
return;
|
|
1012
1167
|
}
|
|
1013
|
-
const updates = await this
|
|
1168
|
+
const updates = await this.#client[kInternal].httpClient.getThreadsSince({
|
|
1014
1169
|
roomId,
|
|
1015
1170
|
since: lastRequestedAt,
|
|
1016
1171
|
signal
|
|
@@ -1021,15 +1176,15 @@ var UmbrellaStore = class {
|
|
|
1021
1176
|
updates.threads.deleted,
|
|
1022
1177
|
updates.inboxNotifications.deleted
|
|
1023
1178
|
);
|
|
1024
|
-
this
|
|
1179
|
+
this.#updatePermissionHints(updates.permissionHints);
|
|
1025
1180
|
if (lastRequestedAt < updates.requestedAt) {
|
|
1026
|
-
this.
|
|
1181
|
+
this.#roomThreadsLastRequestedAtByRoom.set(roomId, updates.requestedAt);
|
|
1027
1182
|
}
|
|
1028
1183
|
}
|
|
1029
1184
|
waitUntilUserThreadsLoaded(query) {
|
|
1030
1185
|
const queryKey = makeUserThreadsQueryKey(query);
|
|
1031
1186
|
const threadsFetcher = async (cursor) => {
|
|
1032
|
-
const result = await this
|
|
1187
|
+
const result = await this.#client[kInternal].httpClient.getUserThreads_experimental({
|
|
1033
1188
|
cursor,
|
|
1034
1189
|
query
|
|
1035
1190
|
});
|
|
@@ -1037,13 +1192,13 @@ var UmbrellaStore = class {
|
|
|
1037
1192
|
result.threads,
|
|
1038
1193
|
result.inboxNotifications
|
|
1039
1194
|
);
|
|
1040
|
-
this
|
|
1041
|
-
if (this
|
|
1042
|
-
this
|
|
1195
|
+
this.#updatePermissionHints(result.permissionHints);
|
|
1196
|
+
if (this.#userThreadsLastRequestedAt === null) {
|
|
1197
|
+
this.#userThreadsLastRequestedAt = result.requestedAt;
|
|
1043
1198
|
}
|
|
1044
1199
|
return result.nextCursor;
|
|
1045
1200
|
};
|
|
1046
|
-
let paginatedResource = this.
|
|
1201
|
+
let paginatedResource = this.#userThreads.get(queryKey);
|
|
1047
1202
|
if (paginatedResource === void 0) {
|
|
1048
1203
|
paginatedResource = new PaginatedResource(threadsFetcher);
|
|
1049
1204
|
}
|
|
@@ -1051,23 +1206,34 @@ var UmbrellaStore = class {
|
|
|
1051
1206
|
() => (
|
|
1052
1207
|
// Note that the store itself does not change, but it's only vehicle at
|
|
1053
1208
|
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
1054
|
-
this.
|
|
1209
|
+
this.invalidateEntireStore()
|
|
1055
1210
|
)
|
|
1056
1211
|
);
|
|
1057
|
-
this.
|
|
1212
|
+
this.#userThreads.set(queryKey, paginatedResource);
|
|
1058
1213
|
return paginatedResource.waitUntilLoaded();
|
|
1059
1214
|
}
|
|
1215
|
+
// TODO(vincent+nimesh) We should really be going over all call sites, and replace this call
|
|
1216
|
+
// with a more specific invalidation!
|
|
1217
|
+
invalidateEntireStore() {
|
|
1218
|
+
batch(() => {
|
|
1219
|
+
this.baseVersionsByRoomId.set((store) => ({ ...store }));
|
|
1220
|
+
this.baseNotificationsById.set((store) => ({ ...store }));
|
|
1221
|
+
this.optimisticUpdates.set((store) => [...store]);
|
|
1222
|
+
this.permissionHintsByRoomId.set((store) => ({ ...store }));
|
|
1223
|
+
this.baseSettingsByRoomId.set((store) => ({ ...store }));
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1060
1226
|
async fetchUserThreadsDeltaUpdate(signal) {
|
|
1061
|
-
const lastRequestedAt = this
|
|
1227
|
+
const lastRequestedAt = this.#userThreadsLastRequestedAt;
|
|
1062
1228
|
if (lastRequestedAt === null) {
|
|
1063
1229
|
return;
|
|
1064
1230
|
}
|
|
1065
|
-
const result = await this
|
|
1231
|
+
const result = await this.#client[kInternal].httpClient.getUserThreadsSince_experimental({
|
|
1066
1232
|
since: lastRequestedAt,
|
|
1067
1233
|
signal
|
|
1068
1234
|
});
|
|
1069
1235
|
if (lastRequestedAt < result.requestedAt) {
|
|
1070
|
-
this
|
|
1236
|
+
this.#notificationsLastRequestedAt = result.requestedAt;
|
|
1071
1237
|
}
|
|
1072
1238
|
this.updateThreadsAndNotifications(
|
|
1073
1239
|
result.threads.updated,
|
|
@@ -1075,14 +1241,14 @@ var UmbrellaStore = class {
|
|
|
1075
1241
|
result.threads.deleted,
|
|
1076
1242
|
result.inboxNotifications.deleted
|
|
1077
1243
|
);
|
|
1078
|
-
this
|
|
1244
|
+
this.#updatePermissionHints(result.permissionHints);
|
|
1079
1245
|
}
|
|
1080
1246
|
waitUntilRoomVersionsLoaded(roomId) {
|
|
1081
1247
|
const queryKey = makeVersionsQueryKey(roomId);
|
|
1082
|
-
let resource = this.
|
|
1248
|
+
let resource = this.#roomVersions.get(queryKey);
|
|
1083
1249
|
if (resource === void 0) {
|
|
1084
1250
|
const versionsFetcher = async () => {
|
|
1085
|
-
const room = this.
|
|
1251
|
+
const room = this.#client.getRoom(roomId);
|
|
1086
1252
|
if (room === null) {
|
|
1087
1253
|
throw new HttpError(
|
|
1088
1254
|
`Room '${roomId}' is not available on client`,
|
|
@@ -1090,10 +1256,10 @@ var UmbrellaStore = class {
|
|
|
1090
1256
|
);
|
|
1091
1257
|
}
|
|
1092
1258
|
const result = await room[kInternal].listTextVersions();
|
|
1093
|
-
this
|
|
1094
|
-
const lastRequestedAt = this.
|
|
1259
|
+
this.#updateRoomVersions(roomId, result.versions);
|
|
1260
|
+
const lastRequestedAt = this.#roomVersionsLastRequestedAtByRoom.get(roomId);
|
|
1095
1261
|
if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
|
|
1096
|
-
this.
|
|
1262
|
+
this.#roomVersionsLastRequestedAtByRoom.set(
|
|
1097
1263
|
roomId,
|
|
1098
1264
|
result.requestedAt
|
|
1099
1265
|
);
|
|
@@ -1105,36 +1271,36 @@ var UmbrellaStore = class {
|
|
|
1105
1271
|
() => (
|
|
1106
1272
|
// Note that the store itself does not change, but it's only vehicle at
|
|
1107
1273
|
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
1108
|
-
this.
|
|
1274
|
+
this.invalidateEntireStore()
|
|
1109
1275
|
)
|
|
1110
1276
|
);
|
|
1111
|
-
this.
|
|
1277
|
+
this.#roomVersions.set(queryKey, resource);
|
|
1112
1278
|
return resource.waitUntilLoaded();
|
|
1113
1279
|
}
|
|
1114
1280
|
async fetchRoomVersionsDeltaUpdate(roomId, signal) {
|
|
1115
|
-
const lastRequestedAt = this.
|
|
1281
|
+
const lastRequestedAt = this.#roomVersionsLastRequestedAtByRoom.get(roomId);
|
|
1116
1282
|
if (lastRequestedAt === void 0) {
|
|
1117
1283
|
return;
|
|
1118
1284
|
}
|
|
1119
1285
|
const room = nn(
|
|
1120
|
-
this.
|
|
1286
|
+
this.#client.getRoom(roomId),
|
|
1121
1287
|
`Room with id ${roomId} is not available on client`
|
|
1122
1288
|
);
|
|
1123
1289
|
const updates = await room[kInternal].listTextVersionsSince({
|
|
1124
1290
|
since: lastRequestedAt,
|
|
1125
1291
|
signal
|
|
1126
1292
|
});
|
|
1127
|
-
this
|
|
1293
|
+
this.#updateRoomVersions(roomId, updates.versions);
|
|
1128
1294
|
if (lastRequestedAt < updates.requestedAt) {
|
|
1129
|
-
this.
|
|
1295
|
+
this.#roomVersionsLastRequestedAtByRoom.set(roomId, updates.requestedAt);
|
|
1130
1296
|
}
|
|
1131
1297
|
}
|
|
1132
1298
|
waitUntilRoomNotificationSettingsLoaded(roomId) {
|
|
1133
1299
|
const queryKey = makeNotificationSettingsQueryKey(roomId);
|
|
1134
|
-
let resource = this.
|
|
1300
|
+
let resource = this.#roomNotificationSettings.get(queryKey);
|
|
1135
1301
|
if (resource === void 0) {
|
|
1136
1302
|
const notificationSettingsFetcher = async () => {
|
|
1137
|
-
const room = this.
|
|
1303
|
+
const room = this.#client.getRoom(roomId);
|
|
1138
1304
|
if (room === null) {
|
|
1139
1305
|
throw new HttpError(
|
|
1140
1306
|
`Room '${roomId}' is not available on client`,
|
|
@@ -1142,7 +1308,7 @@ var UmbrellaStore = class {
|
|
|
1142
1308
|
);
|
|
1143
1309
|
}
|
|
1144
1310
|
const result = await room.getNotificationSettings();
|
|
1145
|
-
this
|
|
1311
|
+
this.#setNotificationSettings(roomId, result);
|
|
1146
1312
|
};
|
|
1147
1313
|
resource = new SinglePageResource(notificationSettingsFetcher);
|
|
1148
1314
|
}
|
|
@@ -1150,28 +1316,25 @@ var UmbrellaStore = class {
|
|
|
1150
1316
|
() => (
|
|
1151
1317
|
// Note that the store itself does not change, but it's only vehicle at
|
|
1152
1318
|
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
1153
|
-
this.
|
|
1319
|
+
this.invalidateEntireStore()
|
|
1154
1320
|
)
|
|
1155
1321
|
);
|
|
1156
|
-
this.
|
|
1322
|
+
this.#roomNotificationSettings.set(queryKey, resource);
|
|
1157
1323
|
return resource.waitUntilLoaded();
|
|
1158
1324
|
}
|
|
1159
1325
|
async refreshRoomNotificationSettings(roomId, signal) {
|
|
1160
1326
|
const room = nn(
|
|
1161
|
-
this.
|
|
1327
|
+
this.#client.getRoom(roomId),
|
|
1162
1328
|
`Room with id ${roomId} is not available on client`
|
|
1163
1329
|
);
|
|
1164
1330
|
const result = await room.getNotificationSettings({ signal });
|
|
1165
|
-
this
|
|
1331
|
+
this.#setNotificationSettings(roomId, result);
|
|
1166
1332
|
}
|
|
1167
1333
|
};
|
|
1168
|
-
function
|
|
1169
|
-
const threadsDB =
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
settingsByRoomId: { ...state.settingsByRoomId }
|
|
1173
|
-
};
|
|
1174
|
-
for (const optimisticUpdate of state.optimisticUpdates) {
|
|
1334
|
+
function applyOptimisticUpdates_forThreadifications(baseThreadsDB, rawNotificationsById, optimisticUpdates) {
|
|
1335
|
+
const threadsDB = baseThreadsDB.clone();
|
|
1336
|
+
let notificationsById = { ...rawNotificationsById };
|
|
1337
|
+
for (const optimisticUpdate of optimisticUpdates) {
|
|
1175
1338
|
switch (optimisticUpdate.type) {
|
|
1176
1339
|
case "create-thread": {
|
|
1177
1340
|
threadsDB.upsert(optimisticUpdate.thread);
|
|
@@ -1209,15 +1372,13 @@ function internalToExternalState(state, rawThreadsDB) {
|
|
|
1209
1372
|
const thread = threadsDB.get(optimisticUpdate.comment.threadId);
|
|
1210
1373
|
if (thread === void 0) break;
|
|
1211
1374
|
threadsDB.upsert(applyUpsertComment(thread, optimisticUpdate.comment));
|
|
1212
|
-
const inboxNotification = Object.values(
|
|
1213
|
-
computed.notificationsById
|
|
1214
|
-
).find(
|
|
1375
|
+
const inboxNotification = Object.values(notificationsById).find(
|
|
1215
1376
|
(notification) => notification.kind === "thread" && notification.threadId === thread.id
|
|
1216
1377
|
);
|
|
1217
1378
|
if (inboxNotification === void 0) {
|
|
1218
1379
|
break;
|
|
1219
1380
|
}
|
|
1220
|
-
|
|
1381
|
+
notificationsById[inboxNotification.id] = {
|
|
1221
1382
|
...inboxNotification,
|
|
1222
1383
|
notifiedAt: optimisticUpdate.comment.createdAt,
|
|
1223
1384
|
readAt: optimisticUpdate.comment.createdAt
|
|
@@ -1280,23 +1441,23 @@ function internalToExternalState(state, rawThreadsDB) {
|
|
|
1280
1441
|
break;
|
|
1281
1442
|
}
|
|
1282
1443
|
case "mark-inbox-notification-as-read": {
|
|
1283
|
-
const ibn =
|
|
1444
|
+
const ibn = notificationsById[optimisticUpdate.inboxNotificationId];
|
|
1284
1445
|
if (ibn === void 0) {
|
|
1285
1446
|
break;
|
|
1286
1447
|
}
|
|
1287
|
-
|
|
1448
|
+
notificationsById[optimisticUpdate.inboxNotificationId] = {
|
|
1288
1449
|
...ibn,
|
|
1289
1450
|
readAt: optimisticUpdate.readAt
|
|
1290
1451
|
};
|
|
1291
1452
|
break;
|
|
1292
1453
|
}
|
|
1293
1454
|
case "mark-all-inbox-notifications-as-read": {
|
|
1294
|
-
for (const id in
|
|
1295
|
-
const ibn =
|
|
1455
|
+
for (const id in notificationsById) {
|
|
1456
|
+
const ibn = notificationsById[id];
|
|
1296
1457
|
if (ibn === void 0) {
|
|
1297
1458
|
break;
|
|
1298
1459
|
}
|
|
1299
|
-
|
|
1460
|
+
notificationsById[id] = {
|
|
1300
1461
|
...ibn,
|
|
1301
1462
|
readAt: optimisticUpdate.readAt
|
|
1302
1463
|
};
|
|
@@ -1304,38 +1465,44 @@ function internalToExternalState(state, rawThreadsDB) {
|
|
|
1304
1465
|
break;
|
|
1305
1466
|
}
|
|
1306
1467
|
case "delete-inbox-notification": {
|
|
1307
|
-
delete
|
|
1468
|
+
delete notificationsById[optimisticUpdate.inboxNotificationId];
|
|
1308
1469
|
break;
|
|
1309
1470
|
}
|
|
1310
1471
|
case "delete-all-inbox-notifications": {
|
|
1311
|
-
|
|
1472
|
+
notificationsById = {};
|
|
1312
1473
|
break;
|
|
1313
1474
|
}
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
const sortedNotifications = (
|
|
1478
|
+
// Sort so that the most recent notifications are first
|
|
1479
|
+
Object.values(notificationsById).filter(
|
|
1480
|
+
(ibn) => ibn.kind === "thread" ? threadsDB.get(ibn.threadId) !== void 0 : true
|
|
1481
|
+
).sort((a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime())
|
|
1482
|
+
);
|
|
1483
|
+
return {
|
|
1484
|
+
sortedNotifications,
|
|
1485
|
+
notificationsById,
|
|
1486
|
+
threadsDB
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
function applyOptimisticUpdates_forSettings(baseSettingsByRoomId, optimisticUpdates) {
|
|
1490
|
+
const settingsByRoomId = { ...baseSettingsByRoomId };
|
|
1491
|
+
for (const optimisticUpdate of optimisticUpdates) {
|
|
1492
|
+
switch (optimisticUpdate.type) {
|
|
1314
1493
|
case "update-notification-settings": {
|
|
1315
|
-
const settings =
|
|
1494
|
+
const settings = settingsByRoomId[optimisticUpdate.roomId];
|
|
1316
1495
|
if (settings === void 0) {
|
|
1317
1496
|
break;
|
|
1318
1497
|
}
|
|
1319
|
-
|
|
1498
|
+
settingsByRoomId[optimisticUpdate.roomId] = {
|
|
1320
1499
|
...settings,
|
|
1321
1500
|
...optimisticUpdate.settings
|
|
1322
1501
|
};
|
|
1323
1502
|
}
|
|
1324
1503
|
}
|
|
1325
1504
|
}
|
|
1326
|
-
|
|
1327
|
-
// Sort so that the most recent notifications are first
|
|
1328
|
-
Object.values(computed.notificationsById).filter(
|
|
1329
|
-
(ibn) => ibn.kind === "thread" ? threadsDB.get(ibn.threadId) !== void 0 : true
|
|
1330
|
-
).sort((a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime())
|
|
1331
|
-
);
|
|
1332
|
-
return {
|
|
1333
|
-
cleanedNotifications,
|
|
1334
|
-
notificationsById: computed.notificationsById,
|
|
1335
|
-
settingsByRoomId: computed.settingsByRoomId,
|
|
1336
|
-
threadsDB,
|
|
1337
|
-
versionsByRoomId: state.versionsByRoomId
|
|
1338
|
-
};
|
|
1505
|
+
return settingsByRoomId;
|
|
1339
1506
|
}
|
|
1340
1507
|
function applyThreadDeltaUpdates(db, updates) {
|
|
1341
1508
|
updates.newThreads.forEach((thread) => db.upsertIfNewer(thread));
|
|
@@ -1542,6 +1709,7 @@ function upsertReaction(reactions, reaction) {
|
|
|
1542
1709
|
}
|
|
1543
1710
|
|
|
1544
1711
|
// src/liveblocks.tsx
|
|
1712
|
+
import { jsx } from "react/jsx-runtime";
|
|
1545
1713
|
var ClientContext = createContext2(null);
|
|
1546
1714
|
function missingUserError(userId) {
|
|
1547
1715
|
return new Error(`resolveUsers didn't return anything for user '${userId}'`);
|
|
@@ -1675,7 +1843,7 @@ function makeLiveblocksContextBundle(client) {
|
|
|
1675
1843
|
const useDeleteAllInboxNotifications2 = () => useDeleteAllInboxNotifications_withClient(client);
|
|
1676
1844
|
function LiveblocksProvider2(props) {
|
|
1677
1845
|
useEnsureNoLiveblocksProvider();
|
|
1678
|
-
return /* @__PURE__ */
|
|
1846
|
+
return /* @__PURE__ */ jsx(ClientContext.Provider, { value: client, children: props.children });
|
|
1679
1847
|
}
|
|
1680
1848
|
const shared = createSharedContext(client);
|
|
1681
1849
|
const bundle = {
|
|
@@ -1706,10 +1874,10 @@ function makeLiveblocksContextBundle(client) {
|
|
|
1706
1874
|
}
|
|
1707
1875
|
function useInboxNotifications_withClient(client, selector, isEqual) {
|
|
1708
1876
|
const { store, notificationsPoller: poller } = getLiveblocksExtrasForClient(client);
|
|
1709
|
-
|
|
1877
|
+
useEffect3(() => {
|
|
1710
1878
|
void store.waitUntilNotificationsLoaded();
|
|
1711
1879
|
});
|
|
1712
|
-
|
|
1880
|
+
useEffect3(() => {
|
|
1713
1881
|
poller.inc();
|
|
1714
1882
|
poller.pollNowIfStale();
|
|
1715
1883
|
return () => {
|
|
@@ -1717,7 +1885,7 @@ function useInboxNotifications_withClient(client, selector, isEqual) {
|
|
|
1717
1885
|
};
|
|
1718
1886
|
}, [poller]);
|
|
1719
1887
|
return useSyncExternalStoreWithSelector(
|
|
1720
|
-
store.
|
|
1888
|
+
store.subscribe1_threads,
|
|
1721
1889
|
store.getInboxNotificationsLoadingState,
|
|
1722
1890
|
store.getInboxNotificationsLoadingState,
|
|
1723
1891
|
selector,
|
|
@@ -1839,7 +2007,7 @@ function useDeleteAllInboxNotifications_withClient(client) {
|
|
|
1839
2007
|
}
|
|
1840
2008
|
function useInboxNotificationThread_withClient(client, inboxNotificationId) {
|
|
1841
2009
|
const { store } = getLiveblocksExtrasForClient(client);
|
|
1842
|
-
const getter = store.
|
|
2010
|
+
const getter = store.get1_both;
|
|
1843
2011
|
const selector = useCallback2(
|
|
1844
2012
|
(state) => {
|
|
1845
2013
|
const inboxNotification = state.notificationsById[inboxNotificationId] ?? raise(`Inbox notification with ID "${inboxNotificationId}" not found`);
|
|
@@ -1856,7 +2024,7 @@ function useInboxNotificationThread_withClient(client, inboxNotificationId) {
|
|
|
1856
2024
|
[inboxNotificationId]
|
|
1857
2025
|
);
|
|
1858
2026
|
return useSyncExternalStoreWithSelector(
|
|
1859
|
-
store.
|
|
2027
|
+
store.subscribe1_both,
|
|
1860
2028
|
// Re-evaluate if we need to update any time the notification changes over time
|
|
1861
2029
|
getter,
|
|
1862
2030
|
getter,
|
|
@@ -1880,7 +2048,7 @@ function useUser_withClient(client, userId) {
|
|
|
1880
2048
|
selector,
|
|
1881
2049
|
shallow3
|
|
1882
2050
|
);
|
|
1883
|
-
|
|
2051
|
+
useEffect3(() => {
|
|
1884
2052
|
void usersStore.get(userId);
|
|
1885
2053
|
}, [usersStore, userId, result]);
|
|
1886
2054
|
return result;
|
|
@@ -1901,7 +2069,7 @@ function useUserSuspense_withClient(client, userId) {
|
|
|
1901
2069
|
if (!userState.data) {
|
|
1902
2070
|
throw missingUserError(userId);
|
|
1903
2071
|
}
|
|
1904
|
-
const state =
|
|
2072
|
+
const state = useSyncExternalStore2(
|
|
1905
2073
|
usersStore.subscribe,
|
|
1906
2074
|
getUserState,
|
|
1907
2075
|
getUserState
|
|
@@ -1932,7 +2100,7 @@ function useRoomInfo_withClient(client, roomId) {
|
|
|
1932
2100
|
selector,
|
|
1933
2101
|
shallow3
|
|
1934
2102
|
);
|
|
1935
|
-
|
|
2103
|
+
useEffect3(() => {
|
|
1936
2104
|
void roomsInfoStore.get(roomId);
|
|
1937
2105
|
}, [roomsInfoStore, roomId, result]);
|
|
1938
2106
|
return result;
|
|
@@ -1953,7 +2121,7 @@ function useRoomInfoSuspense_withClient(client, roomId) {
|
|
|
1953
2121
|
if (!roomInfoState.data) {
|
|
1954
2122
|
throw missingRoomInfoError(roomId);
|
|
1955
2123
|
}
|
|
1956
|
-
const state =
|
|
2124
|
+
const state = useSyncExternalStore2(
|
|
1957
2125
|
roomsInfoStore.subscribe,
|
|
1958
2126
|
getRoomInfoState,
|
|
1959
2127
|
getRoomInfoState
|
|
@@ -2006,7 +2174,7 @@ function useClient() {
|
|
|
2006
2174
|
}
|
|
2007
2175
|
function LiveblocksProviderWithClient(props) {
|
|
2008
2176
|
useEnsureNoLiveblocksProvider(props);
|
|
2009
|
-
return /* @__PURE__ */
|
|
2177
|
+
return /* @__PURE__ */ jsx(ClientContext.Provider, { value: props.client, children: props.children });
|
|
2010
2178
|
}
|
|
2011
2179
|
function LiveblocksProvider(props) {
|
|
2012
2180
|
const { children, ...o } = props;
|
|
@@ -2034,8 +2202,8 @@ function LiveblocksProvider(props) {
|
|
|
2034
2202
|
o.enableDebugLogging
|
|
2035
2203
|
)
|
|
2036
2204
|
};
|
|
2037
|
-
const client =
|
|
2038
|
-
return /* @__PURE__ */
|
|
2205
|
+
const client = useMemo2(() => createClient(options), []);
|
|
2206
|
+
return /* @__PURE__ */ jsx(LiveblocksProviderWithClient, { client, children });
|
|
2039
2207
|
}
|
|
2040
2208
|
function createLiveblocksContext(client) {
|
|
2041
2209
|
return getOrCreateContextBundle(client);
|
|
@@ -2047,7 +2215,7 @@ function useUserThreads_experimental(options = {
|
|
|
2047
2215
|
}) {
|
|
2048
2216
|
const client = useClient();
|
|
2049
2217
|
const { store, userThreadsPoller: poller } = getLiveblocksExtrasForClient(client);
|
|
2050
|
-
|
|
2218
|
+
useEffect3(
|
|
2051
2219
|
() => {
|
|
2052
2220
|
void store.waitUntilUserThreadsLoaded(options.query);
|
|
2053
2221
|
}
|
|
@@ -2060,7 +2228,7 @@ function useUserThreads_experimental(options = {
|
|
|
2060
2228
|
// 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
|
|
2061
2229
|
// *next* render after that, a *new* fetch/promise will get created.
|
|
2062
2230
|
);
|
|
2063
|
-
|
|
2231
|
+
useEffect3(() => {
|
|
2064
2232
|
poller.inc();
|
|
2065
2233
|
poller.pollNowIfStale();
|
|
2066
2234
|
return () => {
|
|
@@ -2072,7 +2240,7 @@ function useUserThreads_experimental(options = {
|
|
|
2072
2240
|
[store, options.query]
|
|
2073
2241
|
);
|
|
2074
2242
|
return useSyncExternalStoreWithSelector(
|
|
2075
|
-
store.
|
|
2243
|
+
store.subscribe1_threads,
|
|
2076
2244
|
getter,
|
|
2077
2245
|
getter,
|
|
2078
2246
|
identity,
|
|
@@ -2151,7 +2319,7 @@ function useSyncStatus_withClient(client, options) {
|
|
|
2151
2319
|
}
|
|
2152
2320
|
}
|
|
2153
2321
|
function useSyncStatusImmediate_withClient(client) {
|
|
2154
|
-
return
|
|
2322
|
+
return useSyncExternalStore2(
|
|
2155
2323
|
client.events.syncStatus.subscribe,
|
|
2156
2324
|
client.getSyncStatus,
|
|
2157
2325
|
client.getSyncStatus
|
|
@@ -2159,9 +2327,9 @@ function useSyncStatusImmediate_withClient(client) {
|
|
|
2159
2327
|
}
|
|
2160
2328
|
function useSyncStatusSmooth_withClient(client) {
|
|
2161
2329
|
const getter = client.getSyncStatus;
|
|
2162
|
-
const [status, setStatus] =
|
|
2330
|
+
const [status, setStatus] = useState(getter);
|
|
2163
2331
|
const oldStatus = useLatest(getter());
|
|
2164
|
-
|
|
2332
|
+
useEffect3(() => {
|
|
2165
2333
|
let timeoutId;
|
|
2166
2334
|
const unsub = client.events.syncStatus.subscribe(() => {
|
|
2167
2335
|
const newStatus = getter();
|
|
@@ -2281,6 +2449,18 @@ var UpdateNotificationSettingsError = class extends Error {
|
|
|
2281
2449
|
}
|
|
2282
2450
|
};
|
|
2283
2451
|
|
|
2452
|
+
// src/use-signal.ts
|
|
2453
|
+
var identity2 = (value) => value;
|
|
2454
|
+
function useSignal(signal, selector, isEqual) {
|
|
2455
|
+
return useSyncExternalStoreWithSelector(
|
|
2456
|
+
signal.subscribe,
|
|
2457
|
+
signal.get,
|
|
2458
|
+
signal.get,
|
|
2459
|
+
selector ?? identity2,
|
|
2460
|
+
isEqual
|
|
2461
|
+
);
|
|
2462
|
+
}
|
|
2463
|
+
|
|
2284
2464
|
// src/room.tsx
|
|
2285
2465
|
import { shallow as shallow4 } from "@liveblocks/client";
|
|
2286
2466
|
import {
|
|
@@ -2288,7 +2468,6 @@ import {
|
|
|
2288
2468
|
console as console3,
|
|
2289
2469
|
createCommentId,
|
|
2290
2470
|
createThreadId,
|
|
2291
|
-
deprecateIf,
|
|
2292
2471
|
errorIf,
|
|
2293
2472
|
HttpError as HttpError2,
|
|
2294
2473
|
kInternal as kInternal3,
|
|
@@ -2296,11 +2475,18 @@ import {
|
|
|
2296
2475
|
makePoller as makePoller2,
|
|
2297
2476
|
ServerMsgCode
|
|
2298
2477
|
} from "@liveblocks/core";
|
|
2299
|
-
import
|
|
2300
|
-
|
|
2478
|
+
import {
|
|
2479
|
+
useCallback as useCallback3,
|
|
2480
|
+
useEffect as useEffect5,
|
|
2481
|
+
useMemo as useMemo3,
|
|
2482
|
+
useRef as useRef3,
|
|
2483
|
+
useState as useState2,
|
|
2484
|
+
useSyncExternalStore as useSyncExternalStore3,
|
|
2485
|
+
version as reactVersion
|
|
2486
|
+
} from "react";
|
|
2301
2487
|
|
|
2302
2488
|
// src/use-scroll-to-comment-on-load-effect.ts
|
|
2303
|
-
import
|
|
2489
|
+
import { useEffect as useEffect4 } from "react";
|
|
2304
2490
|
function handleScrollToCommentOnLoad(shouldScrollOnLoad, state) {
|
|
2305
2491
|
if (shouldScrollOnLoad === false) return;
|
|
2306
2492
|
if (!state.threads) return;
|
|
@@ -2319,7 +2505,7 @@ function handleScrollToCommentOnLoad(shouldScrollOnLoad, state) {
|
|
|
2319
2505
|
comment.scrollIntoView();
|
|
2320
2506
|
}
|
|
2321
2507
|
function useScrollToCommentOnLoadEffect(shouldScrollOnLoad, state) {
|
|
2322
|
-
|
|
2508
|
+
useEffect4(
|
|
2323
2509
|
() => {
|
|
2324
2510
|
handleScrollToCommentOnLoad(shouldScrollOnLoad, state);
|
|
2325
2511
|
},
|
|
@@ -2329,24 +2515,10 @@ function useScrollToCommentOnLoadEffect(shouldScrollOnLoad, state) {
|
|
|
2329
2515
|
}
|
|
2330
2516
|
|
|
2331
2517
|
// src/room.tsx
|
|
2518
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
2332
2519
|
var noop3 = () => {
|
|
2333
2520
|
};
|
|
2334
|
-
var
|
|
2335
|
-
var missing_unstable_batchedUpdates = (reactVersion, roomId) => `We noticed you\u2019re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you\u2019re ready to upgrade to React 18:
|
|
2336
|
-
|
|
2337
|
-
import { unstable_batchedUpdates } from "react-dom"; // or "react-native"
|
|
2338
|
-
|
|
2339
|
-
<RoomProvider id=${JSON.stringify(
|
|
2340
|
-
roomId
|
|
2341
|
-
)} ... unstable_batchedUpdates={unstable_batchedUpdates}>
|
|
2342
|
-
...
|
|
2343
|
-
</RoomProvider>
|
|
2344
|
-
|
|
2345
|
-
Why? Please see https://liveblocks.io/docs/platform/troubleshooting#stale-props-zombie-child for more information`;
|
|
2346
|
-
var superfluous_unstable_batchedUpdates = "You don\u2019t need to pass unstable_batchedUpdates to RoomProvider anymore, since you\u2019re on React 18+ already.";
|
|
2347
|
-
function useSyncExternalStore2(s, gs, gss) {
|
|
2348
|
-
return useSyncExternalStoreWithSelector2(s, gs, gss, identity2);
|
|
2349
|
-
}
|
|
2521
|
+
var identity3 = (x) => x;
|
|
2350
2522
|
var STABLE_EMPTY_LIST = Object.freeze([]);
|
|
2351
2523
|
function alwaysEmptyList() {
|
|
2352
2524
|
return STABLE_EMPTY_LIST;
|
|
@@ -2387,7 +2559,7 @@ function makeMutationContext(room) {
|
|
|
2387
2559
|
};
|
|
2388
2560
|
}
|
|
2389
2561
|
function getCurrentUserId(client) {
|
|
2390
|
-
const userId = client[kInternal3].
|
|
2562
|
+
const userId = client[kInternal3].currentUserId.get();
|
|
2391
2563
|
if (userId === void 0) {
|
|
2392
2564
|
return "anonymous";
|
|
2393
2565
|
}
|
|
@@ -2506,7 +2678,7 @@ function makeRoomExtrasForClient(client) {
|
|
|
2506
2678
|
}
|
|
2507
2679
|
function makeRoomContextBundle(client) {
|
|
2508
2680
|
function RoomProvider_withImplicitLiveblocksProvider(props) {
|
|
2509
|
-
return /* @__PURE__ */
|
|
2681
|
+
return /* @__PURE__ */ jsx2(LiveblocksProviderWithClient, { client, allowNesting: true, children: /* @__PURE__ */ jsx2(RoomProvider, { ...props }) });
|
|
2510
2682
|
}
|
|
2511
2683
|
const shared = createSharedContext(client);
|
|
2512
2684
|
const bundle = {
|
|
@@ -2610,10 +2782,10 @@ function makeRoomContextBundle(client) {
|
|
|
2610
2782
|
}
|
|
2611
2783
|
function RoomProvider(props) {
|
|
2612
2784
|
const client = useClient();
|
|
2613
|
-
const [cache] =
|
|
2785
|
+
const [cache] = useState2(
|
|
2614
2786
|
() => /* @__PURE__ */ new Map()
|
|
2615
2787
|
);
|
|
2616
|
-
const stableEnterRoom =
|
|
2788
|
+
const stableEnterRoom = useCallback3(
|
|
2617
2789
|
(roomId, options) => {
|
|
2618
2790
|
const cached = cache.get(roomId);
|
|
2619
2791
|
if (cached) return cached;
|
|
@@ -2628,7 +2800,7 @@ function RoomProvider(props) {
|
|
|
2628
2800
|
},
|
|
2629
2801
|
[client, cache]
|
|
2630
2802
|
);
|
|
2631
|
-
return /* @__PURE__ */
|
|
2803
|
+
return /* @__PURE__ */ jsx2(
|
|
2632
2804
|
RoomProviderInner,
|
|
2633
2805
|
{
|
|
2634
2806
|
...props,
|
|
@@ -2648,31 +2820,26 @@ function RoomProviderInner(props) {
|
|
|
2648
2820
|
if (!isString(roomId)) {
|
|
2649
2821
|
throw new Error("RoomProvider id property should be a string.");
|
|
2650
2822
|
}
|
|
2651
|
-
const majorReactVersion = parseInt(
|
|
2652
|
-
const
|
|
2823
|
+
const majorReactVersion = parseInt(reactVersion) || 1;
|
|
2824
|
+
const requiredVersion = 18;
|
|
2653
2825
|
errorIf(
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
);
|
|
2657
|
-
deprecateIf(
|
|
2658
|
-
!oldReactVersion && props.unstable_batchedUpdates !== void 0,
|
|
2659
|
-
superfluous_unstable_batchedUpdates
|
|
2826
|
+
majorReactVersion < requiredVersion,
|
|
2827
|
+
`React ${requiredVersion} or higher is required (you\u2019re on ${reactVersion})`
|
|
2660
2828
|
);
|
|
2661
2829
|
}
|
|
2662
2830
|
const frozenProps = useInitial({
|
|
2663
2831
|
initialPresence: props.initialPresence,
|
|
2664
2832
|
initialStorage: props.initialStorage,
|
|
2665
|
-
unstable_batchedUpdates: props.unstable_batchedUpdates,
|
|
2666
2833
|
autoConnect: props.autoConnect ?? typeof window !== "undefined"
|
|
2667
2834
|
});
|
|
2668
|
-
const [{ room }, setRoomLeavePair] =
|
|
2835
|
+
const [{ room }, setRoomLeavePair] = useState2(
|
|
2669
2836
|
() => stableEnterRoom(roomId, {
|
|
2670
2837
|
...frozenProps,
|
|
2671
2838
|
autoConnect: false
|
|
2672
2839
|
// Deliberately using false here on the first render, see below
|
|
2673
2840
|
})
|
|
2674
2841
|
);
|
|
2675
|
-
|
|
2842
|
+
useEffect5(() => {
|
|
2676
2843
|
const { store } = getRoomExtrasForClient(client);
|
|
2677
2844
|
async function handleCommentEvent(message) {
|
|
2678
2845
|
if (message.type === ServerMsgCode.THREAD_DELETED) {
|
|
@@ -2685,7 +2852,7 @@ function RoomProviderInner(props) {
|
|
|
2685
2852
|
return;
|
|
2686
2853
|
}
|
|
2687
2854
|
const { thread, inboxNotification } = info;
|
|
2688
|
-
const existingThread = store.
|
|
2855
|
+
const existingThread = store.get1_threads().threadsDB.getEvenIfDeleted(message.threadId);
|
|
2689
2856
|
switch (message.type) {
|
|
2690
2857
|
case ServerMsgCode.COMMENT_EDITED:
|
|
2691
2858
|
case ServerMsgCode.THREAD_METADATA_UPDATED:
|
|
@@ -2707,7 +2874,7 @@ function RoomProviderInner(props) {
|
|
|
2707
2874
|
(message) => void handleCommentEvent(message)
|
|
2708
2875
|
);
|
|
2709
2876
|
}, [client, room]);
|
|
2710
|
-
|
|
2877
|
+
useEffect5(() => {
|
|
2711
2878
|
const pair = stableEnterRoom(roomId, frozenProps);
|
|
2712
2879
|
setRoomLeavePair(pair);
|
|
2713
2880
|
const { room: room2, leave } = pair;
|
|
@@ -2718,7 +2885,7 @@ function RoomProviderInner(props) {
|
|
|
2718
2885
|
leave();
|
|
2719
2886
|
};
|
|
2720
2887
|
}, [roomId, frozenProps, stableEnterRoom]);
|
|
2721
|
-
return /* @__PURE__ */
|
|
2888
|
+
return /* @__PURE__ */ jsx2(RoomContext.Provider, { value: room, children: props.children });
|
|
2722
2889
|
}
|
|
2723
2890
|
function useRoom() {
|
|
2724
2891
|
const room = useRoomOrNull();
|
|
@@ -2732,12 +2899,12 @@ function useStatus() {
|
|
|
2732
2899
|
const subscribe = room.events.status.subscribe;
|
|
2733
2900
|
const getSnapshot = room.getStatus;
|
|
2734
2901
|
const getServerSnapshot = room.getStatus;
|
|
2735
|
-
return
|
|
2902
|
+
return useSyncExternalStore3(subscribe, getSnapshot, getServerSnapshot);
|
|
2736
2903
|
}
|
|
2737
2904
|
function useReportTextEditor(editor, rootKey) {
|
|
2738
|
-
const isReported =
|
|
2905
|
+
const isReported = useRef3(false);
|
|
2739
2906
|
const room = useRoom();
|
|
2740
|
-
|
|
2907
|
+
useEffect5(() => {
|
|
2741
2908
|
if (isReported.current) {
|
|
2742
2909
|
return;
|
|
2743
2910
|
}
|
|
@@ -2750,6 +2917,52 @@ function useReportTextEditor(editor, rootKey) {
|
|
|
2750
2917
|
return unsubscribe;
|
|
2751
2918
|
}, [room, editor, rootKey]);
|
|
2752
2919
|
}
|
|
2920
|
+
function useYjsProvider() {
|
|
2921
|
+
const room = useRoom();
|
|
2922
|
+
const subscribe = useCallback3(
|
|
2923
|
+
(onStoreChange) => {
|
|
2924
|
+
return room[kInternal3].yjsProviderDidChange.subscribe(onStoreChange);
|
|
2925
|
+
},
|
|
2926
|
+
[room]
|
|
2927
|
+
);
|
|
2928
|
+
const getSnapshot = useCallback3(() => {
|
|
2929
|
+
return room[kInternal3].getYjsProvider();
|
|
2930
|
+
}, [room]);
|
|
2931
|
+
return useSyncExternalStore3(subscribe, getSnapshot, getSnapshot);
|
|
2932
|
+
}
|
|
2933
|
+
function useCreateTextMention() {
|
|
2934
|
+
const room = useRoom();
|
|
2935
|
+
return useCallback3(
|
|
2936
|
+
(userId, mentionId) => {
|
|
2937
|
+
room[kInternal3].createTextMention(userId, mentionId).catch((err) => {
|
|
2938
|
+
console3.error(
|
|
2939
|
+
`Cannot create text mention for user '${userId}' and mention '${mentionId}'`,
|
|
2940
|
+
err
|
|
2941
|
+
);
|
|
2942
|
+
});
|
|
2943
|
+
},
|
|
2944
|
+
[room]
|
|
2945
|
+
);
|
|
2946
|
+
}
|
|
2947
|
+
function useDeleteTextMention() {
|
|
2948
|
+
const room = useRoom();
|
|
2949
|
+
return useCallback3(
|
|
2950
|
+
(mentionId) => {
|
|
2951
|
+
room[kInternal3].deleteTextMention(mentionId).catch((err) => {
|
|
2952
|
+
console3.error(`Cannot delete text mention '${mentionId}'`, err);
|
|
2953
|
+
});
|
|
2954
|
+
},
|
|
2955
|
+
[room]
|
|
2956
|
+
);
|
|
2957
|
+
}
|
|
2958
|
+
function useResolveMentionSuggestions() {
|
|
2959
|
+
const client = useClient();
|
|
2960
|
+
return client[kInternal3].resolveMentionSuggestions;
|
|
2961
|
+
}
|
|
2962
|
+
function useMentionSuggestionsCache() {
|
|
2963
|
+
const client = useClient();
|
|
2964
|
+
return client[kInternal3].mentionSuggestionsCache;
|
|
2965
|
+
}
|
|
2753
2966
|
function useStorageStatus(options) {
|
|
2754
2967
|
const smooth = useInitial(options?.smooth ?? false);
|
|
2755
2968
|
if (smooth) {
|
|
@@ -2763,13 +2976,13 @@ function useStorageStatusImmediate() {
|
|
|
2763
2976
|
const subscribe = room.events.storageStatus.subscribe;
|
|
2764
2977
|
const getSnapshot = room.getStorageStatus;
|
|
2765
2978
|
const getServerSnapshot = room.getStorageStatus;
|
|
2766
|
-
return
|
|
2979
|
+
return useSyncExternalStore3(subscribe, getSnapshot, getServerSnapshot);
|
|
2767
2980
|
}
|
|
2768
2981
|
function useStorageStatusSmooth() {
|
|
2769
2982
|
const room = useRoom();
|
|
2770
|
-
const [status, setStatus] =
|
|
2983
|
+
const [status, setStatus] = useState2(room.getStorageStatus);
|
|
2771
2984
|
const oldStatus = useLatest(room.getStorageStatus());
|
|
2772
|
-
|
|
2985
|
+
useEffect5(() => {
|
|
2773
2986
|
let timeoutId;
|
|
2774
2987
|
const unsub = room.events.storageStatus.subscribe((newStatus) => {
|
|
2775
2988
|
if (oldStatus.current === "synchronizing" && newStatus === "synchronized") {
|
|
@@ -2791,7 +3004,7 @@ function useBatch() {
|
|
|
2791
3004
|
}
|
|
2792
3005
|
function useBroadcastEvent() {
|
|
2793
3006
|
const room = useRoom();
|
|
2794
|
-
return
|
|
3007
|
+
return useCallback3(
|
|
2795
3008
|
(event, options = { shouldQueueEventIfNotReady: false }) => {
|
|
2796
3009
|
room.broadcastEvent(event, options);
|
|
2797
3010
|
},
|
|
@@ -2801,7 +3014,7 @@ function useBroadcastEvent() {
|
|
|
2801
3014
|
function useOthersListener(callback) {
|
|
2802
3015
|
const room = useRoom();
|
|
2803
3016
|
const savedCallback = useLatest(callback);
|
|
2804
|
-
|
|
3017
|
+
useEffect5(
|
|
2805
3018
|
() => room.events.others.subscribe((event) => savedCallback.current(event)),
|
|
2806
3019
|
[room, savedCallback]
|
|
2807
3020
|
);
|
|
@@ -2809,7 +3022,7 @@ function useOthersListener(callback) {
|
|
|
2809
3022
|
function useLostConnectionListener(callback) {
|
|
2810
3023
|
const room = useRoom();
|
|
2811
3024
|
const savedCallback = useLatest(callback);
|
|
2812
|
-
|
|
3025
|
+
useEffect5(
|
|
2813
3026
|
() => room.events.lostConnection.subscribe(
|
|
2814
3027
|
(event) => savedCallback.current(event)
|
|
2815
3028
|
),
|
|
@@ -2819,7 +3032,7 @@ function useLostConnectionListener(callback) {
|
|
|
2819
3032
|
function useErrorListener(callback) {
|
|
2820
3033
|
const room = useRoom();
|
|
2821
3034
|
const savedCallback = useLatest(callback);
|
|
2822
|
-
|
|
3035
|
+
useEffect5(
|
|
2823
3036
|
() => room.events.error.subscribe((e) => savedCallback.current(e)),
|
|
2824
3037
|
[room, savedCallback]
|
|
2825
3038
|
);
|
|
@@ -2827,7 +3040,7 @@ function useErrorListener(callback) {
|
|
|
2827
3040
|
function useEventListener(callback) {
|
|
2828
3041
|
const room = useRoom();
|
|
2829
3042
|
const savedCallback = useLatest(callback);
|
|
2830
|
-
|
|
3043
|
+
useEffect5(() => {
|
|
2831
3044
|
const listener = (eventData) => {
|
|
2832
3045
|
savedCallback.current(eventData);
|
|
2833
3046
|
};
|
|
@@ -2847,25 +3060,25 @@ function useCanUndo() {
|
|
|
2847
3060
|
const room = useRoom();
|
|
2848
3061
|
const subscribe = room.events.history.subscribe;
|
|
2849
3062
|
const canUndo = room.history.canUndo;
|
|
2850
|
-
return
|
|
3063
|
+
return useSyncExternalStore3(subscribe, canUndo, canUndo);
|
|
2851
3064
|
}
|
|
2852
3065
|
function useCanRedo() {
|
|
2853
3066
|
const room = useRoom();
|
|
2854
3067
|
const subscribe = room.events.history.subscribe;
|
|
2855
3068
|
const canRedo = room.history.canRedo;
|
|
2856
|
-
return
|
|
3069
|
+
return useSyncExternalStore3(subscribe, canRedo, canRedo);
|
|
2857
3070
|
}
|
|
2858
3071
|
function useSelf(maybeSelector, isEqual) {
|
|
2859
3072
|
const room = useRoom();
|
|
2860
3073
|
const subscribe = room.events.self.subscribe;
|
|
2861
3074
|
const getSnapshot = room.getSelf;
|
|
2862
|
-
const selector = maybeSelector ??
|
|
2863
|
-
const wrappedSelector =
|
|
3075
|
+
const selector = maybeSelector ?? identity3;
|
|
3076
|
+
const wrappedSelector = useCallback3(
|
|
2864
3077
|
(me) => me !== null ? selector(me) : null,
|
|
2865
3078
|
[selector]
|
|
2866
3079
|
);
|
|
2867
3080
|
const getServerSnapshot = alwaysNull;
|
|
2868
|
-
return
|
|
3081
|
+
return useSyncExternalStoreWithSelector(
|
|
2869
3082
|
subscribe,
|
|
2870
3083
|
getSnapshot,
|
|
2871
3084
|
getServerSnapshot,
|
|
@@ -2877,7 +3090,7 @@ function useMyPresence() {
|
|
|
2877
3090
|
const room = useRoom();
|
|
2878
3091
|
const subscribe = room.events.myPresence.subscribe;
|
|
2879
3092
|
const getSnapshot = room.getPresence;
|
|
2880
|
-
const presence =
|
|
3093
|
+
const presence = useSyncExternalStore3(subscribe, getSnapshot, getSnapshot);
|
|
2881
3094
|
const setPresence = room.updatePresence;
|
|
2882
3095
|
return [presence, setPresence];
|
|
2883
3096
|
}
|
|
@@ -2889,20 +3102,20 @@ function useOthers(selector, isEqual) {
|
|
|
2889
3102
|
const subscribe = room.events.others.subscribe;
|
|
2890
3103
|
const getSnapshot = room.getOthers;
|
|
2891
3104
|
const getServerSnapshot = alwaysEmptyList;
|
|
2892
|
-
return
|
|
3105
|
+
return useSyncExternalStoreWithSelector(
|
|
2893
3106
|
subscribe,
|
|
2894
3107
|
getSnapshot,
|
|
2895
3108
|
getServerSnapshot,
|
|
2896
|
-
selector ??
|
|
3109
|
+
selector ?? identity3,
|
|
2897
3110
|
isEqual
|
|
2898
3111
|
);
|
|
2899
3112
|
}
|
|
2900
3113
|
function useOthersMapped(itemSelector, itemIsEqual) {
|
|
2901
|
-
const wrappedSelector =
|
|
3114
|
+
const wrappedSelector = useCallback3(
|
|
2902
3115
|
(others) => others.map((other) => [other.connectionId, itemSelector(other)]),
|
|
2903
3116
|
[itemSelector]
|
|
2904
3117
|
);
|
|
2905
|
-
const wrappedIsEqual =
|
|
3118
|
+
const wrappedIsEqual = useCallback3(
|
|
2906
3119
|
(a, b) => {
|
|
2907
3120
|
const eq = itemIsEqual ?? Object.is;
|
|
2908
3121
|
return a.length === b.length && a.every((atuple, index) => {
|
|
@@ -2919,14 +3132,14 @@ function useOthersConnectionIds() {
|
|
|
2919
3132
|
}
|
|
2920
3133
|
var NOT_FOUND = Symbol();
|
|
2921
3134
|
function useOther(connectionId, selector, isEqual) {
|
|
2922
|
-
const wrappedSelector =
|
|
3135
|
+
const wrappedSelector = useCallback3(
|
|
2923
3136
|
(others) => {
|
|
2924
3137
|
const other2 = others.find((other3) => other3.connectionId === connectionId);
|
|
2925
3138
|
return other2 !== void 0 ? selector(other2) : NOT_FOUND;
|
|
2926
3139
|
},
|
|
2927
3140
|
[connectionId, selector]
|
|
2928
3141
|
);
|
|
2929
|
-
const wrappedIsEqual =
|
|
3142
|
+
const wrappedIsEqual = useCallback3(
|
|
2930
3143
|
(prev, curr) => {
|
|
2931
3144
|
if (prev === NOT_FOUND || curr === NOT_FOUND) {
|
|
2932
3145
|
return prev === curr;
|
|
@@ -2949,7 +3162,7 @@ function useMutableStorageRoot() {
|
|
|
2949
3162
|
const subscribe = room.events.storageDidLoad.subscribeOnce;
|
|
2950
3163
|
const getSnapshot = room.getStorageSnapshot;
|
|
2951
3164
|
const getServerSnapshot = alwaysNull;
|
|
2952
|
-
return
|
|
3165
|
+
return useSyncExternalStore3(subscribe, getSnapshot, getServerSnapshot);
|
|
2953
3166
|
}
|
|
2954
3167
|
function useStorageRoot() {
|
|
2955
3168
|
return [useMutableStorageRoot()];
|
|
@@ -2957,15 +3170,15 @@ function useStorageRoot() {
|
|
|
2957
3170
|
function useStorage(selector, isEqual) {
|
|
2958
3171
|
const room = useRoom();
|
|
2959
3172
|
const rootOrNull = useMutableStorageRoot();
|
|
2960
|
-
const wrappedSelector =
|
|
3173
|
+
const wrappedSelector = useCallback3(
|
|
2961
3174
|
(rootOrNull2) => rootOrNull2 !== null ? selector(rootOrNull2) : null,
|
|
2962
3175
|
[selector]
|
|
2963
3176
|
);
|
|
2964
|
-
const subscribe =
|
|
3177
|
+
const subscribe = useCallback3(
|
|
2965
3178
|
(onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) : noop3,
|
|
2966
3179
|
[room, rootOrNull]
|
|
2967
3180
|
);
|
|
2968
|
-
const getSnapshot =
|
|
3181
|
+
const getSnapshot = useCallback3(() => {
|
|
2969
3182
|
if (rootOrNull === null) {
|
|
2970
3183
|
return null;
|
|
2971
3184
|
} else {
|
|
@@ -2975,7 +3188,7 @@ function useStorage(selector, isEqual) {
|
|
|
2975
3188
|
}
|
|
2976
3189
|
}, [rootOrNull]);
|
|
2977
3190
|
const getServerSnapshot = alwaysNull;
|
|
2978
|
-
return
|
|
3191
|
+
return useSyncExternalStoreWithSelector(
|
|
2979
3192
|
subscribe,
|
|
2980
3193
|
getSnapshot,
|
|
2981
3194
|
getServerSnapshot,
|
|
@@ -2985,7 +3198,7 @@ function useStorage(selector, isEqual) {
|
|
|
2985
3198
|
}
|
|
2986
3199
|
function useMutation(callback, deps) {
|
|
2987
3200
|
const room = useRoom();
|
|
2988
|
-
return
|
|
3201
|
+
return useMemo3(
|
|
2989
3202
|
() => {
|
|
2990
3203
|
return (...args) => (
|
|
2991
3204
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
@@ -3012,7 +3225,7 @@ function useThreads(options = {
|
|
|
3012
3225
|
const room = useRoom();
|
|
3013
3226
|
const { store, getOrCreateThreadsPollerForRoomId } = getRoomExtrasForClient(client);
|
|
3014
3227
|
const poller = getOrCreateThreadsPollerForRoomId(room.id);
|
|
3015
|
-
|
|
3228
|
+
useEffect5(
|
|
3016
3229
|
() => {
|
|
3017
3230
|
void store.waitUntilRoomThreadsLoaded(room.id, options.query);
|
|
3018
3231
|
}
|
|
@@ -3025,20 +3238,20 @@ function useThreads(options = {
|
|
|
3025
3238
|
// 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
|
|
3026
3239
|
// *next* render after that, a *new* fetch/promise will get created.
|
|
3027
3240
|
);
|
|
3028
|
-
|
|
3241
|
+
useEffect5(() => {
|
|
3029
3242
|
poller.inc();
|
|
3030
3243
|
poller.pollNowIfStale();
|
|
3031
3244
|
return () => poller.dec();
|
|
3032
3245
|
}, [poller]);
|
|
3033
|
-
const getter =
|
|
3246
|
+
const getter = useCallback3(
|
|
3034
3247
|
() => store.getRoomThreadsLoadingState(room.id, options.query),
|
|
3035
3248
|
[store, room.id, options.query]
|
|
3036
3249
|
);
|
|
3037
|
-
const state =
|
|
3038
|
-
store.
|
|
3250
|
+
const state = useSyncExternalStoreWithSelector(
|
|
3251
|
+
store.subscribe1_threads,
|
|
3039
3252
|
getter,
|
|
3040
3253
|
getter,
|
|
3041
|
-
|
|
3254
|
+
identity3,
|
|
3042
3255
|
shallow2
|
|
3043
3256
|
// NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
|
|
3044
3257
|
);
|
|
@@ -3049,7 +3262,7 @@ function useCommentsErrorListener(callback) {
|
|
|
3049
3262
|
const client = useClient();
|
|
3050
3263
|
const savedCallback = useLatest(callback);
|
|
3051
3264
|
const { commentsErrorEventSource } = getRoomExtrasForClient(client);
|
|
3052
|
-
|
|
3265
|
+
useEffect5(() => {
|
|
3053
3266
|
return commentsErrorEventSource.subscribe(savedCallback.current);
|
|
3054
3267
|
}, [savedCallback, commentsErrorEventSource]);
|
|
3055
3268
|
}
|
|
@@ -3058,7 +3271,7 @@ function useCreateThread() {
|
|
|
3058
3271
|
}
|
|
3059
3272
|
function useCreateRoomThread(roomId) {
|
|
3060
3273
|
const client = useClient();
|
|
3061
|
-
return
|
|
3274
|
+
return useCallback3(
|
|
3062
3275
|
(options) => {
|
|
3063
3276
|
const body = options.body;
|
|
3064
3277
|
const metadata = options.metadata ?? {};
|
|
@@ -3127,11 +3340,11 @@ function useDeleteThread() {
|
|
|
3127
3340
|
}
|
|
3128
3341
|
function useDeleteRoomThread(roomId) {
|
|
3129
3342
|
const client = useClient();
|
|
3130
|
-
return
|
|
3343
|
+
return useCallback3(
|
|
3131
3344
|
(threadId) => {
|
|
3132
3345
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3133
3346
|
const userId = getCurrentUserId(client);
|
|
3134
|
-
const existing = store.
|
|
3347
|
+
const existing = store.get1_threads().threadsDB.get(threadId);
|
|
3135
3348
|
if (existing?.comments?.[0]?.userId !== userId) {
|
|
3136
3349
|
throw new Error("Only the thread creator can delete the thread");
|
|
3137
3350
|
}
|
|
@@ -3160,7 +3373,7 @@ function useEditThreadMetadata() {
|
|
|
3160
3373
|
}
|
|
3161
3374
|
function useEditRoomThreadMetadata(roomId) {
|
|
3162
3375
|
const client = useClient();
|
|
3163
|
-
return
|
|
3376
|
+
return useCallback3(
|
|
3164
3377
|
(options) => {
|
|
3165
3378
|
if (!options.metadata) {
|
|
3166
3379
|
return;
|
|
@@ -3204,7 +3417,7 @@ function useCreateComment() {
|
|
|
3204
3417
|
}
|
|
3205
3418
|
function useCreateRoomComment(roomId) {
|
|
3206
3419
|
const client = useClient();
|
|
3207
|
-
return
|
|
3420
|
+
return useCallback3(
|
|
3208
3421
|
({ threadId, body, attachments }) => {
|
|
3209
3422
|
const commentId = createCommentId();
|
|
3210
3423
|
const createdAt = /* @__PURE__ */ new Date();
|
|
@@ -3250,11 +3463,11 @@ function useEditComment() {
|
|
|
3250
3463
|
}
|
|
3251
3464
|
function useEditRoomComment(roomId) {
|
|
3252
3465
|
const client = useClient();
|
|
3253
|
-
return
|
|
3466
|
+
return useCallback3(
|
|
3254
3467
|
({ threadId, commentId, body, attachments }) => {
|
|
3255
3468
|
const editedAt = /* @__PURE__ */ new Date();
|
|
3256
3469
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3257
|
-
const existing = store.
|
|
3470
|
+
const existing = store.get1_threads().threadsDB.getEvenIfDeleted(threadId);
|
|
3258
3471
|
if (existing === void 0) {
|
|
3259
3472
|
console3.warn(
|
|
3260
3473
|
`Internal unexpected behavior. Cannot edit comment in thread "${threadId}" because the thread does not exist in the cache.`
|
|
@@ -3304,7 +3517,7 @@ function useDeleteComment() {
|
|
|
3304
3517
|
}
|
|
3305
3518
|
function useDeleteRoomComment(roomId) {
|
|
3306
3519
|
const client = useClient();
|
|
3307
|
-
return
|
|
3520
|
+
return useCallback3(
|
|
3308
3521
|
({ threadId, commentId }) => {
|
|
3309
3522
|
const deletedAt = /* @__PURE__ */ new Date();
|
|
3310
3523
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
@@ -3343,7 +3556,7 @@ function useAddReaction() {
|
|
|
3343
3556
|
}
|
|
3344
3557
|
function useAddRoomCommentReaction(roomId) {
|
|
3345
3558
|
const client = useClient();
|
|
3346
|
-
return
|
|
3559
|
+
return useCallback3(
|
|
3347
3560
|
({ threadId, commentId, emoji }) => {
|
|
3348
3561
|
const createdAt = /* @__PURE__ */ new Date();
|
|
3349
3562
|
const userId = getCurrentUserId(client);
|
|
@@ -3388,7 +3601,7 @@ function useRemoveReaction() {
|
|
|
3388
3601
|
}
|
|
3389
3602
|
function useRemoveRoomCommentReaction(roomId) {
|
|
3390
3603
|
const client = useClient();
|
|
3391
|
-
return
|
|
3604
|
+
return useCallback3(
|
|
3392
3605
|
({ threadId, commentId, emoji }) => {
|
|
3393
3606
|
const userId = getCurrentUserId(client);
|
|
3394
3607
|
const removedAt = /* @__PURE__ */ new Date();
|
|
@@ -3432,11 +3645,11 @@ function useMarkThreadAsRead() {
|
|
|
3432
3645
|
}
|
|
3433
3646
|
function useMarkRoomThreadAsRead(roomId) {
|
|
3434
3647
|
const client = useClient();
|
|
3435
|
-
return
|
|
3648
|
+
return useCallback3(
|
|
3436
3649
|
(threadId) => {
|
|
3437
3650
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3438
3651
|
const inboxNotification = Object.values(
|
|
3439
|
-
store.
|
|
3652
|
+
store.get1_notifications().notificationsById
|
|
3440
3653
|
).find(
|
|
3441
3654
|
(inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
|
|
3442
3655
|
);
|
|
@@ -3478,7 +3691,7 @@ function useMarkThreadAsResolved() {
|
|
|
3478
3691
|
}
|
|
3479
3692
|
function useMarkRoomThreadAsResolved(roomId) {
|
|
3480
3693
|
const client = useClient();
|
|
3481
|
-
return
|
|
3694
|
+
return useCallback3(
|
|
3482
3695
|
(threadId) => {
|
|
3483
3696
|
const updatedAt = /* @__PURE__ */ new Date();
|
|
3484
3697
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
@@ -3514,7 +3727,7 @@ function useMarkThreadAsUnresolved() {
|
|
|
3514
3727
|
}
|
|
3515
3728
|
function useMarkRoomThreadAsUnresolved(roomId) {
|
|
3516
3729
|
const client = useClient();
|
|
3517
|
-
return
|
|
3730
|
+
return useCallback3(
|
|
3518
3731
|
(threadId) => {
|
|
3519
3732
|
const updatedAt = /* @__PURE__ */ new Date();
|
|
3520
3733
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
@@ -3548,9 +3761,10 @@ function useMarkRoomThreadAsUnresolved(roomId) {
|
|
|
3548
3761
|
function useThreadSubscription(threadId) {
|
|
3549
3762
|
const client = useClient();
|
|
3550
3763
|
const { store } = getRoomExtrasForClient(client);
|
|
3551
|
-
const
|
|
3764
|
+
const signal = store.outputs.threadifications;
|
|
3765
|
+
const selector = useCallback3(
|
|
3552
3766
|
(state) => {
|
|
3553
|
-
const notification = state.
|
|
3767
|
+
const notification = state.sortedNotifications.find(
|
|
3554
3768
|
(inboxNotification) => inboxNotification.kind === "thread" && inboxNotification.threadId === threadId
|
|
3555
3769
|
);
|
|
3556
3770
|
const thread = state.threadsDB.get(threadId);
|
|
@@ -3564,12 +3778,7 @@ function useThreadSubscription(threadId) {
|
|
|
3564
3778
|
},
|
|
3565
3779
|
[threadId]
|
|
3566
3780
|
);
|
|
3567
|
-
return
|
|
3568
|
-
store.subscribe,
|
|
3569
|
-
store.getFullState,
|
|
3570
|
-
store.getFullState,
|
|
3571
|
-
selector
|
|
3572
|
-
);
|
|
3781
|
+
return useSignal(signal, selector, shallow4);
|
|
3573
3782
|
}
|
|
3574
3783
|
function useRoomNotificationSettings() {
|
|
3575
3784
|
const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
|
|
@@ -3577,7 +3786,7 @@ function useRoomNotificationSettings() {
|
|
|
3577
3786
|
const room = useRoom();
|
|
3578
3787
|
const { store, getOrCreateNotificationsSettingsPollerForRoomId } = getRoomExtrasForClient(client);
|
|
3579
3788
|
const poller = getOrCreateNotificationsSettingsPollerForRoomId(room.id);
|
|
3580
|
-
|
|
3789
|
+
useEffect5(
|
|
3581
3790
|
() => {
|
|
3582
3791
|
void store.waitUntilRoomNotificationSettingsLoaded(room.id);
|
|
3583
3792
|
}
|
|
@@ -3590,25 +3799,25 @@ function useRoomNotificationSettings() {
|
|
|
3590
3799
|
// 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
|
|
3591
3800
|
// *next* render after that, a *new* fetch/promise will get created.
|
|
3592
3801
|
);
|
|
3593
|
-
|
|
3802
|
+
useEffect5(() => {
|
|
3594
3803
|
poller.inc();
|
|
3595
3804
|
poller.pollNowIfStale();
|
|
3596
3805
|
return () => {
|
|
3597
3806
|
poller.dec();
|
|
3598
3807
|
};
|
|
3599
3808
|
}, [poller]);
|
|
3600
|
-
const getter =
|
|
3809
|
+
const getter = useCallback3(
|
|
3601
3810
|
() => store.getNotificationSettingsLoadingState(room.id),
|
|
3602
3811
|
[store, room.id]
|
|
3603
3812
|
);
|
|
3604
|
-
const settings =
|
|
3605
|
-
store.
|
|
3813
|
+
const settings = useSyncExternalStoreWithSelector(
|
|
3814
|
+
store.subscribe2,
|
|
3606
3815
|
getter,
|
|
3607
3816
|
getter,
|
|
3608
|
-
|
|
3817
|
+
identity3,
|
|
3609
3818
|
shallow2
|
|
3610
3819
|
);
|
|
3611
|
-
return
|
|
3820
|
+
return useMemo3(() => {
|
|
3612
3821
|
return [settings, updateRoomNotificationSettings];
|
|
3613
3822
|
}, [settings, updateRoomNotificationSettings]);
|
|
3614
3823
|
}
|
|
@@ -3620,16 +3829,16 @@ function useRoomNotificationSettingsSuspense() {
|
|
|
3620
3829
|
const [settings, updateRoomNotificationSettings] = useRoomNotificationSettings();
|
|
3621
3830
|
assert2(!settings.error, "Did not expect error");
|
|
3622
3831
|
assert2(!settings.isLoading, "Did not expect loading");
|
|
3623
|
-
return
|
|
3832
|
+
return useMemo3(() => {
|
|
3624
3833
|
return [settings, updateRoomNotificationSettings];
|
|
3625
3834
|
}, [settings, updateRoomNotificationSettings]);
|
|
3626
3835
|
}
|
|
3627
3836
|
function useHistoryVersionData(versionId) {
|
|
3628
|
-
const [state, setState] =
|
|
3837
|
+
const [state, setState] = useState2({
|
|
3629
3838
|
isLoading: true
|
|
3630
3839
|
});
|
|
3631
3840
|
const room = useRoom();
|
|
3632
|
-
|
|
3841
|
+
useEffect5(() => {
|
|
3633
3842
|
setState({ isLoading: true });
|
|
3634
3843
|
const load = async () => {
|
|
3635
3844
|
try {
|
|
@@ -3658,16 +3867,16 @@ function useHistoryVersions() {
|
|
|
3658
3867
|
const room = useRoom();
|
|
3659
3868
|
const { store, getOrCreateVersionsPollerForRoomId } = getRoomExtrasForClient(client);
|
|
3660
3869
|
const poller = getOrCreateVersionsPollerForRoomId(room.id);
|
|
3661
|
-
|
|
3870
|
+
useEffect5(() => {
|
|
3662
3871
|
poller.inc();
|
|
3663
3872
|
poller.pollNowIfStale();
|
|
3664
3873
|
return () => poller.dec();
|
|
3665
3874
|
}, [poller]);
|
|
3666
|
-
const getter =
|
|
3875
|
+
const getter = useCallback3(
|
|
3667
3876
|
() => store.getRoomVersionsLoadingState(room.id),
|
|
3668
3877
|
[store, room.id]
|
|
3669
3878
|
);
|
|
3670
|
-
|
|
3879
|
+
useEffect5(
|
|
3671
3880
|
() => {
|
|
3672
3881
|
void store.waitUntilRoomVersionsLoaded(room.id);
|
|
3673
3882
|
}
|
|
@@ -3680,11 +3889,11 @@ function useHistoryVersions() {
|
|
|
3680
3889
|
// 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
|
|
3681
3890
|
// *next* render after that, a *new* fetch/promise will get created.
|
|
3682
3891
|
);
|
|
3683
|
-
const state =
|
|
3684
|
-
store.
|
|
3892
|
+
const state = useSyncExternalStoreWithSelector(
|
|
3893
|
+
store.subscribe3,
|
|
3685
3894
|
getter,
|
|
3686
3895
|
getter,
|
|
3687
|
-
|
|
3896
|
+
identity3,
|
|
3688
3897
|
shallow2
|
|
3689
3898
|
);
|
|
3690
3899
|
return state;
|
|
@@ -3702,7 +3911,7 @@ function useHistoryVersionsSuspense() {
|
|
|
3702
3911
|
function useUpdateRoomNotificationSettings() {
|
|
3703
3912
|
const client = useClient();
|
|
3704
3913
|
const room = useRoom();
|
|
3705
|
-
return
|
|
3914
|
+
return useCallback3(
|
|
3706
3915
|
(settings) => {
|
|
3707
3916
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3708
3917
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
@@ -3816,14 +4025,14 @@ function useAttachmentUrl(attachmentId) {
|
|
|
3816
4025
|
function useRoomAttachmentUrl(attachmentId, roomId) {
|
|
3817
4026
|
const client = useClient();
|
|
3818
4027
|
const store = client[kInternal3].httpClient.getOrCreateAttachmentUrlsStore(roomId);
|
|
3819
|
-
const getAttachmentUrlState =
|
|
4028
|
+
const getAttachmentUrlState = useCallback3(
|
|
3820
4029
|
() => store.getState(attachmentId),
|
|
3821
4030
|
[store, attachmentId]
|
|
3822
4031
|
);
|
|
3823
|
-
|
|
4032
|
+
useEffect5(() => {
|
|
3824
4033
|
void store.get(attachmentId);
|
|
3825
4034
|
}, [store, attachmentId]);
|
|
3826
|
-
return
|
|
4035
|
+
return useSyncExternalStoreWithSelector(
|
|
3827
4036
|
store.subscribe,
|
|
3828
4037
|
getAttachmentUrlState,
|
|
3829
4038
|
getAttachmentUrlState,
|
|
@@ -3834,7 +4043,7 @@ function useRoomAttachmentUrl(attachmentId, roomId) {
|
|
|
3834
4043
|
function useAttachmentUrlSuspense(attachmentId) {
|
|
3835
4044
|
const room = useRoom();
|
|
3836
4045
|
const { attachmentUrlsStore } = room[kInternal3];
|
|
3837
|
-
const getAttachmentUrlState =
|
|
4046
|
+
const getAttachmentUrlState = useCallback3(
|
|
3838
4047
|
() => attachmentUrlsStore.getState(attachmentId),
|
|
3839
4048
|
[attachmentUrlsStore, attachmentId]
|
|
3840
4049
|
);
|
|
@@ -3845,7 +4054,7 @@ function useAttachmentUrlSuspense(attachmentId) {
|
|
|
3845
4054
|
if (attachmentUrlState.error) {
|
|
3846
4055
|
throw attachmentUrlState.error;
|
|
3847
4056
|
}
|
|
3848
|
-
const state =
|
|
4057
|
+
const state = useSyncExternalStore3(
|
|
3849
4058
|
attachmentUrlsStore.subscribe,
|
|
3850
4059
|
getAttachmentUrlState,
|
|
3851
4060
|
getAttachmentUrlState
|
|
@@ -3862,11 +4071,10 @@ function useAttachmentUrlSuspense(attachmentId) {
|
|
|
3862
4071
|
function useRoomPermissions(roomId) {
|
|
3863
4072
|
const client = useClient();
|
|
3864
4073
|
const store = getRoomExtrasForClient(client).store;
|
|
3865
|
-
return
|
|
3866
|
-
store.
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
) ?? /* @__PURE__ */ new Set();
|
|
4074
|
+
return useSignal(
|
|
4075
|
+
store.permissionHintsByRoomId,
|
|
4076
|
+
(hints) => hints[roomId] ?? /* @__PURE__ */ new Set()
|
|
4077
|
+
);
|
|
3870
4078
|
}
|
|
3871
4079
|
function createRoomContext(client) {
|
|
3872
4080
|
return getOrCreateRoomContextBundle(client);
|
|
@@ -3913,6 +4121,7 @@ var _useUpdateMyPresence = useUpdateMyPresence;
|
|
|
3913
4121
|
export {
|
|
3914
4122
|
RoomContext,
|
|
3915
4123
|
useRoomOrNull,
|
|
4124
|
+
useSyncExternalStoreWithSelector,
|
|
3916
4125
|
ClientContext,
|
|
3917
4126
|
getUmbrellaStoreForClient,
|
|
3918
4127
|
useClientOrNull,
|
|
@@ -3936,8 +4145,14 @@ export {
|
|
|
3936
4145
|
_useUserThreadsSuspense_experimental,
|
|
3937
4146
|
useSyncStatus,
|
|
3938
4147
|
CreateThreadError,
|
|
4148
|
+
useSignal,
|
|
3939
4149
|
useStatus,
|
|
3940
4150
|
useReportTextEditor,
|
|
4151
|
+
useYjsProvider,
|
|
4152
|
+
useCreateTextMention,
|
|
4153
|
+
useDeleteTextMention,
|
|
4154
|
+
useResolveMentionSuggestions,
|
|
4155
|
+
useMentionSuggestionsCache,
|
|
3941
4156
|
useStorageStatus,
|
|
3942
4157
|
useBatch,
|
|
3943
4158
|
useLostConnectionListener,
|
|
@@ -4008,4 +4223,4 @@ export {
|
|
|
4008
4223
|
_useStorageRoot,
|
|
4009
4224
|
_useUpdateMyPresence
|
|
4010
4225
|
};
|
|
4011
|
-
//# sourceMappingURL=chunk-
|
|
4226
|
+
//# sourceMappingURL=chunk-UJLD6FYC.mjs.map
|