@liveblocks/react 2.15.1 → 2.15.2
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 +5 -3
- package/dist/_private.d.ts +5 -3
- package/dist/_private.js +11 -6
- package/dist/_private.js.map +1 -1
- package/dist/_private.mjs +10 -5
- package/dist/_private.mjs.map +1 -1
- package/dist/{chunk-WV5AI4AE.js → chunk-3KHBALYA.js} +2 -2
- package/dist/{chunk-NUDMG62P.js → chunk-DEAPV4GE.js} +488 -681
- package/dist/chunk-DEAPV4GE.js.map +1 -0
- package/dist/{chunk-GMKB6I6V.mjs → chunk-EEYUKRIA.mjs} +482 -675
- package/dist/chunk-EEYUKRIA.mjs.map +1 -0
- package/dist/{chunk-UX3CG7ZS.mjs → chunk-Z5VZOX7K.mjs} +2 -2
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/index.mjs +2 -2
- package/dist/{room-XbmI0Hoh.d.mts → room-0rxzsE_0.d.mts} +29 -64
- package/dist/{room-XbmI0Hoh.d.ts → room-0rxzsE_0.d.ts} +29 -64
- package/dist/suspense.d.mts +1 -1
- package/dist/suspense.d.ts +1 -1
- package/dist/suspense.js +4 -4
- package/dist/suspense.mjs +2 -2
- package/package.json +3 -3
- package/dist/chunk-GMKB6I6V.mjs.map +0 -1
- package/dist/chunk-NUDMG62P.js.map +0 -1
- /package/dist/{chunk-WV5AI4AE.js.map → chunk-3KHBALYA.js.map} +0 -0
- /package/dist/{chunk-UX3CG7ZS.mjs.map → chunk-Z5VZOX7K.mjs.map} +0 -0
|
@@ -85,6 +85,18 @@ function useSyncExternalStoreWithSelector(subscribe, getSnapshot, getServerSnaps
|
|
|
85
85
|
return value;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// src/use-signal.ts
|
|
89
|
+
var identity = (value) => value;
|
|
90
|
+
function useSignal(signal, selector, isEqual) {
|
|
91
|
+
return useSyncExternalStoreWithSelector(
|
|
92
|
+
signal.subscribe,
|
|
93
|
+
signal.get,
|
|
94
|
+
signal.get,
|
|
95
|
+
selector ?? identity,
|
|
96
|
+
isEqual
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
88
100
|
// src/liveblocks.tsx
|
|
89
101
|
import {
|
|
90
102
|
assert,
|
|
@@ -121,19 +133,30 @@ var config = {
|
|
|
121
133
|
NOTIFICATION_SETTINGS_MAX_STALE_TIME: 5 * SECONDS
|
|
122
134
|
};
|
|
123
135
|
|
|
124
|
-
// src/lib/
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
// src/lib/AsyncResult.ts
|
|
137
|
+
var ASYNC_LOADING = Object.freeze({ isLoading: true });
|
|
138
|
+
var ASYNC_ERR = (error) => Object.freeze({ isLoading: false, error });
|
|
139
|
+
function ASYNC_OK(fieldOrData, data) {
|
|
140
|
+
if (arguments.length === 1) {
|
|
141
|
+
return Object.freeze({ isLoading: false, data: fieldOrData });
|
|
142
|
+
} else {
|
|
143
|
+
return Object.freeze({ isLoading: false, [fieldOrData]: data });
|
|
129
144
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// src/lib/itertools.ts
|
|
148
|
+
function find(it, predicate) {
|
|
149
|
+
for (const item of it) {
|
|
150
|
+
if (predicate(item)) return item;
|
|
133
151
|
}
|
|
134
|
-
return
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
return void 0;
|
|
153
|
+
}
|
|
154
|
+
function count(it, predicate) {
|
|
155
|
+
let total = 0;
|
|
156
|
+
for (const item of it) {
|
|
157
|
+
if (predicate(item)) total++;
|
|
158
|
+
}
|
|
159
|
+
return total;
|
|
137
160
|
}
|
|
138
161
|
|
|
139
162
|
// src/lib/use-initial.ts
|
|
@@ -199,16 +222,17 @@ import {
|
|
|
199
222
|
batch as batch2,
|
|
200
223
|
compactObject,
|
|
201
224
|
console as console2,
|
|
225
|
+
DefaultMap,
|
|
202
226
|
DerivedSignal,
|
|
203
227
|
HttpError,
|
|
204
228
|
kInternal,
|
|
205
|
-
makeEventSource,
|
|
206
229
|
MutableSignal as MutableSignal2,
|
|
207
230
|
nanoid,
|
|
208
231
|
nn,
|
|
209
232
|
shallow as shallow3,
|
|
210
233
|
Signal,
|
|
211
|
-
stringify
|
|
234
|
+
stringify,
|
|
235
|
+
unstringify
|
|
212
236
|
} from "@liveblocks/core";
|
|
213
237
|
|
|
214
238
|
// src/lib/autobind.ts
|
|
@@ -228,12 +252,19 @@ function autobind(self) {
|
|
|
228
252
|
} while ((obj = Reflect.getPrototypeOf(obj)) && obj !== Object.prototype);
|
|
229
253
|
}
|
|
230
254
|
|
|
231
|
-
// src/lib/
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
255
|
+
// src/lib/shallow2.ts
|
|
256
|
+
import { isPlainObject, shallow } from "@liveblocks/core";
|
|
257
|
+
function shallow2(a, b) {
|
|
258
|
+
if (!isPlainObject(a) || !isPlainObject(b)) {
|
|
259
|
+
return shallow(a, b);
|
|
235
260
|
}
|
|
236
|
-
|
|
261
|
+
const keysA = Object.keys(a);
|
|
262
|
+
if (keysA.length !== Object.keys(b).length) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
return keysA.every(
|
|
266
|
+
(key) => Object.prototype.hasOwnProperty.call(b, key) && shallow(a[key], b[key])
|
|
267
|
+
);
|
|
237
268
|
}
|
|
238
269
|
|
|
239
270
|
// src/ThreadDB.ts
|
|
@@ -355,12 +386,12 @@ var ThreadDB = class _ThreadDB {
|
|
|
355
386
|
this.upsert(thread);
|
|
356
387
|
}
|
|
357
388
|
}
|
|
358
|
-
applyDelta(
|
|
389
|
+
applyDelta(newThreads, deletedThreads) {
|
|
359
390
|
batch(() => {
|
|
360
|
-
for (const thread of
|
|
391
|
+
for (const thread of newThreads) {
|
|
361
392
|
this.upsertIfNewer(thread);
|
|
362
393
|
}
|
|
363
|
-
for (const { id, deletedAt } of
|
|
394
|
+
for (const { id, deletedAt } of deletedThreads) {
|
|
364
395
|
const existing = this.getEvenIfDeleted(id);
|
|
365
396
|
if (!existing) continue;
|
|
366
397
|
this.delete(id, deletedAt);
|
|
@@ -401,16 +432,10 @@ var ThreadDB = class _ThreadDB {
|
|
|
401
432
|
|
|
402
433
|
// src/umbrella-store.ts
|
|
403
434
|
function makeRoomThreadsQueryKey(roomId, query) {
|
|
404
|
-
return
|
|
435
|
+
return stringify([roomId, query ?? {}]);
|
|
405
436
|
}
|
|
406
437
|
function makeUserThreadsQueryKey(query) {
|
|
407
|
-
return
|
|
408
|
-
}
|
|
409
|
-
function makeNotificationSettingsQueryKey(roomId) {
|
|
410
|
-
return `${roomId}:NOTIFICATION_SETTINGS`;
|
|
411
|
-
}
|
|
412
|
-
function makeVersionsQueryKey(roomId) {
|
|
413
|
-
return `${roomId}-VERSIONS`;
|
|
438
|
+
return stringify(query ?? {});
|
|
414
439
|
}
|
|
415
440
|
function usify(promise) {
|
|
416
441
|
if ("status" in promise) {
|
|
@@ -431,53 +456,50 @@ function usify(promise) {
|
|
|
431
456
|
return usable;
|
|
432
457
|
}
|
|
433
458
|
var noop2 = Promise.resolve();
|
|
434
|
-
var ASYNC_LOADING = Object.freeze({ isLoading: true });
|
|
435
459
|
var PaginatedResource = class {
|
|
436
|
-
|
|
437
|
-
|
|
460
|
+
#signal;
|
|
461
|
+
signal;
|
|
438
462
|
#fetchPage;
|
|
439
|
-
#paginationState;
|
|
440
|
-
// Should be null while in loading or error state!
|
|
441
463
|
#pendingFetchMore;
|
|
442
464
|
constructor(fetchPage) {
|
|
443
|
-
this.#
|
|
465
|
+
this.#signal = new Signal(ASYNC_LOADING);
|
|
444
466
|
this.#fetchPage = fetchPage;
|
|
445
|
-
this.#eventSource = makeEventSource();
|
|
446
467
|
this.#pendingFetchMore = null;
|
|
447
|
-
this.
|
|
468
|
+
this.signal = this.#signal.asReadonly();
|
|
448
469
|
autobind(this);
|
|
449
470
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
this.#
|
|
471
|
+
get() {
|
|
472
|
+
return this.#signal.get();
|
|
473
|
+
}
|
|
474
|
+
#patch(patch) {
|
|
475
|
+
const state = this.#signal.get();
|
|
476
|
+
if (state.data === void 0) return;
|
|
477
|
+
this.#signal.set(ASYNC_OK({ ...state.data, ...patch }));
|
|
455
478
|
}
|
|
456
479
|
async #fetchMore() {
|
|
457
|
-
const state = this.#
|
|
458
|
-
if (!state?.cursor) {
|
|
480
|
+
const state = this.#signal.get();
|
|
481
|
+
if (!state.data?.cursor || state.data.isFetchingMore) {
|
|
459
482
|
return;
|
|
460
483
|
}
|
|
461
|
-
this.#
|
|
484
|
+
this.#patch({ isFetchingMore: true });
|
|
462
485
|
try {
|
|
463
|
-
const nextCursor = await this.#fetchPage(state.cursor);
|
|
464
|
-
this.#
|
|
486
|
+
const nextCursor = await this.#fetchPage(state.data.cursor);
|
|
487
|
+
this.#patch({
|
|
465
488
|
cursor: nextCursor,
|
|
489
|
+
hasFetchedAll: nextCursor === null,
|
|
466
490
|
fetchMoreError: void 0,
|
|
467
491
|
isFetchingMore: false
|
|
468
492
|
});
|
|
469
493
|
} catch (err) {
|
|
470
|
-
this.#
|
|
494
|
+
this.#patch({
|
|
471
495
|
isFetchingMore: false,
|
|
472
496
|
fetchMoreError: err
|
|
473
497
|
});
|
|
474
498
|
}
|
|
475
499
|
}
|
|
476
500
|
fetchMore() {
|
|
477
|
-
const state = this.#
|
|
478
|
-
if (state?.cursor
|
|
479
|
-
return noop2;
|
|
480
|
-
}
|
|
501
|
+
const state = this.#signal.get();
|
|
502
|
+
if (!state.data?.cursor) return noop2;
|
|
481
503
|
if (!this.#pendingFetchMore) {
|
|
482
504
|
this.#pendingFetchMore = this.#fetchMore().finally(() => {
|
|
483
505
|
this.#pendingFetchMore = null;
|
|
@@ -485,31 +507,12 @@ var PaginatedResource = class {
|
|
|
485
507
|
}
|
|
486
508
|
return this.#pendingFetchMore;
|
|
487
509
|
}
|
|
488
|
-
get() {
|
|
489
|
-
const usable = this.#cachedPromise;
|
|
490
|
-
if (usable === null || usable.status === "pending") {
|
|
491
|
-
return ASYNC_LOADING;
|
|
492
|
-
}
|
|
493
|
-
if (usable.status === "rejected") {
|
|
494
|
-
return { isLoading: false, error: usable.reason };
|
|
495
|
-
}
|
|
496
|
-
const state = this.#paginationState;
|
|
497
|
-
return {
|
|
498
|
-
isLoading: false,
|
|
499
|
-
data: {
|
|
500
|
-
fetchMore: this.fetchMore,
|
|
501
|
-
isFetchingMore: state.isFetchingMore,
|
|
502
|
-
fetchMoreError: state.fetchMoreError,
|
|
503
|
-
hasFetchedAll: state.cursor === null
|
|
504
|
-
}
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
510
|
#cachedPromise = null;
|
|
508
511
|
waitUntilLoaded() {
|
|
509
512
|
if (this.#cachedPromise) {
|
|
510
513
|
return this.#cachedPromise;
|
|
511
514
|
}
|
|
512
|
-
const
|
|
515
|
+
const initialPageFetch$ = autoRetry(
|
|
513
516
|
() => this.#fetchPage(
|
|
514
517
|
/* cursor */
|
|
515
518
|
void 0
|
|
@@ -517,67 +520,64 @@ var PaginatedResource = class {
|
|
|
517
520
|
5,
|
|
518
521
|
[5e3, 5e3, 1e4, 15e3]
|
|
519
522
|
);
|
|
520
|
-
const promise = usify(
|
|
521
|
-
initialFetcher.then((cursor) => {
|
|
522
|
-
this.#paginationState = {
|
|
523
|
-
cursor,
|
|
524
|
-
isFetchingMore: false,
|
|
525
|
-
fetchMoreError: void 0
|
|
526
|
-
};
|
|
527
|
-
})
|
|
528
|
-
);
|
|
523
|
+
const promise = usify(initialPageFetch$);
|
|
529
524
|
promise.then(
|
|
530
|
-
() =>
|
|
531
|
-
|
|
532
|
-
|
|
525
|
+
(cursor) => {
|
|
526
|
+
this.#signal.set(
|
|
527
|
+
ASYNC_OK({
|
|
528
|
+
cursor,
|
|
529
|
+
hasFetchedAll: cursor === null,
|
|
530
|
+
isFetchingMore: false,
|
|
531
|
+
fetchMoreError: void 0,
|
|
532
|
+
fetchMore: this.fetchMore
|
|
533
|
+
})
|
|
534
|
+
);
|
|
535
|
+
},
|
|
536
|
+
(err) => {
|
|
537
|
+
this.#signal.set(ASYNC_ERR(err));
|
|
533
538
|
setTimeout(() => {
|
|
534
539
|
this.#cachedPromise = null;
|
|
535
|
-
this.#
|
|
540
|
+
this.#signal.set(ASYNC_LOADING);
|
|
536
541
|
}, 5e3);
|
|
537
542
|
}
|
|
538
543
|
);
|
|
539
544
|
this.#cachedPromise = promise;
|
|
540
|
-
return
|
|
545
|
+
return this.#cachedPromise;
|
|
541
546
|
}
|
|
542
547
|
};
|
|
543
548
|
var SinglePageResource = class {
|
|
544
|
-
|
|
545
|
-
|
|
549
|
+
#signal;
|
|
550
|
+
signal;
|
|
546
551
|
#fetchPage;
|
|
547
552
|
constructor(fetchPage) {
|
|
553
|
+
this.#signal = new Signal(ASYNC_LOADING);
|
|
554
|
+
this.signal = this.#signal.asReadonly();
|
|
548
555
|
this.#fetchPage = fetchPage;
|
|
549
|
-
this.#eventSource = makeEventSource();
|
|
550
|
-
this.observable = this.#eventSource.observable;
|
|
551
556
|
autobind(this);
|
|
552
557
|
}
|
|
553
558
|
get() {
|
|
554
|
-
|
|
555
|
-
if (usable === null || usable.status === "pending") {
|
|
556
|
-
return ASYNC_LOADING;
|
|
557
|
-
} else if (usable.status === "rejected") {
|
|
558
|
-
return { isLoading: false, error: usable.reason };
|
|
559
|
-
} else {
|
|
560
|
-
return { isLoading: false, data: void 0 };
|
|
561
|
-
}
|
|
559
|
+
return this.#signal.get();
|
|
562
560
|
}
|
|
563
561
|
#cachedPromise = null;
|
|
564
562
|
waitUntilLoaded() {
|
|
565
563
|
if (this.#cachedPromise) {
|
|
566
564
|
return this.#cachedPromise;
|
|
567
565
|
}
|
|
568
|
-
const initialFetcher = autoRetry(
|
|
566
|
+
const initialFetcher$ = autoRetry(
|
|
569
567
|
() => this.#fetchPage(),
|
|
570
568
|
5,
|
|
571
569
|
[5e3, 5e3, 1e4, 15e3]
|
|
572
570
|
);
|
|
573
|
-
const promise = usify(initialFetcher);
|
|
571
|
+
const promise = usify(initialFetcher$);
|
|
574
572
|
promise.then(
|
|
575
|
-
() => this.#eventSource.notify(),
|
|
576
573
|
() => {
|
|
577
|
-
this.#
|
|
574
|
+
this.#signal.set(ASYNC_OK(void 0));
|
|
575
|
+
},
|
|
576
|
+
(err) => {
|
|
577
|
+
this.#signal.set(ASYNC_ERR(err));
|
|
578
578
|
setTimeout(() => {
|
|
579
579
|
this.#cachedPromise = null;
|
|
580
|
-
this.#
|
|
580
|
+
this.#signal.set(ASYNC_LOADING);
|
|
581
581
|
}, 5e3);
|
|
582
582
|
}
|
|
583
583
|
);
|
|
@@ -610,10 +610,10 @@ function createStore_forNotifications() {
|
|
|
610
610
|
function clear() {
|
|
611
611
|
signal.mutate((lut) => lut.clear());
|
|
612
612
|
}
|
|
613
|
-
function applyDelta(
|
|
613
|
+
function applyDelta(newNotifications, deletedNotifications) {
|
|
614
614
|
signal.mutate((lut) => {
|
|
615
615
|
let mutated = false;
|
|
616
|
-
for (const n of
|
|
616
|
+
for (const n of newNotifications) {
|
|
617
617
|
const existing = lut.get(n.id);
|
|
618
618
|
if (existing) {
|
|
619
619
|
const result = compareInboxNotifications(existing, n);
|
|
@@ -644,6 +644,11 @@ function createStore_forNotifications() {
|
|
|
644
644
|
return true;
|
|
645
645
|
});
|
|
646
646
|
}
|
|
647
|
+
function upsert(notification) {
|
|
648
|
+
signal.mutate((lut) => {
|
|
649
|
+
lut.set(notification.id, notification);
|
|
650
|
+
});
|
|
651
|
+
}
|
|
647
652
|
return {
|
|
648
653
|
signal: signal.asReadonly(),
|
|
649
654
|
// Mutations
|
|
@@ -653,66 +658,70 @@ function createStore_forNotifications() {
|
|
|
653
658
|
applyDelta,
|
|
654
659
|
clear,
|
|
655
660
|
updateAssociatedNotification,
|
|
656
|
-
|
|
657
|
-
force_set: (mutationCallback) => signal.mutate(mutationCallback),
|
|
658
|
-
invalidate: () => signal.mutate()
|
|
661
|
+
upsert
|
|
659
662
|
};
|
|
660
663
|
}
|
|
661
|
-
function createStore_forRoomNotificationSettings() {
|
|
662
|
-
const
|
|
664
|
+
function createStore_forRoomNotificationSettings(updates) {
|
|
665
|
+
const baseSignal = new MutableSignal2(/* @__PURE__ */ new Map());
|
|
663
666
|
function update(roomId, settings) {
|
|
664
|
-
|
|
667
|
+
baseSignal.mutate((lut) => {
|
|
665
668
|
lut.set(roomId, settings);
|
|
666
669
|
});
|
|
667
670
|
}
|
|
668
671
|
return {
|
|
669
|
-
signal:
|
|
672
|
+
signal: DerivedSignal.from(
|
|
673
|
+
baseSignal,
|
|
674
|
+
updates,
|
|
675
|
+
(base, updates2) => applyOptimisticUpdates_forSettings(base, updates2)
|
|
676
|
+
),
|
|
670
677
|
// Mutations
|
|
671
|
-
update
|
|
672
|
-
// XXX_vincent Remove this eventually
|
|
673
|
-
invalidate: () => signal.mutate()
|
|
678
|
+
update
|
|
674
679
|
};
|
|
675
680
|
}
|
|
676
681
|
function createStore_forHistoryVersions() {
|
|
677
|
-
const
|
|
682
|
+
const baseSignal = new MutableSignal2(
|
|
683
|
+
new DefaultMap(() => /* @__PURE__ */ new Map())
|
|
684
|
+
);
|
|
678
685
|
function update(roomId, versions) {
|
|
679
|
-
|
|
680
|
-
const versionsById = lut.
|
|
686
|
+
baseSignal.mutate((lut) => {
|
|
687
|
+
const versionsById = lut.getOrCreate(roomId);
|
|
681
688
|
for (const version of versions) {
|
|
682
689
|
versionsById.set(version.id, version);
|
|
683
690
|
}
|
|
684
691
|
});
|
|
685
692
|
}
|
|
686
693
|
return {
|
|
687
|
-
signal:
|
|
694
|
+
signal: DerivedSignal.from(
|
|
695
|
+
baseSignal,
|
|
696
|
+
(hv) => Object.fromEntries(
|
|
697
|
+
[...hv].map(([roomId, versions]) => [
|
|
698
|
+
roomId,
|
|
699
|
+
Object.fromEntries(versions)
|
|
700
|
+
])
|
|
701
|
+
)
|
|
702
|
+
),
|
|
688
703
|
// Mutations
|
|
689
|
-
update
|
|
690
|
-
// XXX_vincent Remove these eventually
|
|
691
|
-
force_set: (callback) => signal.mutate(callback),
|
|
692
|
-
invalidate: () => signal.mutate()
|
|
704
|
+
update
|
|
693
705
|
};
|
|
694
706
|
}
|
|
695
707
|
function createStore_forPermissionHints() {
|
|
696
|
-
const signal = new
|
|
708
|
+
const signal = new MutableSignal2(
|
|
709
|
+
new DefaultMap(() => /* @__PURE__ */ new Set())
|
|
710
|
+
);
|
|
697
711
|
function update(newHints) {
|
|
698
|
-
signal.
|
|
699
|
-
const permissionsByRoom = { ...prev };
|
|
712
|
+
signal.mutate((lut) => {
|
|
700
713
|
for (const [roomId, newPermissions] of Object.entries(newHints)) {
|
|
701
|
-
const existing =
|
|
714
|
+
const existing = lut.getOrCreate(roomId);
|
|
702
715
|
for (const permission of newPermissions) {
|
|
703
716
|
existing.add(permission);
|
|
704
717
|
}
|
|
705
|
-
permissionsByRoom[roomId] = existing;
|
|
706
718
|
}
|
|
707
|
-
return permissionsByRoom;
|
|
708
719
|
});
|
|
709
720
|
}
|
|
710
721
|
return {
|
|
711
722
|
signal: signal.asReadonly(),
|
|
712
723
|
// Mutations
|
|
713
|
-
update
|
|
714
|
-
// XXX_vincent Remove this eventually
|
|
715
|
-
invalidate: () => signal.set((store) => ({ ...store }))
|
|
724
|
+
update
|
|
716
725
|
};
|
|
717
726
|
}
|
|
718
727
|
function createStore_forOptimistic(client) {
|
|
@@ -736,9 +745,7 @@ function createStore_forOptimistic(client) {
|
|
|
736
745
|
signal: signal.asReadonly(),
|
|
737
746
|
// Mutations
|
|
738
747
|
add,
|
|
739
|
-
remove
|
|
740
|
-
// XXX_vincent Remove this eventually
|
|
741
|
-
invalidate: () => signal.set((store) => [...store])
|
|
748
|
+
remove
|
|
742
749
|
};
|
|
743
750
|
}
|
|
744
751
|
var UmbrellaStore = class {
|
|
@@ -788,48 +795,37 @@ var UmbrellaStore = class {
|
|
|
788
795
|
// threads and notifications separately, but the threadifications signal will
|
|
789
796
|
// be updated whenever either of them change.
|
|
790
797
|
//
|
|
791
|
-
// XXX_vincent APIs like getRoomThreadsLoadingState should really also be modeled as output signals.
|
|
792
|
-
//
|
|
793
798
|
outputs;
|
|
794
799
|
// Notifications
|
|
795
800
|
#notificationsLastRequestedAt = null;
|
|
796
801
|
// 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.
|
|
797
|
-
#
|
|
802
|
+
#notificationsPaginationState;
|
|
798
803
|
// Room Threads
|
|
799
804
|
#roomThreadsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
800
|
-
#roomThreads = /* @__PURE__ */ new Map();
|
|
801
805
|
// User Threads
|
|
802
806
|
#userThreadsLastRequestedAt = null;
|
|
803
|
-
#userThreads = /* @__PURE__ */ new Map();
|
|
804
807
|
// Room versions
|
|
805
|
-
#roomVersions = /* @__PURE__ */ new Map();
|
|
806
808
|
#roomVersionsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
807
|
-
// Room notification settings
|
|
808
|
-
#roomNotificationSettings = /* @__PURE__ */ new Map();
|
|
809
809
|
constructor(client) {
|
|
810
810
|
this.#client = client[kInternal].as();
|
|
811
811
|
this.optimisticUpdates = createStore_forOptimistic(this.#client);
|
|
812
812
|
this.permissionHints = createStore_forPermissionHints();
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
this.#notificationsLastRequestedAt
|
|
813
|
+
this.#notificationsPaginationState = new PaginatedResource(
|
|
814
|
+
async (cursor) => {
|
|
815
|
+
const result = await this.#client.getInboxNotifications({ cursor });
|
|
816
|
+
this.updateThreadifications(result.threads, result.inboxNotifications);
|
|
817
|
+
if (this.#notificationsLastRequestedAt === null) {
|
|
818
|
+
this.#notificationsLastRequestedAt = result.requestedAt;
|
|
819
|
+
}
|
|
820
|
+
const nextCursor = result.nextCursor;
|
|
821
|
+
return nextCursor;
|
|
818
822
|
}
|
|
819
|
-
const nextCursor = result.nextCursor;
|
|
820
|
-
return nextCursor;
|
|
821
|
-
};
|
|
822
|
-
this.#notifications = new PaginatedResource(inboxFetcher);
|
|
823
|
-
this.#notifications.observable.subscribe(
|
|
824
|
-
() => (
|
|
825
|
-
// Note that the store itself does not change, but it's only vehicle at
|
|
826
|
-
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
827
|
-
this.invalidateEntireStore()
|
|
828
|
-
)
|
|
829
823
|
);
|
|
830
824
|
this.threads = new ThreadDB();
|
|
831
825
|
this.notifications = createStore_forNotifications();
|
|
832
|
-
this.roomNotificationSettings = createStore_forRoomNotificationSettings(
|
|
826
|
+
this.roomNotificationSettings = createStore_forRoomNotificationSettings(
|
|
827
|
+
this.optimisticUpdates.signal
|
|
828
|
+
);
|
|
833
829
|
this.historyVersions = createStore_forHistoryVersions();
|
|
834
830
|
const threadifications = DerivedSignal.from(
|
|
835
831
|
this.threads.signal,
|
|
@@ -837,13 +833,7 @@ var UmbrellaStore = class {
|
|
|
837
833
|
this.optimisticUpdates.signal,
|
|
838
834
|
(ts, ns, updates) => applyOptimisticUpdates_forThreadifications(ts, ns, updates)
|
|
839
835
|
);
|
|
840
|
-
const threads = DerivedSignal.from(
|
|
841
|
-
threadifications,
|
|
842
|
-
(s) => ({
|
|
843
|
-
threadsDB: s.threadsDB
|
|
844
|
-
}),
|
|
845
|
-
shallow3
|
|
846
|
-
);
|
|
836
|
+
const threads = DerivedSignal.from(threadifications, (s) => s.threadsDB);
|
|
847
837
|
const notifications = DerivedSignal.from(
|
|
848
838
|
threadifications,
|
|
849
839
|
(s) => ({
|
|
@@ -852,177 +842,181 @@ var UmbrellaStore = class {
|
|
|
852
842
|
}),
|
|
853
843
|
shallow3
|
|
854
844
|
);
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
845
|
+
const loadingUserThreads = new DefaultMap(
|
|
846
|
+
(queryKey) => {
|
|
847
|
+
const query = unstringify(queryKey);
|
|
848
|
+
const resource = new PaginatedResource(async (cursor) => {
|
|
849
|
+
const result = await this.#client[kInternal].httpClient.getUserThreads_experimental({
|
|
850
|
+
cursor,
|
|
851
|
+
query
|
|
852
|
+
});
|
|
853
|
+
this.updateThreadifications(
|
|
854
|
+
result.threads,
|
|
855
|
+
result.inboxNotifications
|
|
856
|
+
);
|
|
857
|
+
this.permissionHints.update(result.permissionHints);
|
|
858
|
+
if (this.#userThreadsLastRequestedAt === null) {
|
|
859
|
+
this.#userThreadsLastRequestedAt = result.requestedAt;
|
|
860
|
+
}
|
|
861
|
+
return result.nextCursor;
|
|
862
|
+
});
|
|
863
|
+
const signal = DerivedSignal.from(() => {
|
|
864
|
+
const result = resource.get();
|
|
865
|
+
if (result.isLoading || result.error) {
|
|
866
|
+
return result;
|
|
867
|
+
}
|
|
868
|
+
const threads2 = this.outputs.threads.get().findMany(
|
|
869
|
+
void 0,
|
|
870
|
+
// Do _not_ filter by roomId
|
|
871
|
+
query ?? {},
|
|
872
|
+
"desc"
|
|
873
|
+
);
|
|
874
|
+
const page = result.data;
|
|
875
|
+
return {
|
|
876
|
+
isLoading: false,
|
|
877
|
+
threads: threads2,
|
|
878
|
+
hasFetchedAll: page.hasFetchedAll,
|
|
879
|
+
isFetchingMore: page.isFetchingMore,
|
|
880
|
+
fetchMoreError: page.fetchMoreError,
|
|
881
|
+
fetchMore: page.fetchMore
|
|
882
|
+
};
|
|
883
|
+
}, shallow2);
|
|
884
|
+
return { signal, waitUntilLoaded: resource.waitUntilLoaded };
|
|
885
|
+
}
|
|
859
886
|
);
|
|
860
|
-
const
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
887
|
+
const loadingRoomThreads = new DefaultMap(
|
|
888
|
+
(queryKey) => {
|
|
889
|
+
const [roomId, query] = unstringify(queryKey);
|
|
890
|
+
const resource = new PaginatedResource(async (cursor) => {
|
|
891
|
+
const result = await this.#client[kInternal].httpClient.getThreads({
|
|
892
|
+
roomId,
|
|
893
|
+
cursor,
|
|
894
|
+
query
|
|
895
|
+
});
|
|
896
|
+
this.updateThreadifications(
|
|
897
|
+
result.threads,
|
|
898
|
+
result.inboxNotifications
|
|
899
|
+
);
|
|
900
|
+
this.permissionHints.update(result.permissionHints);
|
|
901
|
+
const lastRequestedAt = this.#roomThreadsLastRequestedAtByRoom.get(roomId);
|
|
902
|
+
if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
|
|
903
|
+
this.#roomThreadsLastRequestedAtByRoom.set(
|
|
904
|
+
roomId,
|
|
905
|
+
result.requestedAt
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
return result.nextCursor;
|
|
909
|
+
});
|
|
910
|
+
const signal = DerivedSignal.from(() => {
|
|
911
|
+
const result = resource.get();
|
|
912
|
+
if (result.isLoading || result.error) {
|
|
913
|
+
return result;
|
|
914
|
+
}
|
|
915
|
+
const threads2 = this.outputs.threads.get().findMany(roomId, query ?? {}, "asc");
|
|
916
|
+
const page = result.data;
|
|
917
|
+
return {
|
|
918
|
+
isLoading: false,
|
|
919
|
+
threads: threads2,
|
|
920
|
+
hasFetchedAll: page.hasFetchedAll,
|
|
921
|
+
isFetchingMore: page.isFetchingMore,
|
|
922
|
+
fetchMoreError: page.fetchMoreError,
|
|
923
|
+
fetchMore: page.fetchMore
|
|
924
|
+
};
|
|
925
|
+
}, shallow2);
|
|
926
|
+
return { signal, waitUntilLoaded: resource.waitUntilLoaded };
|
|
927
|
+
}
|
|
928
|
+
);
|
|
929
|
+
const loadingNotifications = {
|
|
930
|
+
signal: DerivedSignal.from(() => {
|
|
931
|
+
const result = this.#notificationsPaginationState.get();
|
|
932
|
+
if (result.isLoading || result.error) {
|
|
933
|
+
return result;
|
|
934
|
+
}
|
|
935
|
+
const page = result.data;
|
|
936
|
+
return {
|
|
937
|
+
isLoading: false,
|
|
938
|
+
inboxNotifications: this.outputs.notifications.get().sortedNotifications,
|
|
939
|
+
hasFetchedAll: page.hasFetchedAll,
|
|
940
|
+
isFetchingMore: page.isFetchingMore,
|
|
941
|
+
fetchMoreError: page.fetchMoreError,
|
|
942
|
+
fetchMore: page.fetchMore
|
|
943
|
+
};
|
|
944
|
+
}),
|
|
945
|
+
waitUntilLoaded: this.#notificationsPaginationState.waitUntilLoaded
|
|
946
|
+
};
|
|
947
|
+
const settingsByRoomId = new DefaultMap((roomId) => {
|
|
948
|
+
const resource = new SinglePageResource(async () => {
|
|
949
|
+
const room = this.#client.getRoom(roomId);
|
|
950
|
+
if (room === null) {
|
|
951
|
+
throw new HttpError(
|
|
952
|
+
`Room '${roomId}' is not available on client`,
|
|
953
|
+
479
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
const result = await room.getNotificationSettings();
|
|
957
|
+
this.roomNotificationSettings.update(roomId, result);
|
|
958
|
+
});
|
|
959
|
+
const signal = DerivedSignal.from(() => {
|
|
960
|
+
const result = resource.get();
|
|
961
|
+
if (result.isLoading || result.error) {
|
|
962
|
+
return result;
|
|
963
|
+
} else {
|
|
964
|
+
return ASYNC_OK(
|
|
965
|
+
"settings",
|
|
966
|
+
nn(this.roomNotificationSettings.signal.get()[roomId])
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
}, shallow3);
|
|
970
|
+
return { signal, waitUntilLoaded: resource.waitUntilLoaded };
|
|
971
|
+
});
|
|
972
|
+
const versionsByRoomId = new DefaultMap(
|
|
973
|
+
(roomId) => {
|
|
974
|
+
const resource = new SinglePageResource(async () => {
|
|
975
|
+
const room = this.#client.getRoom(roomId);
|
|
976
|
+
if (room === null) {
|
|
977
|
+
throw new HttpError(
|
|
978
|
+
`Room '${roomId}' is not available on client`,
|
|
979
|
+
479
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
const result = await room[kInternal].listTextVersions();
|
|
983
|
+
this.historyVersions.update(roomId, result.versions);
|
|
984
|
+
const lastRequestedAt = this.#roomVersionsLastRequestedAtByRoom.get(roomId);
|
|
985
|
+
if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
|
|
986
|
+
this.#roomVersionsLastRequestedAtByRoom.set(
|
|
987
|
+
roomId,
|
|
988
|
+
result.requestedAt
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
});
|
|
992
|
+
const signal = DerivedSignal.from(() => {
|
|
993
|
+
const result = resource.get();
|
|
994
|
+
if (result.isLoading || result.error) {
|
|
995
|
+
return result;
|
|
996
|
+
} else {
|
|
997
|
+
return {
|
|
998
|
+
isLoading: false,
|
|
999
|
+
versions: Object.values(
|
|
1000
|
+
this.historyVersions.signal.get()[roomId] ?? {}
|
|
1001
|
+
)
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
}, shallow3);
|
|
1005
|
+
return { signal, waitUntilLoaded: resource.waitUntilLoaded };
|
|
1006
|
+
}
|
|
868
1007
|
);
|
|
869
1008
|
this.outputs = {
|
|
870
1009
|
threadifications,
|
|
871
1010
|
threads,
|
|
1011
|
+
loadingRoomThreads,
|
|
1012
|
+
loadingUserThreads,
|
|
872
1013
|
notifications,
|
|
1014
|
+
loadingNotifications,
|
|
873
1015
|
settingsByRoomId,
|
|
874
1016
|
versionsByRoomId
|
|
875
1017
|
};
|
|
876
1018
|
autobind(this);
|
|
877
1019
|
}
|
|
878
|
-
get1_both() {
|
|
879
|
-
return this.outputs.threadifications.get();
|
|
880
|
-
}
|
|
881
|
-
subscribe1_both(callback) {
|
|
882
|
-
return this.outputs.threadifications.subscribe(callback);
|
|
883
|
-
}
|
|
884
|
-
get1_threads() {
|
|
885
|
-
return this.outputs.threads.get();
|
|
886
|
-
}
|
|
887
|
-
subscribe1_threads(callback) {
|
|
888
|
-
return this.outputs.threads.subscribe(callback);
|
|
889
|
-
}
|
|
890
|
-
get1_notifications() {
|
|
891
|
-
return this.outputs.notifications.get();
|
|
892
|
-
}
|
|
893
|
-
subscribe1_notifications(callback) {
|
|
894
|
-
return this.outputs.notifications.subscribe(callback);
|
|
895
|
-
}
|
|
896
|
-
get2() {
|
|
897
|
-
return this.outputs.settingsByRoomId.get();
|
|
898
|
-
}
|
|
899
|
-
subscribe2(callback) {
|
|
900
|
-
return this.outputs.settingsByRoomId.subscribe(callback);
|
|
901
|
-
}
|
|
902
|
-
get3() {
|
|
903
|
-
return this.outputs.versionsByRoomId.get();
|
|
904
|
-
}
|
|
905
|
-
subscribe3(callback) {
|
|
906
|
-
return this.outputs.versionsByRoomId.subscribe(callback);
|
|
907
|
-
}
|
|
908
|
-
/**
|
|
909
|
-
* Returns the async result of the given query and room id. If the query is success,
|
|
910
|
-
* then it will return the threads that match that provided query and room id.
|
|
911
|
-
*
|
|
912
|
-
*/
|
|
913
|
-
getRoomThreadsLoadingState(roomId, query) {
|
|
914
|
-
const queryKey = makeRoomThreadsQueryKey(roomId, query);
|
|
915
|
-
const paginatedResource = this.#roomThreads.get(queryKey);
|
|
916
|
-
if (paginatedResource === void 0) {
|
|
917
|
-
return ASYNC_LOADING;
|
|
918
|
-
}
|
|
919
|
-
const asyncResult = paginatedResource.get();
|
|
920
|
-
if (asyncResult.isLoading || asyncResult.error) {
|
|
921
|
-
return asyncResult;
|
|
922
|
-
}
|
|
923
|
-
const threads = this.get1_threads().threadsDB.findMany(
|
|
924
|
-
roomId,
|
|
925
|
-
query ?? {},
|
|
926
|
-
"asc"
|
|
927
|
-
);
|
|
928
|
-
const page = asyncResult.data;
|
|
929
|
-
return {
|
|
930
|
-
isLoading: false,
|
|
931
|
-
threads,
|
|
932
|
-
hasFetchedAll: page.hasFetchedAll,
|
|
933
|
-
isFetchingMore: page.isFetchingMore,
|
|
934
|
-
fetchMoreError: page.fetchMoreError,
|
|
935
|
-
fetchMore: page.fetchMore
|
|
936
|
-
};
|
|
937
|
-
}
|
|
938
|
-
getUserThreadsLoadingState(query) {
|
|
939
|
-
const queryKey = makeUserThreadsQueryKey(query);
|
|
940
|
-
const paginatedResource = this.#userThreads.get(queryKey);
|
|
941
|
-
if (paginatedResource === void 0) {
|
|
942
|
-
return ASYNC_LOADING;
|
|
943
|
-
}
|
|
944
|
-
const asyncResult = paginatedResource.get();
|
|
945
|
-
if (asyncResult.isLoading || asyncResult.error) {
|
|
946
|
-
return asyncResult;
|
|
947
|
-
}
|
|
948
|
-
const threads = this.get1_threads().threadsDB.findMany(
|
|
949
|
-
void 0,
|
|
950
|
-
// Do _not_ filter by roomId
|
|
951
|
-
query ?? {},
|
|
952
|
-
"desc"
|
|
953
|
-
);
|
|
954
|
-
const page = asyncResult.data;
|
|
955
|
-
return {
|
|
956
|
-
isLoading: false,
|
|
957
|
-
threads,
|
|
958
|
-
hasFetchedAll: page.hasFetchedAll,
|
|
959
|
-
isFetchingMore: page.isFetchingMore,
|
|
960
|
-
fetchMoreError: page.fetchMoreError,
|
|
961
|
-
fetchMore: page.fetchMore
|
|
962
|
-
};
|
|
963
|
-
}
|
|
964
|
-
// NOTE: This will read the async result, but WILL NOT start loading at the moment!
|
|
965
|
-
getInboxNotificationsLoadingState() {
|
|
966
|
-
const asyncResult = this.#notifications.get();
|
|
967
|
-
if (asyncResult.isLoading || asyncResult.error) {
|
|
968
|
-
return asyncResult;
|
|
969
|
-
}
|
|
970
|
-
const page = asyncResult.data;
|
|
971
|
-
return {
|
|
972
|
-
isLoading: false,
|
|
973
|
-
inboxNotifications: this.get1_notifications().sortedNotifications,
|
|
974
|
-
hasFetchedAll: page.hasFetchedAll,
|
|
975
|
-
isFetchingMore: page.isFetchingMore,
|
|
976
|
-
fetchMoreError: page.fetchMoreError,
|
|
977
|
-
fetchMore: page.fetchMore
|
|
978
|
-
};
|
|
979
|
-
}
|
|
980
|
-
// NOTE: This will read the async result, but WILL NOT start loading at the moment!
|
|
981
|
-
// XXX_vincent This should really be a derived Signal!
|
|
982
|
-
getNotificationSettingsLoadingState(roomId) {
|
|
983
|
-
const queryKey = makeNotificationSettingsQueryKey(roomId);
|
|
984
|
-
const resource = this.#roomNotificationSettings.get(queryKey);
|
|
985
|
-
if (resource === void 0) {
|
|
986
|
-
return ASYNC_LOADING;
|
|
987
|
-
}
|
|
988
|
-
const asyncResult = resource.get();
|
|
989
|
-
if (asyncResult.isLoading || asyncResult.error) {
|
|
990
|
-
return asyncResult;
|
|
991
|
-
}
|
|
992
|
-
return {
|
|
993
|
-
isLoading: false,
|
|
994
|
-
settings: nn(this.get2()[roomId])
|
|
995
|
-
};
|
|
996
|
-
}
|
|
997
|
-
getRoomVersionsLoadingState(roomId) {
|
|
998
|
-
const queryKey = makeVersionsQueryKey(roomId);
|
|
999
|
-
const resource = this.#roomVersions.get(queryKey);
|
|
1000
|
-
if (resource === void 0) {
|
|
1001
|
-
return ASYNC_LOADING;
|
|
1002
|
-
}
|
|
1003
|
-
const asyncResult = resource.get();
|
|
1004
|
-
if (asyncResult.isLoading || asyncResult.error) {
|
|
1005
|
-
return asyncResult;
|
|
1006
|
-
}
|
|
1007
|
-
return {
|
|
1008
|
-
isLoading: false,
|
|
1009
|
-
versions: Object.values(this.get3()[roomId] ?? {})
|
|
1010
|
-
};
|
|
1011
|
-
}
|
|
1012
|
-
/** @internal - Only call this method from unit tests. */
|
|
1013
|
-
force_set_versions(callback) {
|
|
1014
|
-
batch2(() => {
|
|
1015
|
-
this.historyVersions.force_set(callback);
|
|
1016
|
-
this.invalidateEntireStore();
|
|
1017
|
-
});
|
|
1018
|
-
}
|
|
1019
|
-
/** @internal - Only call this method from unit tests. */
|
|
1020
|
-
force_set_notifications(callback) {
|
|
1021
|
-
batch2(() => {
|
|
1022
|
-
this.notifications.force_set(callback);
|
|
1023
|
-
this.invalidateEntireStore();
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
1026
1020
|
/**
|
|
1027
1021
|
* Updates an existing inbox notification with a new value, replacing the
|
|
1028
1022
|
* corresponding optimistic update.
|
|
@@ -1164,7 +1158,7 @@ var UmbrellaStore = class {
|
|
|
1164
1158
|
}
|
|
1165
1159
|
updateThreadifications(threads, notifications, deletedThreads = [], deletedNotifications = []) {
|
|
1166
1160
|
batch2(() => {
|
|
1167
|
-
this.threads.applyDelta(
|
|
1161
|
+
this.threads.applyDelta(threads, deletedThreads);
|
|
1168
1162
|
this.notifications.applyDelta(notifications, deletedNotifications);
|
|
1169
1163
|
});
|
|
1170
1164
|
}
|
|
@@ -1197,39 +1191,6 @@ var UmbrellaStore = class {
|
|
|
1197
1191
|
result.inboxNotifications.deleted
|
|
1198
1192
|
);
|
|
1199
1193
|
}
|
|
1200
|
-
waitUntilNotificationsLoaded() {
|
|
1201
|
-
return this.#notifications.waitUntilLoaded();
|
|
1202
|
-
}
|
|
1203
|
-
waitUntilRoomThreadsLoaded(roomId, query) {
|
|
1204
|
-
const threadsFetcher = async (cursor) => {
|
|
1205
|
-
const result = await this.#client[kInternal].httpClient.getThreads({
|
|
1206
|
-
roomId,
|
|
1207
|
-
cursor,
|
|
1208
|
-
query
|
|
1209
|
-
});
|
|
1210
|
-
this.updateThreadifications(result.threads, result.inboxNotifications);
|
|
1211
|
-
this.permissionHints.update(result.permissionHints);
|
|
1212
|
-
const lastRequestedAt = this.#roomThreadsLastRequestedAtByRoom.get(roomId);
|
|
1213
|
-
if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
|
|
1214
|
-
this.#roomThreadsLastRequestedAtByRoom.set(roomId, result.requestedAt);
|
|
1215
|
-
}
|
|
1216
|
-
return result.nextCursor;
|
|
1217
|
-
};
|
|
1218
|
-
const queryKey = makeRoomThreadsQueryKey(roomId, query);
|
|
1219
|
-
let paginatedResource = this.#roomThreads.get(queryKey);
|
|
1220
|
-
if (paginatedResource === void 0) {
|
|
1221
|
-
paginatedResource = new PaginatedResource(threadsFetcher);
|
|
1222
|
-
}
|
|
1223
|
-
paginatedResource.observable.subscribe(
|
|
1224
|
-
() => (
|
|
1225
|
-
// Note that the store itself does not change, but it's only vehicle at
|
|
1226
|
-
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
1227
|
-
this.invalidateEntireStore()
|
|
1228
|
-
)
|
|
1229
|
-
);
|
|
1230
|
-
this.#roomThreads.set(queryKey, paginatedResource);
|
|
1231
|
-
return paginatedResource.waitUntilLoaded();
|
|
1232
|
-
}
|
|
1233
1194
|
async fetchRoomThreadsDeltaUpdate(roomId, signal) {
|
|
1234
1195
|
const lastRequestedAt = this.#roomThreadsLastRequestedAtByRoom.get(roomId);
|
|
1235
1196
|
if (lastRequestedAt === void 0) {
|
|
@@ -1251,45 +1212,6 @@ var UmbrellaStore = class {
|
|
|
1251
1212
|
this.#roomThreadsLastRequestedAtByRoom.set(roomId, updates.requestedAt);
|
|
1252
1213
|
}
|
|
1253
1214
|
}
|
|
1254
|
-
waitUntilUserThreadsLoaded(query) {
|
|
1255
|
-
const queryKey = makeUserThreadsQueryKey(query);
|
|
1256
|
-
const threadsFetcher = async (cursor) => {
|
|
1257
|
-
const result = await this.#client[kInternal].httpClient.getUserThreads_experimental({
|
|
1258
|
-
cursor,
|
|
1259
|
-
query
|
|
1260
|
-
});
|
|
1261
|
-
this.updateThreadifications(result.threads, result.inboxNotifications);
|
|
1262
|
-
this.permissionHints.update(result.permissionHints);
|
|
1263
|
-
if (this.#userThreadsLastRequestedAt === null) {
|
|
1264
|
-
this.#userThreadsLastRequestedAt = result.requestedAt;
|
|
1265
|
-
}
|
|
1266
|
-
return result.nextCursor;
|
|
1267
|
-
};
|
|
1268
|
-
let paginatedResource = this.#userThreads.get(queryKey);
|
|
1269
|
-
if (paginatedResource === void 0) {
|
|
1270
|
-
paginatedResource = new PaginatedResource(threadsFetcher);
|
|
1271
|
-
}
|
|
1272
|
-
paginatedResource.observable.subscribe(
|
|
1273
|
-
() => (
|
|
1274
|
-
// Note that the store itself does not change, but it's only vehicle at
|
|
1275
|
-
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
1276
|
-
this.invalidateEntireStore()
|
|
1277
|
-
)
|
|
1278
|
-
);
|
|
1279
|
-
this.#userThreads.set(queryKey, paginatedResource);
|
|
1280
|
-
return paginatedResource.waitUntilLoaded();
|
|
1281
|
-
}
|
|
1282
|
-
// XXX_vincent We should really be going over all call sites, and replace this call
|
|
1283
|
-
// with a more specific invalidation!
|
|
1284
|
-
invalidateEntireStore() {
|
|
1285
|
-
batch2(() => {
|
|
1286
|
-
this.historyVersions.invalidate();
|
|
1287
|
-
this.notifications.invalidate();
|
|
1288
|
-
this.optimisticUpdates.invalidate();
|
|
1289
|
-
this.permissionHints.invalidate();
|
|
1290
|
-
this.roomNotificationSettings.invalidate();
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
1293
1215
|
async fetchUserThreadsDeltaUpdate(signal) {
|
|
1294
1216
|
const lastRequestedAt = this.#userThreadsLastRequestedAt;
|
|
1295
1217
|
if (lastRequestedAt === null) {
|
|
@@ -1310,40 +1232,6 @@ var UmbrellaStore = class {
|
|
|
1310
1232
|
);
|
|
1311
1233
|
this.permissionHints.update(result.permissionHints);
|
|
1312
1234
|
}
|
|
1313
|
-
waitUntilRoomVersionsLoaded(roomId) {
|
|
1314
|
-
const queryKey = makeVersionsQueryKey(roomId);
|
|
1315
|
-
let resource = this.#roomVersions.get(queryKey);
|
|
1316
|
-
if (resource === void 0) {
|
|
1317
|
-
const versionsFetcher = async () => {
|
|
1318
|
-
const room = this.#client.getRoom(roomId);
|
|
1319
|
-
if (room === null) {
|
|
1320
|
-
throw new HttpError(
|
|
1321
|
-
`Room '${roomId}' is not available on client`,
|
|
1322
|
-
479
|
|
1323
|
-
);
|
|
1324
|
-
}
|
|
1325
|
-
const result = await room[kInternal].listTextVersions();
|
|
1326
|
-
this.historyVersions.update(roomId, result.versions);
|
|
1327
|
-
const lastRequestedAt = this.#roomVersionsLastRequestedAtByRoom.get(roomId);
|
|
1328
|
-
if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
|
|
1329
|
-
this.#roomVersionsLastRequestedAtByRoom.set(
|
|
1330
|
-
roomId,
|
|
1331
|
-
result.requestedAt
|
|
1332
|
-
);
|
|
1333
|
-
}
|
|
1334
|
-
};
|
|
1335
|
-
resource = new SinglePageResource(versionsFetcher);
|
|
1336
|
-
}
|
|
1337
|
-
resource.observable.subscribe(
|
|
1338
|
-
() => (
|
|
1339
|
-
// Note that the store itself does not change, but it's only vehicle at
|
|
1340
|
-
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
1341
|
-
this.invalidateEntireStore()
|
|
1342
|
-
)
|
|
1343
|
-
);
|
|
1344
|
-
this.#roomVersions.set(queryKey, resource);
|
|
1345
|
-
return resource.waitUntilLoaded();
|
|
1346
|
-
}
|
|
1347
1235
|
async fetchRoomVersionsDeltaUpdate(roomId, signal) {
|
|
1348
1236
|
const lastRequestedAt = this.#roomVersionsLastRequestedAtByRoom.get(roomId);
|
|
1349
1237
|
if (lastRequestedAt === void 0) {
|
|
@@ -1362,33 +1250,6 @@ var UmbrellaStore = class {
|
|
|
1362
1250
|
this.#roomVersionsLastRequestedAtByRoom.set(roomId, updates.requestedAt);
|
|
1363
1251
|
}
|
|
1364
1252
|
}
|
|
1365
|
-
waitUntilRoomNotificationSettingsLoaded(roomId) {
|
|
1366
|
-
const queryKey = makeNotificationSettingsQueryKey(roomId);
|
|
1367
|
-
let resource = this.#roomNotificationSettings.get(queryKey);
|
|
1368
|
-
if (resource === void 0) {
|
|
1369
|
-
const notificationSettingsFetcher = async () => {
|
|
1370
|
-
const room = this.#client.getRoom(roomId);
|
|
1371
|
-
if (room === null) {
|
|
1372
|
-
throw new HttpError(
|
|
1373
|
-
`Room '${roomId}' is not available on client`,
|
|
1374
|
-
479
|
|
1375
|
-
);
|
|
1376
|
-
}
|
|
1377
|
-
const result = await room.getNotificationSettings();
|
|
1378
|
-
this.roomNotificationSettings.update(roomId, result);
|
|
1379
|
-
};
|
|
1380
|
-
resource = new SinglePageResource(notificationSettingsFetcher);
|
|
1381
|
-
}
|
|
1382
|
-
resource.observable.subscribe(
|
|
1383
|
-
() => (
|
|
1384
|
-
// Note that the store itself does not change, but it's only vehicle at
|
|
1385
|
-
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
1386
|
-
this.invalidateEntireStore()
|
|
1387
|
-
)
|
|
1388
|
-
);
|
|
1389
|
-
this.#roomNotificationSettings.set(queryKey, resource);
|
|
1390
|
-
return resource.waitUntilLoaded();
|
|
1391
|
-
}
|
|
1392
1253
|
async refreshRoomNotificationSettings(roomId, signal) {
|
|
1393
1254
|
const room = nn(
|
|
1394
1255
|
this.#client.getRoom(roomId),
|
|
@@ -1760,29 +1621,23 @@ function missingRoomInfoError(roomId) {
|
|
|
1760
1621
|
`resolveRoomsInfo didn't return anything for room '${roomId}'`
|
|
1761
1622
|
);
|
|
1762
1623
|
}
|
|
1763
|
-
function
|
|
1624
|
+
function identity2(x) {
|
|
1764
1625
|
return x;
|
|
1765
1626
|
}
|
|
1766
1627
|
var _umbrellaStores = /* @__PURE__ */ new WeakMap();
|
|
1767
1628
|
var _extras = /* @__PURE__ */ new WeakMap();
|
|
1768
1629
|
var _bundles = /* @__PURE__ */ new WeakMap();
|
|
1769
|
-
function selectUnreadInboxNotificationsCount(inboxNotifications) {
|
|
1770
|
-
let count = 0;
|
|
1771
|
-
for (const notification of inboxNotifications) {
|
|
1772
|
-
if (notification.readAt === null || notification.readAt < notification.notifiedAt) {
|
|
1773
|
-
count++;
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
return count;
|
|
1777
|
-
}
|
|
1778
1630
|
function selectorFor_useUnreadInboxNotificationsCount(result) {
|
|
1779
1631
|
if (!result.inboxNotifications) {
|
|
1780
1632
|
return result;
|
|
1781
1633
|
}
|
|
1782
|
-
return
|
|
1783
|
-
|
|
1784
|
-
count
|
|
1785
|
-
|
|
1634
|
+
return ASYNC_OK(
|
|
1635
|
+
"count",
|
|
1636
|
+
count(
|
|
1637
|
+
result.inboxNotifications,
|
|
1638
|
+
(n) => n.readAt === null || n.readAt < n.notifiedAt
|
|
1639
|
+
)
|
|
1640
|
+
);
|
|
1786
1641
|
}
|
|
1787
1642
|
function selectorFor_useUser(state, userId) {
|
|
1788
1643
|
if (state === void 0 || state?.isLoading) {
|
|
@@ -1889,7 +1744,7 @@ function makeLiveblocksContextBundle(client) {
|
|
|
1889
1744
|
const shared = createSharedContext(client);
|
|
1890
1745
|
const bundle = {
|
|
1891
1746
|
LiveblocksProvider: LiveblocksProvider2,
|
|
1892
|
-
useInboxNotifications: () => useInboxNotifications_withClient(client,
|
|
1747
|
+
useInboxNotifications: () => useInboxNotifications_withClient(client, identity2, shallow4),
|
|
1893
1748
|
useUnreadInboxNotificationsCount: () => useUnreadInboxNotificationsCount_withClient(client),
|
|
1894
1749
|
useMarkInboxNotificationAsRead: useMarkInboxNotificationAsRead2,
|
|
1895
1750
|
useMarkAllInboxNotificationsAsRead: useMarkAllInboxNotificationsAsRead2,
|
|
@@ -1915,9 +1770,17 @@ function makeLiveblocksContextBundle(client) {
|
|
|
1915
1770
|
}
|
|
1916
1771
|
function useInboxNotifications_withClient(client, selector, isEqual) {
|
|
1917
1772
|
const { store, notificationsPoller: poller } = getLiveblocksExtrasForClient(client);
|
|
1918
|
-
useEffect3(
|
|
1919
|
-
void store.
|
|
1920
|
-
|
|
1773
|
+
useEffect3(
|
|
1774
|
+
() => void store.outputs.loadingNotifications.waitUntilLoaded()
|
|
1775
|
+
// NOTE: Deliberately *not* using a dependency array here!
|
|
1776
|
+
//
|
|
1777
|
+
// It is important to call waitUntil on *every* render.
|
|
1778
|
+
// This is harmless though, on most renders, except:
|
|
1779
|
+
// 1. The very first render, in which case we'll want to trigger the initial page fetch.
|
|
1780
|
+
// 2. All other subsequent renders now "just" return the same promise (a quick operation).
|
|
1781
|
+
// 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
|
|
1782
|
+
// *next* render after that, a *new* fetch/promise will get created.
|
|
1783
|
+
);
|
|
1921
1784
|
useEffect3(() => {
|
|
1922
1785
|
poller.inc();
|
|
1923
1786
|
poller.pollNowIfStale();
|
|
@@ -1925,18 +1788,16 @@ function useInboxNotifications_withClient(client, selector, isEqual) {
|
|
|
1925
1788
|
poller.dec();
|
|
1926
1789
|
};
|
|
1927
1790
|
}, [poller]);
|
|
1928
|
-
return
|
|
1929
|
-
store.
|
|
1930
|
-
store.getInboxNotificationsLoadingState,
|
|
1931
|
-
store.getInboxNotificationsLoadingState,
|
|
1791
|
+
return useSignal(
|
|
1792
|
+
store.outputs.loadingNotifications.signal,
|
|
1932
1793
|
selector,
|
|
1933
1794
|
isEqual
|
|
1934
1795
|
);
|
|
1935
1796
|
}
|
|
1936
1797
|
function useInboxNotificationsSuspense_withClient(client) {
|
|
1937
1798
|
const store = getLiveblocksExtrasForClient(client).store;
|
|
1938
|
-
use(store.
|
|
1939
|
-
const result = useInboxNotifications_withClient(client,
|
|
1799
|
+
use(store.outputs.loadingNotifications.waitUntilLoaded());
|
|
1800
|
+
const result = useInboxNotifications_withClient(client, identity2, shallow4);
|
|
1940
1801
|
assert(!result.error, "Did not expect error");
|
|
1941
1802
|
assert(!result.isLoading, "Did not expect loading");
|
|
1942
1803
|
return result;
|
|
@@ -1950,7 +1811,7 @@ function useUnreadInboxNotificationsCount_withClient(client) {
|
|
|
1950
1811
|
}
|
|
1951
1812
|
function useUnreadInboxNotificationsCountSuspense_withClient(client) {
|
|
1952
1813
|
const store = getLiveblocksExtrasForClient(client).store;
|
|
1953
|
-
use(store.
|
|
1814
|
+
use(store.outputs.loadingNotifications.waitUntilLoaded());
|
|
1954
1815
|
const result = useUnreadInboxNotificationsCount_withClient(client);
|
|
1955
1816
|
assert(!result.isLoading, "Did not expect loading");
|
|
1956
1817
|
assert(!result.error, "Did not expect error");
|
|
@@ -2042,34 +1903,31 @@ function useDeleteAllInboxNotifications_withClient(client) {
|
|
|
2042
1903
|
}
|
|
2043
1904
|
function useInboxNotificationThread_withClient(client, inboxNotificationId) {
|
|
2044
1905
|
const { store } = getLiveblocksExtrasForClient(client);
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
(
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
`Inbox notification with ID "${inboxNotificationId}" is not of kind "thread"`
|
|
1906
|
+
return useSignal(
|
|
1907
|
+
store.outputs.threadifications,
|
|
1908
|
+
useCallback2(
|
|
1909
|
+
(state) => {
|
|
1910
|
+
const inboxNotification = state.notificationsById[inboxNotificationId] ?? raise(
|
|
1911
|
+
`Inbox notification with ID "${inboxNotificationId}" not found`
|
|
2052
1912
|
);
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
getter,
|
|
2066
|
-
selector
|
|
1913
|
+
if (inboxNotification.kind !== "thread") {
|
|
1914
|
+
raise(
|
|
1915
|
+
`Inbox notification with ID "${inboxNotificationId}" is not of kind "thread"`
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
const thread = state.threadsDB.get(inboxNotification.threadId) ?? raise(
|
|
1919
|
+
`Thread with ID "${inboxNotification.threadId}" not found, this inbox notification might not be of kind "thread"`
|
|
1920
|
+
);
|
|
1921
|
+
return thread;
|
|
1922
|
+
},
|
|
1923
|
+
[inboxNotificationId]
|
|
1924
|
+
)
|
|
2067
1925
|
);
|
|
2068
1926
|
}
|
|
2069
1927
|
function useUser_withClient(client, userId) {
|
|
2070
1928
|
const usersStore = client[kInternal2].usersStore;
|
|
2071
1929
|
const getUserState = useCallback2(
|
|
2072
|
-
() => usersStore.
|
|
1930
|
+
() => usersStore.getItemState(userId),
|
|
2073
1931
|
[usersStore, userId]
|
|
2074
1932
|
);
|
|
2075
1933
|
const selector = useCallback2(
|
|
@@ -2083,20 +1941,29 @@ function useUser_withClient(client, userId) {
|
|
|
2083
1941
|
selector,
|
|
2084
1942
|
shallow4
|
|
2085
1943
|
);
|
|
2086
|
-
useEffect3(
|
|
2087
|
-
void usersStore.
|
|
2088
|
-
|
|
1944
|
+
useEffect3(
|
|
1945
|
+
() => void usersStore.enqueue(userId)
|
|
1946
|
+
// NOTE: Deliberately *not* using a dependency array here!
|
|
1947
|
+
//
|
|
1948
|
+
// It is important to call usersStore.enqueue on *every* render.
|
|
1949
|
+
// This is harmless though, on most renders, except:
|
|
1950
|
+
// 1. The very first render, in which case we'll want to trigger evaluation
|
|
1951
|
+
// of the userId.
|
|
1952
|
+
// 2. All other subsequent renders now are a no-op (from the implementation
|
|
1953
|
+
// of .enqueue)
|
|
1954
|
+
// 3. If ever the userId gets invalidated, the user would be fetched again.
|
|
1955
|
+
);
|
|
2089
1956
|
return result;
|
|
2090
1957
|
}
|
|
2091
1958
|
function useUserSuspense_withClient(client, userId) {
|
|
2092
1959
|
const usersStore = client[kInternal2].usersStore;
|
|
2093
1960
|
const getUserState = useCallback2(
|
|
2094
|
-
() => usersStore.
|
|
1961
|
+
() => usersStore.getItemState(userId),
|
|
2095
1962
|
[usersStore, userId]
|
|
2096
1963
|
);
|
|
2097
1964
|
const userState = getUserState();
|
|
2098
1965
|
if (!userState || userState.isLoading) {
|
|
2099
|
-
throw usersStore.
|
|
1966
|
+
throw usersStore.enqueue(userId);
|
|
2100
1967
|
}
|
|
2101
1968
|
if (userState.error) {
|
|
2102
1969
|
throw userState.error;
|
|
@@ -2121,7 +1988,7 @@ function useUserSuspense_withClient(client, userId) {
|
|
|
2121
1988
|
function useRoomInfo_withClient(client, roomId) {
|
|
2122
1989
|
const roomsInfoStore = client[kInternal2].roomsInfoStore;
|
|
2123
1990
|
const getRoomInfoState = useCallback2(
|
|
2124
|
-
() => roomsInfoStore.
|
|
1991
|
+
() => roomsInfoStore.getItemState(roomId),
|
|
2125
1992
|
[roomsInfoStore, roomId]
|
|
2126
1993
|
);
|
|
2127
1994
|
const selector = useCallback2(
|
|
@@ -2135,20 +2002,29 @@ function useRoomInfo_withClient(client, roomId) {
|
|
|
2135
2002
|
selector,
|
|
2136
2003
|
shallow4
|
|
2137
2004
|
);
|
|
2138
|
-
useEffect3(
|
|
2139
|
-
void roomsInfoStore.
|
|
2140
|
-
|
|
2005
|
+
useEffect3(
|
|
2006
|
+
() => void roomsInfoStore.enqueue(roomId)
|
|
2007
|
+
// NOTE: Deliberately *not* using a dependency array here!
|
|
2008
|
+
//
|
|
2009
|
+
// It is important to call roomsInfoStore.enqueue on *every* render.
|
|
2010
|
+
// This is harmless though, on most renders, except:
|
|
2011
|
+
// 1. The very first render, in which case we'll want to trigger evaluation
|
|
2012
|
+
// of the roomId.
|
|
2013
|
+
// 2. All other subsequent renders now are a no-op (from the implementation
|
|
2014
|
+
// of .enqueue)
|
|
2015
|
+
// 3. If ever the roomId gets invalidated, the room info would be fetched again.
|
|
2016
|
+
);
|
|
2141
2017
|
return result;
|
|
2142
2018
|
}
|
|
2143
2019
|
function useRoomInfoSuspense_withClient(client, roomId) {
|
|
2144
2020
|
const roomsInfoStore = client[kInternal2].roomsInfoStore;
|
|
2145
2021
|
const getRoomInfoState = useCallback2(
|
|
2146
|
-
() => roomsInfoStore.
|
|
2022
|
+
() => roomsInfoStore.getItemState(roomId),
|
|
2147
2023
|
[roomsInfoStore, roomId]
|
|
2148
2024
|
);
|
|
2149
2025
|
const roomInfoState = getRoomInfoState();
|
|
2150
2026
|
if (!roomInfoState || roomInfoState.isLoading) {
|
|
2151
|
-
throw roomsInfoStore.
|
|
2027
|
+
throw roomsInfoStore.enqueue(roomId);
|
|
2152
2028
|
}
|
|
2153
2029
|
if (roomInfoState.error) {
|
|
2154
2030
|
throw roomInfoState.error;
|
|
@@ -2250,10 +2126,9 @@ function useUserThreads_experimental(options = {
|
|
|
2250
2126
|
}) {
|
|
2251
2127
|
const client = useClient();
|
|
2252
2128
|
const { store, userThreadsPoller: poller } = getLiveblocksExtrasForClient(client);
|
|
2129
|
+
const queryKey = makeUserThreadsQueryKey(options.query);
|
|
2253
2130
|
useEffect3(
|
|
2254
|
-
() =>
|
|
2255
|
-
void store.waitUntilUserThreadsLoaded(options.query);
|
|
2256
|
-
}
|
|
2131
|
+
() => void store.outputs.loadingUserThreads.getOrCreate(queryKey).waitUntilLoaded()
|
|
2257
2132
|
// NOTE: Deliberately *not* using a dependency array here!
|
|
2258
2133
|
//
|
|
2259
2134
|
// It is important to call waitUntil on *every* render.
|
|
@@ -2270,17 +2145,8 @@ function useUserThreads_experimental(options = {
|
|
|
2270
2145
|
poller.dec();
|
|
2271
2146
|
};
|
|
2272
2147
|
}, [poller]);
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
[store, options.query]
|
|
2276
|
-
);
|
|
2277
|
-
return useSyncExternalStoreWithSelector(
|
|
2278
|
-
store.subscribe1_threads,
|
|
2279
|
-
getter,
|
|
2280
|
-
getter,
|
|
2281
|
-
identity,
|
|
2282
|
-
shallow2
|
|
2283
|
-
// NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
|
|
2148
|
+
return useSignal(
|
|
2149
|
+
store.outputs.loadingUserThreads.getOrCreate(queryKey).signal
|
|
2284
2150
|
);
|
|
2285
2151
|
}
|
|
2286
2152
|
function useUserThreadsSuspense_experimental(options = {
|
|
@@ -2290,14 +2156,15 @@ function useUserThreadsSuspense_experimental(options = {
|
|
|
2290
2156
|
}) {
|
|
2291
2157
|
const client = useClient();
|
|
2292
2158
|
const { store } = getLiveblocksExtrasForClient(client);
|
|
2293
|
-
|
|
2159
|
+
const queryKey = makeUserThreadsQueryKey(options.query);
|
|
2160
|
+
use(store.outputs.loadingUserThreads.getOrCreate(queryKey).waitUntilLoaded());
|
|
2294
2161
|
const result = useUserThreads_experimental(options);
|
|
2295
2162
|
assert(!result.error, "Did not expect error");
|
|
2296
2163
|
assert(!result.isLoading, "Did not expect loading");
|
|
2297
2164
|
return result;
|
|
2298
2165
|
}
|
|
2299
2166
|
function useInboxNotifications() {
|
|
2300
|
-
return useInboxNotifications_withClient(useClient(),
|
|
2167
|
+
return useInboxNotifications_withClient(useClient(), identity2, shallow4);
|
|
2301
2168
|
}
|
|
2302
2169
|
function useInboxNotificationsSuspense() {
|
|
2303
2170
|
return useInboxNotificationsSuspense_withClient(useClient());
|
|
@@ -2484,18 +2351,6 @@ var UpdateNotificationSettingsError = class extends Error {
|
|
|
2484
2351
|
}
|
|
2485
2352
|
};
|
|
2486
2353
|
|
|
2487
|
-
// src/use-signal.ts
|
|
2488
|
-
var identity2 = (value) => value;
|
|
2489
|
-
function useSignal(signal, selector, isEqual) {
|
|
2490
|
-
return useSyncExternalStoreWithSelector(
|
|
2491
|
-
signal.subscribe,
|
|
2492
|
-
signal.get,
|
|
2493
|
-
signal.get,
|
|
2494
|
-
selector ?? identity2,
|
|
2495
|
-
isEqual
|
|
2496
|
-
);
|
|
2497
|
-
}
|
|
2498
|
-
|
|
2499
2354
|
// src/room.tsx
|
|
2500
2355
|
import { shallow as shallow5 } from "@liveblocks/client";
|
|
2501
2356
|
import {
|
|
@@ -2503,10 +2358,11 @@ import {
|
|
|
2503
2358
|
console as console3,
|
|
2504
2359
|
createCommentId,
|
|
2505
2360
|
createThreadId,
|
|
2361
|
+
DefaultMap as DefaultMap2,
|
|
2506
2362
|
errorIf,
|
|
2507
2363
|
HttpError as HttpError2,
|
|
2508
2364
|
kInternal as kInternal3,
|
|
2509
|
-
makeEventSource
|
|
2365
|
+
makeEventSource,
|
|
2510
2366
|
makePoller as makePoller2,
|
|
2511
2367
|
ServerMsgCode
|
|
2512
2368
|
} from "@liveblocks/core";
|
|
@@ -2628,7 +2484,7 @@ function getRoomExtrasForClient(client) {
|
|
|
2628
2484
|
}
|
|
2629
2485
|
function makeRoomExtrasForClient(client) {
|
|
2630
2486
|
const store = getUmbrellaStoreForClient(client);
|
|
2631
|
-
const commentsErrorEventSource =
|
|
2487
|
+
const commentsErrorEventSource = makeEventSource();
|
|
2632
2488
|
function onMutationFailure(innerError, optimisticId, createPublicError) {
|
|
2633
2489
|
store.optimisticUpdates.remove(optimisticId);
|
|
2634
2490
|
if (innerError instanceof HttpError2) {
|
|
@@ -2642,73 +2498,59 @@ function makeRoomExtrasForClient(client) {
|
|
|
2642
2498
|
}
|
|
2643
2499
|
throw innerError;
|
|
2644
2500
|
}
|
|
2645
|
-
const threadsPollersByRoomId =
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
}
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
let poller = roomNotificationSettingsPollersByRoomId.get(roomId);
|
|
2688
|
-
if (!poller) {
|
|
2689
|
-
poller = makePoller2(
|
|
2690
|
-
async (signal) => {
|
|
2691
|
-
try {
|
|
2692
|
-
return await store.refreshRoomNotificationSettings(roomId, signal);
|
|
2693
|
-
} catch (err) {
|
|
2694
|
-
console3.warn(`Polling notification settings for '${roomId}' failed: ${String(err)}`);
|
|
2695
|
-
throw err;
|
|
2696
|
-
}
|
|
2697
|
-
},
|
|
2698
|
-
config.NOTIFICATION_SETTINGS_POLL_INTERVAL,
|
|
2699
|
-
{ maxStaleTimeMs: config.NOTIFICATION_SETTINGS_MAX_STALE_TIME }
|
|
2700
|
-
);
|
|
2701
|
-
roomNotificationSettingsPollersByRoomId.set(roomId, poller);
|
|
2702
|
-
}
|
|
2703
|
-
return poller;
|
|
2704
|
-
}
|
|
2501
|
+
const threadsPollersByRoomId = new DefaultMap2(
|
|
2502
|
+
(roomId) => makePoller2(
|
|
2503
|
+
async (signal) => {
|
|
2504
|
+
try {
|
|
2505
|
+
return await store.fetchRoomThreadsDeltaUpdate(roomId, signal);
|
|
2506
|
+
} catch (err) {
|
|
2507
|
+
console3.warn(`Polling new threads for '${roomId}' failed: ${String(err)}`);
|
|
2508
|
+
throw err;
|
|
2509
|
+
}
|
|
2510
|
+
},
|
|
2511
|
+
config.ROOM_THREADS_POLL_INTERVAL,
|
|
2512
|
+
{ maxStaleTimeMs: config.ROOM_THREADS_MAX_STALE_TIME }
|
|
2513
|
+
)
|
|
2514
|
+
);
|
|
2515
|
+
const versionsPollersByRoomId = new DefaultMap2(
|
|
2516
|
+
(roomId) => makePoller2(
|
|
2517
|
+
async (signal) => {
|
|
2518
|
+
try {
|
|
2519
|
+
return await store.fetchRoomVersionsDeltaUpdate(roomId, signal);
|
|
2520
|
+
} catch (err) {
|
|
2521
|
+
console3.warn(`Polling new history versions for '${roomId}' failed: ${String(err)}`);
|
|
2522
|
+
throw err;
|
|
2523
|
+
}
|
|
2524
|
+
},
|
|
2525
|
+
config.HISTORY_VERSIONS_POLL_INTERVAL,
|
|
2526
|
+
{ maxStaleTimeMs: config.HISTORY_VERSIONS_MAX_STALE_TIME }
|
|
2527
|
+
)
|
|
2528
|
+
);
|
|
2529
|
+
const roomNotificationSettingsPollersByRoomId = new DefaultMap2(
|
|
2530
|
+
(roomId) => makePoller2(
|
|
2531
|
+
async (signal) => {
|
|
2532
|
+
try {
|
|
2533
|
+
return await store.refreshRoomNotificationSettings(roomId, signal);
|
|
2534
|
+
} catch (err) {
|
|
2535
|
+
console3.warn(`Polling notification settings for '${roomId}' failed: ${String(err)}`);
|
|
2536
|
+
throw err;
|
|
2537
|
+
}
|
|
2538
|
+
},
|
|
2539
|
+
config.NOTIFICATION_SETTINGS_POLL_INTERVAL,
|
|
2540
|
+
{ maxStaleTimeMs: config.NOTIFICATION_SETTINGS_MAX_STALE_TIME }
|
|
2541
|
+
)
|
|
2542
|
+
);
|
|
2705
2543
|
return {
|
|
2706
2544
|
store,
|
|
2707
2545
|
commentsErrorEventSource: commentsErrorEventSource.observable,
|
|
2708
2546
|
onMutationFailure,
|
|
2709
|
-
getOrCreateThreadsPollerForRoomId
|
|
2710
|
-
|
|
2711
|
-
|
|
2547
|
+
getOrCreateThreadsPollerForRoomId: threadsPollersByRoomId.getOrCreate.bind(
|
|
2548
|
+
threadsPollersByRoomId
|
|
2549
|
+
),
|
|
2550
|
+
getOrCreateVersionsPollerForRoomId: versionsPollersByRoomId.getOrCreate.bind(versionsPollersByRoomId),
|
|
2551
|
+
getOrCreateNotificationsSettingsPollerForRoomId: roomNotificationSettingsPollersByRoomId.getOrCreate.bind(
|
|
2552
|
+
roomNotificationSettingsPollersByRoomId
|
|
2553
|
+
)
|
|
2712
2554
|
};
|
|
2713
2555
|
}
|
|
2714
2556
|
function makeRoomContextBundle(client) {
|
|
@@ -2887,7 +2729,7 @@ function RoomProviderInner(props) {
|
|
|
2887
2729
|
return;
|
|
2888
2730
|
}
|
|
2889
2731
|
const { thread, inboxNotification: maybeNotification } = info;
|
|
2890
|
-
const existingThread = store.
|
|
2732
|
+
const existingThread = store.outputs.threads.get().getEvenIfDeleted(message.threadId);
|
|
2891
2733
|
switch (message.type) {
|
|
2892
2734
|
case ServerMsgCode.COMMENT_EDITED:
|
|
2893
2735
|
case ServerMsgCode.THREAD_METADATA_UPDATED:
|
|
@@ -3258,18 +3100,15 @@ function useMutation(callback, deps) {
|
|
|
3258
3100
|
[room, ...deps]
|
|
3259
3101
|
);
|
|
3260
3102
|
}
|
|
3261
|
-
function useThreads(options = {
|
|
3262
|
-
query: { metadata: {} }
|
|
3263
|
-
}) {
|
|
3103
|
+
function useThreads(options = {}) {
|
|
3264
3104
|
const { scrollOnLoad = true } = options;
|
|
3265
3105
|
const client = useClient();
|
|
3266
3106
|
const room = useRoom();
|
|
3267
3107
|
const { store, getOrCreateThreadsPollerForRoomId } = getRoomExtrasForClient(client);
|
|
3108
|
+
const queryKey = makeRoomThreadsQueryKey(room.id, options.query);
|
|
3268
3109
|
const poller = getOrCreateThreadsPollerForRoomId(room.id);
|
|
3269
3110
|
useEffect5(
|
|
3270
|
-
() =>
|
|
3271
|
-
void store.waitUntilRoomThreadsLoaded(room.id, options.query);
|
|
3272
|
-
}
|
|
3111
|
+
() => void store.outputs.loadingRoomThreads.getOrCreate(queryKey).waitUntilLoaded()
|
|
3273
3112
|
// NOTE: Deliberately *not* using a dependency array here!
|
|
3274
3113
|
//
|
|
3275
3114
|
// It is important to call waitUntil on *every* render.
|
|
@@ -3284,20 +3123,11 @@ function useThreads(options = {
|
|
|
3284
3123
|
poller.pollNowIfStale();
|
|
3285
3124
|
return () => poller.dec();
|
|
3286
3125
|
}, [poller]);
|
|
3287
|
-
const
|
|
3288
|
-
|
|
3289
|
-
[store, room.id, options.query]
|
|
3290
|
-
);
|
|
3291
|
-
const state = useSyncExternalStoreWithSelector(
|
|
3292
|
-
store.subscribe1_threads,
|
|
3293
|
-
getter,
|
|
3294
|
-
getter,
|
|
3295
|
-
identity3,
|
|
3296
|
-
shallow2
|
|
3297
|
-
// NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
|
|
3126
|
+
const result = useSignal(
|
|
3127
|
+
store.outputs.loadingRoomThreads.getOrCreate(queryKey).signal
|
|
3298
3128
|
);
|
|
3299
|
-
useScrollToCommentOnLoadEffect(scrollOnLoad,
|
|
3300
|
-
return
|
|
3129
|
+
useScrollToCommentOnLoadEffect(scrollOnLoad, result);
|
|
3130
|
+
return result;
|
|
3301
3131
|
}
|
|
3302
3132
|
function useCommentsErrorListener(callback) {
|
|
3303
3133
|
const client = useClient();
|
|
@@ -3385,7 +3215,7 @@ function useDeleteRoomThread(roomId) {
|
|
|
3385
3215
|
(threadId) => {
|
|
3386
3216
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3387
3217
|
const userId = getCurrentUserId(client);
|
|
3388
|
-
const existing = store.
|
|
3218
|
+
const existing = store.outputs.threads.get().get(threadId);
|
|
3389
3219
|
if (existing?.comments?.[0]?.userId !== userId) {
|
|
3390
3220
|
throw new Error("Only the thread creator can delete the thread");
|
|
3391
3221
|
}
|
|
@@ -3503,7 +3333,7 @@ function useEditRoomComment(roomId) {
|
|
|
3503
3333
|
({ threadId, commentId, body, attachments }) => {
|
|
3504
3334
|
const editedAt = /* @__PURE__ */ new Date();
|
|
3505
3335
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3506
|
-
const existing = store.
|
|
3336
|
+
const existing = store.outputs.threads.get().getEvenIfDeleted(threadId);
|
|
3507
3337
|
if (existing === void 0) {
|
|
3508
3338
|
console3.warn(
|
|
3509
3339
|
`Internal unexpected behavior. Cannot edit comment in thread "${threadId}" because the thread does not exist in the cache.`
|
|
@@ -3680,7 +3510,7 @@ function useMarkRoomThreadAsRead(roomId) {
|
|
|
3680
3510
|
(threadId) => {
|
|
3681
3511
|
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3682
3512
|
const inboxNotification = Object.values(
|
|
3683
|
-
store.
|
|
3513
|
+
store.outputs.notifications.get().notificationsById
|
|
3684
3514
|
).find(
|
|
3685
3515
|
(inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
|
|
3686
3516
|
);
|
|
@@ -3818,9 +3648,7 @@ function useRoomNotificationSettings() {
|
|
|
3818
3648
|
const { store, getOrCreateNotificationsSettingsPollerForRoomId } = getRoomExtrasForClient(client);
|
|
3819
3649
|
const poller = getOrCreateNotificationsSettingsPollerForRoomId(room.id);
|
|
3820
3650
|
useEffect5(
|
|
3821
|
-
() =>
|
|
3822
|
-
void store.waitUntilRoomNotificationSettingsLoaded(room.id);
|
|
3823
|
-
}
|
|
3651
|
+
() => void store.outputs.settingsByRoomId.getOrCreate(room.id).waitUntilLoaded()
|
|
3824
3652
|
// NOTE: Deliberately *not* using a dependency array here!
|
|
3825
3653
|
//
|
|
3826
3654
|
// It is important to call waitUntil on *every* render.
|
|
@@ -3837,16 +3665,8 @@ function useRoomNotificationSettings() {
|
|
|
3837
3665
|
poller.dec();
|
|
3838
3666
|
};
|
|
3839
3667
|
}, [poller]);
|
|
3840
|
-
const
|
|
3841
|
-
|
|
3842
|
-
[store, room.id]
|
|
3843
|
-
);
|
|
3844
|
-
const settings = useSyncExternalStoreWithSelector(
|
|
3845
|
-
store.subscribe2,
|
|
3846
|
-
getter,
|
|
3847
|
-
getter,
|
|
3848
|
-
identity3,
|
|
3849
|
-
shallow2
|
|
3668
|
+
const settings = useSignal(
|
|
3669
|
+
store.outputs.settingsByRoomId.getOrCreate(room.id).signal
|
|
3850
3670
|
);
|
|
3851
3671
|
return useMemo3(() => {
|
|
3852
3672
|
return [settings, updateRoomNotificationSettings];
|
|
@@ -3856,7 +3676,7 @@ function useRoomNotificationSettingsSuspense() {
|
|
|
3856
3676
|
const client = useClient();
|
|
3857
3677
|
const store = getRoomExtrasForClient(client).store;
|
|
3858
3678
|
const room = useRoom();
|
|
3859
|
-
use(store.
|
|
3679
|
+
use(store.outputs.settingsByRoomId.getOrCreate(room.id).waitUntilLoaded());
|
|
3860
3680
|
const [settings, updateRoomNotificationSettings] = useRoomNotificationSettings();
|
|
3861
3681
|
assert2(!settings.error, "Did not expect error");
|
|
3862
3682
|
assert2(!settings.isLoading, "Did not expect loading");
|
|
@@ -3903,14 +3723,8 @@ function useHistoryVersions() {
|
|
|
3903
3723
|
poller.pollNowIfStale();
|
|
3904
3724
|
return () => poller.dec();
|
|
3905
3725
|
}, [poller]);
|
|
3906
|
-
const getter = useCallback3(
|
|
3907
|
-
() => store.getRoomVersionsLoadingState(room.id),
|
|
3908
|
-
[store, room.id]
|
|
3909
|
-
);
|
|
3910
3726
|
useEffect5(
|
|
3911
|
-
() =>
|
|
3912
|
-
void store.waitUntilRoomVersionsLoaded(room.id);
|
|
3913
|
-
}
|
|
3727
|
+
() => void store.outputs.versionsByRoomId.getOrCreate(room.id).waitUntilLoaded()
|
|
3914
3728
|
// NOTE: Deliberately *not* using a dependency array here!
|
|
3915
3729
|
//
|
|
3916
3730
|
// It is important to call waitUntil on *every* render.
|
|
@@ -3920,20 +3734,13 @@ function useHistoryVersions() {
|
|
|
3920
3734
|
// 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
|
|
3921
3735
|
// *next* render after that, a *new* fetch/promise will get created.
|
|
3922
3736
|
);
|
|
3923
|
-
|
|
3924
|
-
store.subscribe3,
|
|
3925
|
-
getter,
|
|
3926
|
-
getter,
|
|
3927
|
-
identity3,
|
|
3928
|
-
shallow2
|
|
3929
|
-
);
|
|
3930
|
-
return state;
|
|
3737
|
+
return useSignal(store.outputs.versionsByRoomId.getOrCreate(room.id).signal);
|
|
3931
3738
|
}
|
|
3932
3739
|
function useHistoryVersionsSuspense() {
|
|
3933
3740
|
const client = useClient();
|
|
3934
3741
|
const room = useRoom();
|
|
3935
3742
|
const store = getRoomExtrasForClient(client).store;
|
|
3936
|
-
use(store.
|
|
3743
|
+
use(store.outputs.versionsByRoomId.getOrCreate(room.id).waitUntilLoaded());
|
|
3937
3744
|
const result = useHistoryVersions();
|
|
3938
3745
|
assert2(!result.error, "Did not expect error");
|
|
3939
3746
|
assert2(!result.isLoading, "Did not expect loading");
|
|
@@ -4020,13 +3827,12 @@ function useStorageStatusSuspense(options) {
|
|
|
4020
3827
|
useSuspendUntilStorageReady();
|
|
4021
3828
|
return useStorageStatus(options);
|
|
4022
3829
|
}
|
|
4023
|
-
function useThreadsSuspense(options = {
|
|
4024
|
-
query: { metadata: {} }
|
|
4025
|
-
}) {
|
|
3830
|
+
function useThreadsSuspense(options = {}) {
|
|
4026
3831
|
const client = useClient();
|
|
4027
3832
|
const room = useRoom();
|
|
4028
3833
|
const { store } = getRoomExtrasForClient(client);
|
|
4029
|
-
|
|
3834
|
+
const queryKey = makeRoomThreadsQueryKey(room.id, options.query);
|
|
3835
|
+
use(store.outputs.loadingRoomThreads.getOrCreate(queryKey).waitUntilLoaded());
|
|
4030
3836
|
const result = useThreads(options);
|
|
4031
3837
|
assert2(!result.error, "Did not expect error");
|
|
4032
3838
|
assert2(!result.isLoading, "Did not expect loading");
|
|
@@ -4053,11 +3859,11 @@ function useRoomAttachmentUrl(attachmentId, roomId) {
|
|
|
4053
3859
|
const client = useClient();
|
|
4054
3860
|
const store = client[kInternal3].httpClient.getOrCreateAttachmentUrlsStore(roomId);
|
|
4055
3861
|
const getAttachmentUrlState = useCallback3(
|
|
4056
|
-
() => store.
|
|
3862
|
+
() => store.getItemState(attachmentId),
|
|
4057
3863
|
[store, attachmentId]
|
|
4058
3864
|
);
|
|
4059
3865
|
useEffect5(() => {
|
|
4060
|
-
void store.
|
|
3866
|
+
void store.enqueue(attachmentId);
|
|
4061
3867
|
}, [store, attachmentId]);
|
|
4062
3868
|
return useSyncExternalStoreWithSelector(
|
|
4063
3869
|
store.subscribe,
|
|
@@ -4071,12 +3877,12 @@ function useAttachmentUrlSuspense(attachmentId) {
|
|
|
4071
3877
|
const room = useRoom();
|
|
4072
3878
|
const { attachmentUrlsStore } = room[kInternal3];
|
|
4073
3879
|
const getAttachmentUrlState = useCallback3(
|
|
4074
|
-
() => attachmentUrlsStore.
|
|
3880
|
+
() => attachmentUrlsStore.getItemState(attachmentId),
|
|
4075
3881
|
[attachmentUrlsStore, attachmentId]
|
|
4076
3882
|
);
|
|
4077
3883
|
const attachmentUrlState = getAttachmentUrlState();
|
|
4078
3884
|
if (!attachmentUrlState || attachmentUrlState.isLoading) {
|
|
4079
|
-
throw attachmentUrlsStore.
|
|
3885
|
+
throw attachmentUrlsStore.enqueue(attachmentId);
|
|
4080
3886
|
}
|
|
4081
3887
|
if (attachmentUrlState.error) {
|
|
4082
3888
|
throw attachmentUrlState.error;
|
|
@@ -4095,12 +3901,13 @@ function useAttachmentUrlSuspense(attachmentId) {
|
|
|
4095
3901
|
error: void 0
|
|
4096
3902
|
};
|
|
4097
3903
|
}
|
|
3904
|
+
var NO_PERMISSIONS = /* @__PURE__ */ new Set();
|
|
4098
3905
|
function useRoomPermissions(roomId) {
|
|
4099
3906
|
const client = useClient();
|
|
4100
3907
|
const store = getRoomExtrasForClient(client).store;
|
|
4101
3908
|
return useSignal(
|
|
4102
3909
|
store.permissionHints.signal,
|
|
4103
|
-
(hints) => hints
|
|
3910
|
+
(hints) => hints.get(roomId) ?? NO_PERMISSIONS
|
|
4104
3911
|
);
|
|
4105
3912
|
}
|
|
4106
3913
|
function createRoomContext(client) {
|
|
@@ -4149,6 +3956,7 @@ export {
|
|
|
4149
3956
|
RoomContext,
|
|
4150
3957
|
useRoomOrNull,
|
|
4151
3958
|
useSyncExternalStoreWithSelector,
|
|
3959
|
+
useSignal,
|
|
4152
3960
|
ClientContext,
|
|
4153
3961
|
getUmbrellaStoreForClient,
|
|
4154
3962
|
useClientOrNull,
|
|
@@ -4172,7 +3980,6 @@ export {
|
|
|
4172
3980
|
_useUserThreadsSuspense_experimental,
|
|
4173
3981
|
useSyncStatus,
|
|
4174
3982
|
CreateThreadError,
|
|
4175
|
-
useSignal,
|
|
4176
3983
|
useStatus,
|
|
4177
3984
|
useReportTextEditor,
|
|
4178
3985
|
useYjsProvider,
|
|
@@ -4250,4 +4057,4 @@ export {
|
|
|
4250
4057
|
_useStorageRoot,
|
|
4251
4058
|
_useUpdateMyPresence
|
|
4252
4059
|
};
|
|
4253
|
-
//# sourceMappingURL=chunk-
|
|
4060
|
+
//# sourceMappingURL=chunk-EEYUKRIA.mjs.map
|