@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.
@@ -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
+ _nullishCoalesce(selector, () => ( identity)),
96
+ isEqual
97
+ );
98
+ }
99
+
88
100
  // src/liveblocks.tsx
89
101
 
90
102
 
@@ -121,19 +133,30 @@ var config = {
121
133
  NOTIFICATION_SETTINGS_MAX_STALE_TIME: 5 * SECONDS
122
134
  };
123
135
 
124
- // src/lib/shallow2.ts
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 });
144
+ }
145
+ }
125
146
 
126
- function shallow2(a, b) {
127
- if (!_core.isPlainObject.call(void 0, a) || !_core.isPlainObject.call(void 0, b)) {
128
- return _core.shallow.call(void 0, a, b);
147
+ // src/lib/itertools.ts
148
+ function find(it, predicate) {
149
+ for (const item of it) {
150
+ if (predicate(item)) return item;
129
151
  }
130
- const keysA = Object.keys(a);
131
- if (keysA.length !== Object.keys(b).length) {
132
- return false;
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++;
133
158
  }
134
- return keysA.every(
135
- (key) => Object.prototype.hasOwnProperty.call(b, key) && _core.shallow.call(void 0, a[key], b[key])
136
- );
159
+ return total;
137
160
  }
138
161
 
139
162
  // src/lib/use-initial.ts
@@ -211,6 +234,7 @@ var use = (
211
234
 
212
235
 
213
236
 
237
+
214
238
  // src/lib/autobind.ts
215
239
  function autobind(self) {
216
240
  const seen = /* @__PURE__ */ new Set();
@@ -228,12 +252,19 @@ function autobind(self) {
228
252
  } while ((obj = Reflect.getPrototypeOf(obj)) && obj !== Object.prototype);
229
253
  }
230
254
 
231
- // src/lib/itertools.ts
232
- function find(it, predicate) {
233
- for (const item of it) {
234
- if (predicate(item)) return item;
255
+ // src/lib/shallow2.ts
256
+
257
+ function shallow2(a, b) {
258
+ if (!_core.isPlainObject.call(void 0, a) || !_core.isPlainObject.call(void 0, b)) {
259
+ return _core.shallow.call(void 0, a, b);
235
260
  }
236
- return void 0;
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) && _core.shallow.call(void 0, 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(updates) {
389
+ applyDelta(newThreads, deletedThreads) {
359
390
  _core.batch.call(void 0, () => {
360
- for (const thread of updates.newThreads) {
391
+ for (const thread of newThreads) {
361
392
  this.upsertIfNewer(thread);
362
393
  }
363
- for (const { id, deletedAt } of updates.deletedThreads) {
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 `${roomId}-${_core.stringify.call(void 0, _nullishCoalesce(query, () => ( {})))}`;
435
+ return _core.stringify.call(void 0, [roomId, _nullishCoalesce(query, () => ( {}))]);
405
436
  }
406
437
  function makeUserThreadsQueryKey(query) {
407
- return `USER_THREADS:${_core.stringify.call(void 0, _nullishCoalesce(query, () => ( {})))}`;
408
- }
409
- function makeNotificationSettingsQueryKey(roomId) {
410
- return `${roomId}:NOTIFICATION_SETTINGS`;
411
- }
412
- function makeVersionsQueryKey(roomId) {
413
- return `${roomId}-VERSIONS`;
438
+ return _core.stringify.call(void 0, _nullishCoalesce(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 {
460
+ #signal;
436
461
 
437
- #eventSource;
438
462
  #fetchPage;
439
- #paginationState;
440
- // Should be null while in loading or error state!
441
463
  #pendingFetchMore;
442
464
  constructor(fetchPage) {
443
- this.#paginationState = null;
465
+ this.#signal = new (0, _core.Signal)(ASYNC_LOADING);
444
466
  this.#fetchPage = fetchPage;
445
- this.#eventSource = _core.makeEventSource.call(void 0, );
446
467
  this.#pendingFetchMore = null;
447
- this.observable = this.#eventSource.observable;
468
+ this.signal = this.#signal.asReadonly();
448
469
  autobind(this);
449
470
  }
450
- #patchPaginationState(patch) {
451
- const state = this.#paginationState;
452
- if (state === null) return;
453
- this.#paginationState = { ...state, ...patch };
454
- this.#eventSource.notify();
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.#paginationState;
458
- if (!_optionalChain([state, 'optionalAccess', _3 => _3.cursor])) {
480
+ const state = this.#signal.get();
481
+ if (!_optionalChain([state, 'access', _3 => _3.data, 'optionalAccess', _4 => _4.cursor]) || state.data.isFetchingMore) {
459
482
  return;
460
483
  }
461
- this.#patchPaginationState({ isFetchingMore: true });
484
+ this.#patch({ isFetchingMore: true });
462
485
  try {
463
- const nextCursor = await this.#fetchPage(state.cursor);
464
- this.#patchPaginationState({
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.#patchPaginationState({
494
+ this.#patch({
471
495
  isFetchingMore: false,
472
496
  fetchMoreError: err
473
497
  });
474
498
  }
475
499
  }
476
500
  fetchMore() {
477
- const state = this.#paginationState;
478
- if (_optionalChain([state, 'optionalAccess', _4 => _4.cursor]) === null) {
479
- return noop2;
480
- }
501
+ const state = this.#signal.get();
502
+ if (!_optionalChain([state, 'access', _5 => _5.data, 'optionalAccess', _6 => _6.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 initialFetcher = _core.autoRetry.call(void 0,
515
+ const initialPageFetch$ = _core.autoRetry.call(void 0,
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
- () => this.#eventSource.notify(),
531
- () => {
532
- this.#eventSource.notify();
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.#eventSource.notify();
540
+ this.#signal.set(ASYNC_LOADING);
536
541
  }, 5e3);
537
542
  }
538
543
  );
539
544
  this.#cachedPromise = promise;
540
- return promise;
545
+ return this.#cachedPromise;
541
546
  }
542
547
  };
543
548
  var SinglePageResource = class {
549
+ #signal;
544
550
 
545
- #eventSource;
546
551
  #fetchPage;
547
552
  constructor(fetchPage) {
553
+ this.#signal = new (0, _core.Signal)(ASYNC_LOADING);
554
+ this.signal = this.#signal.asReadonly();
548
555
  this.#fetchPage = fetchPage;
549
- this.#eventSource = _core.makeEventSource.call(void 0, );
550
- this.observable = this.#eventSource.observable;
551
556
  autobind(this);
552
557
  }
553
558
  get() {
554
- const usable = this.#cachedPromise;
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 = _core.autoRetry.call(void 0,
566
+ const initialFetcher$ = _core.autoRetry.call(void 0,
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.#eventSource.notify();
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.#eventSource.notify();
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(newInboxNotifications, deletedNotifications) {
613
+ function applyDelta(newNotifications, deletedNotifications) {
614
614
  signal.mutate((lut) => {
615
615
  let mutated = false;
616
- for (const n of newInboxNotifications) {
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
- // XXX_vincent Remove this eventually
657
- force_set: (mutationCallback) => signal.mutate(mutationCallback),
658
- invalidate: () => signal.mutate()
661
+ upsert
659
662
  };
660
663
  }
661
- function createStore_forRoomNotificationSettings() {
662
- const signal = new (0, _core.MutableSignal)(/* @__PURE__ */ new Map());
664
+ function createStore_forRoomNotificationSettings(updates) {
665
+ const baseSignal = new (0, _core.MutableSignal)(/* @__PURE__ */ new Map());
663
666
  function update(roomId, settings) {
664
- signal.mutate((lut) => {
667
+ baseSignal.mutate((lut) => {
665
668
  lut.set(roomId, settings);
666
669
  });
667
670
  }
668
671
  return {
669
- signal: signal.asReadonly(),
672
+ signal: _core.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 signal = new (0, _core.MutableSignal)(/* @__PURE__ */ new Map());
682
+ const baseSignal = new (0, _core.MutableSignal)(
683
+ new (0, _core.DefaultMap)(() => /* @__PURE__ */ new Map())
684
+ );
678
685
  function update(roomId, versions) {
679
- signal.mutate((lut) => {
680
- const versionsById = _nullishCoalesce(lut.get(roomId), () => ( (lut.set(roomId, /* @__PURE__ */ new Map()), lut.get(roomId))));
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: signal.asReadonly(),
694
+ signal: _core.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 (0, _core.Signal)({});
708
+ const signal = new (0, _core.MutableSignal)(
709
+ new (0, _core.DefaultMap)(() => /* @__PURE__ */ new Set())
710
+ );
697
711
  function update(newHints) {
698
- signal.set((prev) => {
699
- const permissionsByRoom = { ...prev };
712
+ signal.mutate((lut) => {
700
713
  for (const [roomId, newPermissions] of Object.entries(newHints)) {
701
- const existing = _nullishCoalesce(permissionsByRoom[roomId], () => ( /* @__PURE__ */ new Set()));
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
 
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
- #notifications;
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[_core.kInternal].as();
811
811
  this.optimisticUpdates = createStore_forOptimistic(this.#client);
812
812
  this.permissionHints = createStore_forPermissionHints();
813
- const inboxFetcher = async (cursor) => {
814
- const result = await this.#client.getInboxNotifications({ cursor });
815
- this.updateThreadifications(result.threads, result.inboxNotifications);
816
- if (this.#notificationsLastRequestedAt === null) {
817
- this.#notificationsLastRequestedAt = result.requestedAt;
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 = _core.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 = _core.DerivedSignal.from(
841
- threadifications,
842
- (s) => ({
843
- threadsDB: s.threadsDB
844
- }),
845
- _core.shallow
846
- );
836
+ const threads = _core.DerivedSignal.from(threadifications, (s) => s.threadsDB);
847
837
  const notifications = _core.DerivedSignal.from(
848
838
  threadifications,
849
839
  (s) => ({
@@ -852,177 +842,181 @@ var UmbrellaStore = class {
852
842
  }),
853
843
  _core.shallow
854
844
  );
855
- const settingsByRoomId = _core.DerivedSignal.from(
856
- this.roomNotificationSettings.signal,
857
- this.optimisticUpdates.signal,
858
- (settings, updates) => applyOptimisticUpdates_forSettings(settings, updates)
845
+ const loadingUserThreads = new (0, _core.DefaultMap)(
846
+ (queryKey) => {
847
+ const query = _core.unstringify.call(void 0, queryKey);
848
+ const resource = new PaginatedResource(async (cursor) => {
849
+ const result = await this.#client[_core.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 = _core.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
+ _nullishCoalesce(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 versionsByRoomId = _core.DerivedSignal.from(
861
- this.historyVersions.signal,
862
- (hv) => Object.fromEntries(
863
- [...hv].map(([roomId, versions]) => [
864
- roomId,
865
- Object.fromEntries(versions)
866
- ])
867
- )
887
+ const loadingRoomThreads = new (0, _core.DefaultMap)(
888
+ (queryKey) => {
889
+ const [roomId, query] = _core.unstringify.call(void 0, queryKey);
890
+ const resource = new PaginatedResource(async (cursor) => {
891
+ const result = await this.#client[_core.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 = _core.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, _nullishCoalesce(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: _core.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 (0, _core.DefaultMap)((roomId) => {
948
+ const resource = new SinglePageResource(async () => {
949
+ const room = this.#client.getRoom(roomId);
950
+ if (room === null) {
951
+ throw new (0, _core.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 = _core.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
+ _core.nn.call(void 0, this.roomNotificationSettings.signal.get()[roomId])
967
+ );
968
+ }
969
+ }, _core.shallow);
970
+ return { signal, waitUntilLoaded: resource.waitUntilLoaded };
971
+ });
972
+ const versionsByRoomId = new (0, _core.DefaultMap)(
973
+ (roomId) => {
974
+ const resource = new SinglePageResource(async () => {
975
+ const room = this.#client.getRoom(roomId);
976
+ if (room === null) {
977
+ throw new (0, _core.HttpError)(
978
+ `Room '${roomId}' is not available on client`,
979
+ 479
980
+ );
981
+ }
982
+ const result = await room[_core.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 = _core.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
+ _nullishCoalesce(this.historyVersions.signal.get()[roomId], () => ( {}))
1001
+ )
1002
+ };
1003
+ }
1004
+ }, _core.shallow);
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
- _nullishCoalesce(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
- _nullishCoalesce(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: _core.nn.call(void 0, 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(_nullishCoalesce(this.get3()[roomId], () => ( {})))
1010
- };
1011
- }
1012
- /** @internal - Only call this method from unit tests. */
1013
- force_set_versions(callback) {
1014
- _core.batch.call(void 0, () => {
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
- _core.batch.call(void 0, () => {
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
  _core.batch.call(void 0, () => {
1167
- this.threads.applyDelta({ newThreads: threads, deletedThreads });
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[_core.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[_core.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
- _core.batch.call(void 0, () => {
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 (0, _core.HttpError)(
1321
- `Room '${roomId}' is not available on client`,
1322
- 479
1323
- );
1324
- }
1325
- const result = await room[_core.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 (0, _core.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 = _core.nn.call(void 0,
1394
1255
  this.#client.getRoom(roomId),
@@ -1620,7 +1481,7 @@ function applyUpsertComment(thread, comment) {
1620
1481
  updatedAt: new Date(
1621
1482
  Math.max(
1622
1483
  thread.updatedAt.getTime(),
1623
- _optionalChain([comment, 'access', _5 => _5.editedAt, 'optionalAccess', _6 => _6.getTime, 'call', _7 => _7()]) || comment.createdAt.getTime()
1484
+ _optionalChain([comment, 'access', _7 => _7.editedAt, 'optionalAccess', _8 => _8.getTime, 'call', _9 => _9()]) || comment.createdAt.getTime()
1624
1485
  )
1625
1486
  ),
1626
1487
  comments: updatedComments
@@ -1760,32 +1621,26 @@ function missingRoomInfoError(roomId) {
1760
1621
  `resolveRoomsInfo didn't return anything for room '${roomId}'`
1761
1622
  );
1762
1623
  }
1763
- function identity(x) {
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
- isLoading: false,
1784
- count: selectUnreadInboxNotificationsCount(result.inboxNotifications)
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
- if (state === void 0 || _optionalChain([state, 'optionalAccess', _8 => _8.isLoading])) {
1643
+ if (state === void 0 || _optionalChain([state, 'optionalAccess', _10 => _10.isLoading])) {
1789
1644
  return _nullishCoalesce(state, () => ( { isLoading: true }));
1790
1645
  }
1791
1646
  if (state.error) {
@@ -1803,7 +1658,7 @@ function selectorFor_useUser(state, userId) {
1803
1658
  };
1804
1659
  }
1805
1660
  function selectorFor_useRoomInfo(state, roomId) {
1806
- if (state === void 0 || _optionalChain([state, 'optionalAccess', _9 => _9.isLoading])) {
1661
+ if (state === void 0 || _optionalChain([state, 'optionalAccess', _11 => _11.isLoading])) {
1807
1662
  return _nullishCoalesce(state, () => ( { isLoading: true }));
1808
1663
  }
1809
1664
  if (state.error) {
@@ -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, identity, _core.shallow),
1747
+ useInboxNotifications: () => useInboxNotifications_withClient(client, identity2, _core.shallow),
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
- _react.useEffect.call(void 0, () => {
1919
- void store.waitUntilNotificationsLoaded();
1920
- });
1773
+ _react.useEffect.call(void 0,
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
  _react.useEffect.call(void 0, () => {
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 useSyncExternalStoreWithSelector(
1929
- store.subscribe1_notifications,
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.waitUntilNotificationsLoaded());
1939
- const result = useInboxNotifications_withClient(client, identity, _core.shallow);
1799
+ use(store.outputs.loadingNotifications.waitUntilLoaded());
1800
+ const result = useInboxNotifications_withClient(client, identity2, _core.shallow);
1940
1801
  _core.assert.call(void 0, !result.error, "Did not expect error");
1941
1802
  _core.assert.call(void 0, !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.waitUntilNotificationsLoaded());
1814
+ use(store.outputs.loadingNotifications.waitUntilLoaded());
1954
1815
  const result = useUnreadInboxNotificationsCount_withClient(client);
1955
1816
  _core.assert.call(void 0, !result.isLoading, "Did not expect loading");
1956
1817
  _core.assert.call(void 0, !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
- const getter = store.get1_both;
2046
- const selector = _react.useCallback.call(void 0,
2047
- (state) => {
2048
- const inboxNotification = _nullishCoalesce(state.notificationsById[inboxNotificationId], () => ( _core.raise.call(void 0, `Inbox notification with ID "${inboxNotificationId}" not found`)));
2049
- if (inboxNotification.kind !== "thread") {
2050
- _core.raise.call(void 0,
2051
- `Inbox notification with ID "${inboxNotificationId}" is not of kind "thread"`
2052
- );
2053
- }
2054
- const thread = _nullishCoalesce(state.threadsDB.get(inboxNotification.threadId), () => ( _core.raise.call(void 0,
2055
- `Thread with ID "${inboxNotification.threadId}" not found, this inbox notification might not be of kind "thread"`
2056
- )));
2057
- return thread;
2058
- },
2059
- [inboxNotificationId]
2060
- );
2061
- return useSyncExternalStoreWithSelector(
2062
- store.subscribe1_both,
2063
- // Re-evaluate if we need to update any time the notification changes over time
2064
- getter,
2065
- getter,
2066
- selector
1906
+ return useSignal(
1907
+ store.outputs.threadifications,
1908
+ _react.useCallback.call(void 0,
1909
+ (state) => {
1910
+ const inboxNotification = _nullishCoalesce(state.notificationsById[inboxNotificationId], () => ( _core.raise.call(void 0,
1911
+ `Inbox notification with ID "${inboxNotificationId}" not found`
1912
+ )));
1913
+ if (inboxNotification.kind !== "thread") {
1914
+ _core.raise.call(void 0,
1915
+ `Inbox notification with ID "${inboxNotificationId}" is not of kind "thread"`
1916
+ );
1917
+ }
1918
+ const thread = _nullishCoalesce(state.threadsDB.get(inboxNotification.threadId), () => ( _core.raise.call(void 0,
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[_core.kInternal].usersStore;
2071
1929
  const getUserState = _react.useCallback.call(void 0,
2072
- () => usersStore.getState(userId),
1930
+ () => usersStore.getItemState(userId),
2073
1931
  [usersStore, userId]
2074
1932
  );
2075
1933
  const selector = _react.useCallback.call(void 0,
@@ -2083,20 +1941,29 @@ function useUser_withClient(client, userId) {
2083
1941
  selector,
2084
1942
  _core.shallow
2085
1943
  );
2086
- _react.useEffect.call(void 0, () => {
2087
- void usersStore.get(userId);
2088
- }, [usersStore, userId, result]);
1944
+ _react.useEffect.call(void 0,
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[_core.kInternal].usersStore;
2093
1960
  const getUserState = _react.useCallback.call(void 0,
2094
- () => usersStore.getState(userId),
1961
+ () => usersStore.getItemState(userId),
2095
1962
  [usersStore, userId]
2096
1963
  );
2097
1964
  const userState = getUserState();
2098
1965
  if (!userState || userState.isLoading) {
2099
- throw usersStore.get(userId);
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[_core.kInternal].roomsInfoStore;
2123
1990
  const getRoomInfoState = _react.useCallback.call(void 0,
2124
- () => roomsInfoStore.getState(roomId),
1991
+ () => roomsInfoStore.getItemState(roomId),
2125
1992
  [roomsInfoStore, roomId]
2126
1993
  );
2127
1994
  const selector = _react.useCallback.call(void 0,
@@ -2135,20 +2002,29 @@ function useRoomInfo_withClient(client, roomId) {
2135
2002
  selector,
2136
2003
  _core.shallow
2137
2004
  );
2138
- _react.useEffect.call(void 0, () => {
2139
- void roomsInfoStore.get(roomId);
2140
- }, [roomsInfoStore, roomId, result]);
2005
+ _react.useEffect.call(void 0,
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[_core.kInternal].roomsInfoStore;
2145
2021
  const getRoomInfoState = _react.useCallback.call(void 0,
2146
- () => roomsInfoStore.getState(roomId),
2022
+ () => roomsInfoStore.getItemState(roomId),
2147
2023
  [roomsInfoStore, roomId]
2148
2024
  );
2149
2025
  const roomInfoState = getRoomInfoState();
2150
2026
  if (!roomInfoState || roomInfoState.isLoading) {
2151
- throw roomsInfoStore.get(roomId);
2027
+ throw roomsInfoStore.enqueue(roomId);
2152
2028
  }
2153
2029
  if (roomInfoState.error) {
2154
2030
  throw roomInfoState.error;
@@ -2195,7 +2071,7 @@ function createSharedContext(client) {
2195
2071
  }
2196
2072
  function useEnsureNoLiveblocksProvider(options) {
2197
2073
  const existing = useClientOrNull();
2198
- if (!_optionalChain([options, 'optionalAccess', _10 => _10.allowNesting]) && existing !== null) {
2074
+ if (!_optionalChain([options, 'optionalAccess', _12 => _12.allowNesting]) && existing !== null) {
2199
2075
  throw new Error(
2200
2076
  "You cannot nest multiple LiveblocksProvider instances in the same React tree."
2201
2077
  );
@@ -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
  _react.useEffect.call(void 0,
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
- const getter = _react.useCallback.call(void 0,
2274
- () => store.getUserThreadsLoadingState(options.query),
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
- use(store.waitUntilUserThreadsLoaded(options.query));
2159
+ const queryKey = makeUserThreadsQueryKey(options.query);
2160
+ use(store.outputs.loadingUserThreads.getOrCreate(queryKey).waitUntilLoaded());
2294
2161
  const result = useUserThreads_experimental(options);
2295
2162
  _core.assert.call(void 0, !result.error, "Did not expect error");
2296
2163
  _core.assert.call(void 0, !result.isLoading, "Did not expect loading");
2297
2164
  return result;
2298
2165
  }
2299
2166
  function useInboxNotifications() {
2300
- return useInboxNotifications_withClient(useClient(), identity, _core.shallow);
2167
+ return useInboxNotifications_withClient(useClient(), identity2, _core.shallow);
2301
2168
  }
2302
2169
  function useInboxNotificationsSuspense() {
2303
2170
  return useInboxNotificationsSuspense_withClient(useClient());
@@ -2346,7 +2213,7 @@ var _useUserSuspense = useUserSuspense;
2346
2213
  var _useUserThreads_experimental = useUserThreads_experimental;
2347
2214
  var _useUserThreadsSuspense_experimental = useUserThreadsSuspense_experimental;
2348
2215
  function useSyncStatus_withClient(client, options) {
2349
- const smooth = useInitial(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _11 => _11.smooth]), () => ( false)));
2216
+ const smooth = useInitial(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _13 => _13.smooth]), () => ( false)));
2350
2217
  if (smooth) {
2351
2218
  return useSyncStatusSmooth_withClient(client);
2352
2219
  } else {
@@ -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
- _nullishCoalesce(selector, () => ( identity2)),
2495
- isEqual
2496
- );
2497
- }
2498
-
2499
2354
  // src/room.tsx
2500
2355
  var _client = require('@liveblocks/client');
2501
2356
 
@@ -2518,6 +2373,7 @@ var _client = require('@liveblocks/client');
2518
2373
 
2519
2374
 
2520
2375
 
2376
+
2521
2377
 
2522
2378
 
2523
2379
  // src/use-scroll-to-comment-on-load-effect.ts
@@ -2602,7 +2458,7 @@ function getCurrentUserId(client) {
2602
2458
  }
2603
2459
  function handleApiError(err) {
2604
2460
  const message = `Request failed with status ${err.status}: ${err.message}`;
2605
- if (_optionalChain([err, 'access', _12 => _12.details, 'optionalAccess', _13 => _13.error]) === "FORBIDDEN") {
2461
+ if (_optionalChain([err, 'access', _14 => _14.details, 'optionalAccess', _15 => _15.error]) === "FORBIDDEN") {
2606
2462
  const detailedMessage = [message, err.details.suggestion, err.details.docs].filter(Boolean).join("\n");
2607
2463
  _core.console.error(detailedMessage);
2608
2464
  }
@@ -2642,73 +2498,59 @@ function makeRoomExtrasForClient(client) {
2642
2498
  }
2643
2499
  throw innerError;
2644
2500
  }
2645
- const threadsPollersByRoomId = /* @__PURE__ */ new Map();
2646
- const versionsPollersByRoomId = /* @__PURE__ */ new Map();
2647
- const roomNotificationSettingsPollersByRoomId = /* @__PURE__ */ new Map();
2648
- function getOrCreateThreadsPollerForRoomId(roomId) {
2649
- let poller = threadsPollersByRoomId.get(roomId);
2650
- if (!poller) {
2651
- poller = _core.makePoller.call(void 0,
2652
- async (signal) => {
2653
- try {
2654
- return await store.fetchRoomThreadsDeltaUpdate(roomId, signal);
2655
- } catch (err) {
2656
- _core.console.warn(`Polling new threads for '${roomId}' failed: ${String(err)}`);
2657
- throw err;
2658
- }
2659
- },
2660
- config.ROOM_THREADS_POLL_INTERVAL,
2661
- { maxStaleTimeMs: config.ROOM_THREADS_MAX_STALE_TIME }
2662
- );
2663
- threadsPollersByRoomId.set(roomId, poller);
2664
- }
2665
- return poller;
2666
- }
2667
- function getOrCreateVersionsPollerForRoomId(roomId) {
2668
- let poller = versionsPollersByRoomId.get(roomId);
2669
- if (!poller) {
2670
- poller = _core.makePoller.call(void 0,
2671
- async (signal) => {
2672
- try {
2673
- return await store.fetchRoomVersionsDeltaUpdate(roomId, signal);
2674
- } catch (err) {
2675
- _core.console.warn(`Polling new history versions for '${roomId}' failed: ${String(err)}`);
2676
- throw err;
2677
- }
2678
- },
2679
- config.HISTORY_VERSIONS_POLL_INTERVAL,
2680
- { maxStaleTimeMs: config.HISTORY_VERSIONS_MAX_STALE_TIME }
2681
- );
2682
- versionsPollersByRoomId.set(roomId, poller);
2683
- }
2684
- return poller;
2685
- }
2686
- function getOrCreateNotificationsSettingsPollerForRoomId(roomId) {
2687
- let poller = roomNotificationSettingsPollersByRoomId.get(roomId);
2688
- if (!poller) {
2689
- poller = _core.makePoller.call(void 0,
2690
- async (signal) => {
2691
- try {
2692
- return await store.refreshRoomNotificationSettings(roomId, signal);
2693
- } catch (err) {
2694
- _core.console.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 (0, _core.DefaultMap)(
2502
+ (roomId) => _core.makePoller.call(void 0,
2503
+ async (signal) => {
2504
+ try {
2505
+ return await store.fetchRoomThreadsDeltaUpdate(roomId, signal);
2506
+ } catch (err) {
2507
+ _core.console.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 (0, _core.DefaultMap)(
2516
+ (roomId) => _core.makePoller.call(void 0,
2517
+ async (signal) => {
2518
+ try {
2519
+ return await store.fetchRoomVersionsDeltaUpdate(roomId, signal);
2520
+ } catch (err) {
2521
+ _core.console.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 (0, _core.DefaultMap)(
2530
+ (roomId) => _core.makePoller.call(void 0,
2531
+ async (signal) => {
2532
+ try {
2533
+ return await store.refreshRoomNotificationSettings(roomId, signal);
2534
+ } catch (err) {
2535
+ _core.console.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
- getOrCreateVersionsPollerForRoomId,
2711
- getOrCreateNotificationsSettingsPollerForRoomId
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.get1_threads().threadsDB.getEvenIfDeleted(message.threadId);
2732
+ const existingThread = store.outputs.threads.get().getEvenIfDeleted(message.threadId);
2891
2733
  switch (message.type) {
2892
2734
  case _core.ServerMsgCode.COMMENT_EDITED:
2893
2735
  case _core.ServerMsgCode.THREAD_METADATA_UPDATED:
@@ -3005,7 +2847,7 @@ function useMentionSuggestionsCache() {
3005
2847
  return client[_core.kInternal].mentionSuggestionsCache;
3006
2848
  }
3007
2849
  function useStorageStatus(options) {
3008
- const smooth = useInitial(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _14 => _14.smooth]), () => ( false)));
2850
+ const smooth = useInitial(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _16 => _16.smooth]), () => ( false)));
3009
2851
  if (smooth) {
3010
2852
  return useStorageStatusSmooth();
3011
2853
  } else {
@@ -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
  _react.useEffect.call(void 0,
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 getter = _react.useCallback.call(void 0,
3288
- () => store.getRoomThreadsLoadingState(room.id, options.query),
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, state);
3300
- return state;
3129
+ useScrollToCommentOnLoadEffect(scrollOnLoad, result);
3130
+ return result;
3301
3131
  }
3302
3132
  function useCommentsErrorListener(callback) {
3303
3133
  const client = useClient();
@@ -3347,7 +3177,7 @@ function useCreateRoomThread(roomId) {
3347
3177
  thread: newThread,
3348
3178
  roomId
3349
3179
  });
3350
- const attachmentIds = _optionalChain([attachments, 'optionalAccess', _15 => _15.map, 'call', _16 => _16((attachment) => attachment.id)]);
3180
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _17 => _17.map, 'call', _18 => _18((attachment) => attachment.id)]);
3351
3181
  client[_core.kInternal].httpClient.createThread({
3352
3182
  roomId,
3353
3183
  threadId,
@@ -3385,8 +3215,8 @@ function useDeleteRoomThread(roomId) {
3385
3215
  (threadId) => {
3386
3216
  const { store, onMutationFailure } = getRoomExtrasForClient(client);
3387
3217
  const userId = getCurrentUserId(client);
3388
- const existing = store.get1_threads().threadsDB.get(threadId);
3389
- if (_optionalChain([existing, 'optionalAccess', _17 => _17.comments, 'optionalAccess', _18 => _18[0], 'optionalAccess', _19 => _19.userId]) !== userId) {
3218
+ const existing = store.outputs.threads.get().get(threadId);
3219
+ if (_optionalChain([existing, 'optionalAccess', _19 => _19.comments, 'optionalAccess', _20 => _20[0], 'optionalAccess', _21 => _21.userId]) !== userId) {
3390
3220
  throw new Error("Only the thread creator can delete the thread");
3391
3221
  }
3392
3222
  const optimisticId = store.optimisticUpdates.add({
@@ -3473,7 +3303,7 @@ function useCreateRoomComment(roomId) {
3473
3303
  type: "create-comment",
3474
3304
  comment
3475
3305
  });
3476
- const attachmentIds = _optionalChain([attachments, 'optionalAccess', _20 => _20.map, 'call', _21 => _21((attachment) => attachment.id)]);
3306
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _22 => _22.map, 'call', _23 => _23((attachment) => attachment.id)]);
3477
3307
  client[_core.kInternal].httpClient.createComment({ roomId, threadId, commentId, body, attachmentIds }).then(
3478
3308
  (newComment) => {
3479
3309
  store.createComment(newComment, optimisticId);
@@ -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.get1_threads().threadsDB.getEvenIfDeleted(threadId);
3336
+ const existing = store.outputs.threads.get().getEvenIfDeleted(threadId);
3507
3337
  if (existing === void 0) {
3508
3338
  _core.console.warn(
3509
3339
  `Internal unexpected behavior. Cannot edit comment in thread "${threadId}" because the thread does not exist in the cache.`
@@ -3528,7 +3358,7 @@ function useEditRoomComment(roomId) {
3528
3358
  attachments: _nullishCoalesce(attachments, () => ( []))
3529
3359
  }
3530
3360
  });
3531
- const attachmentIds = _optionalChain([attachments, 'optionalAccess', _22 => _22.map, 'call', _23 => _23((attachment) => attachment.id)]);
3361
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _24 => _24.map, 'call', _25 => _25((attachment) => attachment.id)]);
3532
3362
  client[_core.kInternal].httpClient.editComment({ roomId, threadId, commentId, body, attachmentIds }).then(
3533
3363
  (editedComment) => {
3534
3364
  store.editComment(threadId, optimisticId, editedComment);
@@ -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.get1_notifications().notificationsById
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
  _react.useEffect.call(void 0,
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 getter = _react.useCallback.call(void 0,
3841
- () => store.getNotificationSettingsLoadingState(room.id),
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 _react.useMemo.call(void 0, () => {
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.waitUntilRoomNotificationSettingsLoaded(room.id));
3679
+ use(store.outputs.settingsByRoomId.getOrCreate(room.id).waitUntilLoaded());
3860
3680
  const [settings, updateRoomNotificationSettings] = useRoomNotificationSettings();
3861
3681
  _core.assert.call(void 0, !settings.error, "Did not expect error");
3862
3682
  _core.assert.call(void 0, !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 = _react.useCallback.call(void 0,
3907
- () => store.getRoomVersionsLoadingState(room.id),
3908
- [store, room.id]
3909
- );
3910
3726
  _react.useEffect.call(void 0,
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
- const state = useSyncExternalStoreWithSelector(
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.waitUntilRoomVersionsLoaded(room.id));
3743
+ use(store.outputs.versionsByRoomId.getOrCreate(room.id).waitUntilLoaded());
3937
3744
  const result = useHistoryVersions();
3938
3745
  _core.assert.call(void 0, !result.error, "Did not expect error");
3939
3746
  _core.assert.call(void 0, !result.isLoading, "Did not expect loading");
@@ -4020,20 +3827,19 @@ 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
- use(store.waitUntilRoomThreadsLoaded(room.id, options.query));
3834
+ const queryKey = makeRoomThreadsQueryKey(room.id, options.query);
3835
+ use(store.outputs.loadingRoomThreads.getOrCreate(queryKey).waitUntilLoaded());
4030
3836
  const result = useThreads(options);
4031
3837
  _core.assert.call(void 0, !result.error, "Did not expect error");
4032
3838
  _core.assert.call(void 0, !result.isLoading, "Did not expect loading");
4033
3839
  return result;
4034
3840
  }
4035
3841
  function selectorFor_useAttachmentUrl(state) {
4036
- if (state === void 0 || _optionalChain([state, 'optionalAccess', _24 => _24.isLoading])) {
3842
+ if (state === void 0 || _optionalChain([state, 'optionalAccess', _26 => _26.isLoading])) {
4037
3843
  return _nullishCoalesce(state, () => ( { isLoading: true }));
4038
3844
  }
4039
3845
  if (state.error) {
@@ -4053,11 +3859,11 @@ function useRoomAttachmentUrl(attachmentId, roomId) {
4053
3859
  const client = useClient();
4054
3860
  const store = client[_core.kInternal].httpClient.getOrCreateAttachmentUrlsStore(roomId);
4055
3861
  const getAttachmentUrlState = _react.useCallback.call(void 0,
4056
- () => store.getState(attachmentId),
3862
+ () => store.getItemState(attachmentId),
4057
3863
  [store, attachmentId]
4058
3864
  );
4059
3865
  _react.useEffect.call(void 0, () => {
4060
- void store.get(attachmentId);
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[_core.kInternal];
4073
3879
  const getAttachmentUrlState = _react.useCallback.call(void 0,
4074
- () => attachmentUrlsStore.getState(attachmentId),
3880
+ () => attachmentUrlsStore.getItemState(attachmentId),
4075
3881
  [attachmentUrlsStore, attachmentId]
4076
3882
  );
4077
3883
  const attachmentUrlState = getAttachmentUrlState();
4078
3884
  if (!attachmentUrlState || attachmentUrlState.isLoading) {
4079
- throw attachmentUrlsStore.get(attachmentId);
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) => _nullishCoalesce(hints[roomId], () => ( /* @__PURE__ */ new Set()))
3910
+ (hints) => _nullishCoalesce(hints.get(roomId), () => ( NO_PERMISSIONS))
4104
3911
  );
4105
3912
  }
4106
3913
  function createRoomContext(client) {
@@ -4249,5 +4056,5 @@ var _useUpdateMyPresence = useUpdateMyPresence;
4249
4056
 
4250
4057
 
4251
4058
 
4252
- exports.RoomContext = RoomContext; exports.useRoomOrNull = useRoomOrNull; exports.useSyncExternalStoreWithSelector = useSyncExternalStoreWithSelector; exports.ClientContext = ClientContext; exports.getUmbrellaStoreForClient = getUmbrellaStoreForClient; exports.useClientOrNull = useClientOrNull; exports.useClient = useClient; exports.LiveblocksProvider = LiveblocksProvider; exports.createLiveblocksContext = createLiveblocksContext; exports.useInboxNotifications = useInboxNotifications; exports.useInboxNotificationsSuspense = useInboxNotificationsSuspense; exports.useMarkAllInboxNotificationsAsRead = useMarkAllInboxNotificationsAsRead; exports.useMarkInboxNotificationAsRead = useMarkInboxNotificationAsRead; exports.useDeleteAllInboxNotifications = useDeleteAllInboxNotifications; exports.useDeleteInboxNotification = useDeleteInboxNotification; exports.useUnreadInboxNotificationsCount = useUnreadInboxNotificationsCount; exports.useUnreadInboxNotificationsCountSuspense = useUnreadInboxNotificationsCountSuspense; exports.useRoomInfo = useRoomInfo; exports.useRoomInfoSuspense = useRoomInfoSuspense; exports._useInboxNotificationThread = _useInboxNotificationThread; exports._useUser = _useUser; exports._useUserSuspense = _useUserSuspense; exports._useUserThreads_experimental = _useUserThreads_experimental; exports._useUserThreadsSuspense_experimental = _useUserThreadsSuspense_experimental; exports.useSyncStatus = useSyncStatus; exports.CreateThreadError = CreateThreadError; exports.useSignal = useSignal; exports.useStatus = useStatus; exports.useReportTextEditor = useReportTextEditor; exports.useYjsProvider = useYjsProvider; exports.useCreateTextMention = useCreateTextMention; exports.useDeleteTextMention = useDeleteTextMention; exports.useResolveMentionSuggestions = useResolveMentionSuggestions; exports.useMentionSuggestionsCache = useMentionSuggestionsCache; exports.useStorageStatus = useStorageStatus; exports.useBatch = useBatch; exports.useLostConnectionListener = useLostConnectionListener; exports.useErrorListener = useErrorListener; exports.useHistory = useHistory; exports.useUndo = useUndo; exports.useRedo = useRedo; exports.useCanUndo = useCanUndo; exports.useCanRedo = useCanRedo; exports.useOthersConnectionIds = useOthersConnectionIds; exports.useCommentsErrorListener = useCommentsErrorListener; exports.useCreateRoomThread = useCreateRoomThread; exports.useDeleteRoomThread = useDeleteRoomThread; exports.useEditRoomThreadMetadata = useEditRoomThreadMetadata; exports.useCreateComment = useCreateComment; exports.useCreateRoomComment = useCreateRoomComment; exports.useEditComment = useEditComment; exports.useEditRoomComment = useEditRoomComment; exports.useDeleteComment = useDeleteComment; exports.useDeleteRoomComment = useDeleteRoomComment; exports.useAddRoomCommentReaction = useAddRoomCommentReaction; exports.useRemoveReaction = useRemoveReaction; exports.useRemoveRoomCommentReaction = useRemoveRoomCommentReaction; exports.useMarkThreadAsRead = useMarkThreadAsRead; exports.useMarkRoomThreadAsRead = useMarkRoomThreadAsRead; exports.useMarkThreadAsResolved = useMarkThreadAsResolved; exports.useMarkRoomThreadAsResolved = useMarkRoomThreadAsResolved; exports.useMarkThreadAsUnresolved = useMarkThreadAsUnresolved; exports.useMarkRoomThreadAsUnresolved = useMarkRoomThreadAsUnresolved; exports.useThreadSubscription = useThreadSubscription; exports.useHistoryVersionData = useHistoryVersionData; exports.useUpdateRoomNotificationSettings = useUpdateRoomNotificationSettings; exports.useOthersConnectionIdsSuspense = useOthersConnectionIdsSuspense; exports.useStorageStatusSuspense = useStorageStatusSuspense; exports.useAttachmentUrl = useAttachmentUrl; exports.useRoomAttachmentUrl = useRoomAttachmentUrl; exports.useAttachmentUrlSuspense = useAttachmentUrlSuspense; exports.useRoomPermissions = useRoomPermissions; exports.createRoomContext = createRoomContext; exports._RoomProvider = _RoomProvider; exports._useBroadcastEvent = _useBroadcastEvent; exports._useOthersListener = _useOthersListener; exports._useRoom = _useRoom; exports._useIsInsideRoom = _useIsInsideRoom; exports._useAddReaction = _useAddReaction; exports._useMutation = _useMutation; exports._useCreateThread = _useCreateThread; exports._useDeleteThread = _useDeleteThread; exports._useEditThreadMetadata = _useEditThreadMetadata; exports._useEventListener = _useEventListener; exports._useMyPresence = _useMyPresence; exports._useOthersMapped = _useOthersMapped; exports._useOthersMappedSuspense = _useOthersMappedSuspense; exports._useThreads = _useThreads; exports._useThreadsSuspense = _useThreadsSuspense; exports._useRoomNotificationSettings = _useRoomNotificationSettings; exports._useRoomNotificationSettingsSuspense = _useRoomNotificationSettingsSuspense; exports._useHistoryVersions = _useHistoryVersions; exports._useHistoryVersionsSuspense = _useHistoryVersionsSuspense; exports._useOther = _useOther; exports._useOthers = _useOthers; exports._useOtherSuspense = _useOtherSuspense; exports._useOthersSuspense = _useOthersSuspense; exports._useStorage = _useStorage; exports._useStorageSuspense = _useStorageSuspense; exports._useSelf = _useSelf; exports._useSelfSuspense = _useSelfSuspense; exports._useStorageRoot = _useStorageRoot; exports._useUpdateMyPresence = _useUpdateMyPresence;
4253
- //# sourceMappingURL=chunk-NUDMG62P.js.map
4059
+ exports.RoomContext = RoomContext; exports.useRoomOrNull = useRoomOrNull; exports.useSyncExternalStoreWithSelector = useSyncExternalStoreWithSelector; exports.useSignal = useSignal; exports.ClientContext = ClientContext; exports.getUmbrellaStoreForClient = getUmbrellaStoreForClient; exports.useClientOrNull = useClientOrNull; exports.useClient = useClient; exports.LiveblocksProvider = LiveblocksProvider; exports.createLiveblocksContext = createLiveblocksContext; exports.useInboxNotifications = useInboxNotifications; exports.useInboxNotificationsSuspense = useInboxNotificationsSuspense; exports.useMarkAllInboxNotificationsAsRead = useMarkAllInboxNotificationsAsRead; exports.useMarkInboxNotificationAsRead = useMarkInboxNotificationAsRead; exports.useDeleteAllInboxNotifications = useDeleteAllInboxNotifications; exports.useDeleteInboxNotification = useDeleteInboxNotification; exports.useUnreadInboxNotificationsCount = useUnreadInboxNotificationsCount; exports.useUnreadInboxNotificationsCountSuspense = useUnreadInboxNotificationsCountSuspense; exports.useRoomInfo = useRoomInfo; exports.useRoomInfoSuspense = useRoomInfoSuspense; exports._useInboxNotificationThread = _useInboxNotificationThread; exports._useUser = _useUser; exports._useUserSuspense = _useUserSuspense; exports._useUserThreads_experimental = _useUserThreads_experimental; exports._useUserThreadsSuspense_experimental = _useUserThreadsSuspense_experimental; exports.useSyncStatus = useSyncStatus; exports.CreateThreadError = CreateThreadError; exports.useStatus = useStatus; exports.useReportTextEditor = useReportTextEditor; exports.useYjsProvider = useYjsProvider; exports.useCreateTextMention = useCreateTextMention; exports.useDeleteTextMention = useDeleteTextMention; exports.useResolveMentionSuggestions = useResolveMentionSuggestions; exports.useMentionSuggestionsCache = useMentionSuggestionsCache; exports.useStorageStatus = useStorageStatus; exports.useBatch = useBatch; exports.useLostConnectionListener = useLostConnectionListener; exports.useErrorListener = useErrorListener; exports.useHistory = useHistory; exports.useUndo = useUndo; exports.useRedo = useRedo; exports.useCanUndo = useCanUndo; exports.useCanRedo = useCanRedo; exports.useOthersConnectionIds = useOthersConnectionIds; exports.useCommentsErrorListener = useCommentsErrorListener; exports.useCreateRoomThread = useCreateRoomThread; exports.useDeleteRoomThread = useDeleteRoomThread; exports.useEditRoomThreadMetadata = useEditRoomThreadMetadata; exports.useCreateComment = useCreateComment; exports.useCreateRoomComment = useCreateRoomComment; exports.useEditComment = useEditComment; exports.useEditRoomComment = useEditRoomComment; exports.useDeleteComment = useDeleteComment; exports.useDeleteRoomComment = useDeleteRoomComment; exports.useAddRoomCommentReaction = useAddRoomCommentReaction; exports.useRemoveReaction = useRemoveReaction; exports.useRemoveRoomCommentReaction = useRemoveRoomCommentReaction; exports.useMarkThreadAsRead = useMarkThreadAsRead; exports.useMarkRoomThreadAsRead = useMarkRoomThreadAsRead; exports.useMarkThreadAsResolved = useMarkThreadAsResolved; exports.useMarkRoomThreadAsResolved = useMarkRoomThreadAsResolved; exports.useMarkThreadAsUnresolved = useMarkThreadAsUnresolved; exports.useMarkRoomThreadAsUnresolved = useMarkRoomThreadAsUnresolved; exports.useThreadSubscription = useThreadSubscription; exports.useHistoryVersionData = useHistoryVersionData; exports.useUpdateRoomNotificationSettings = useUpdateRoomNotificationSettings; exports.useOthersConnectionIdsSuspense = useOthersConnectionIdsSuspense; exports.useStorageStatusSuspense = useStorageStatusSuspense; exports.useAttachmentUrl = useAttachmentUrl; exports.useRoomAttachmentUrl = useRoomAttachmentUrl; exports.useAttachmentUrlSuspense = useAttachmentUrlSuspense; exports.useRoomPermissions = useRoomPermissions; exports.createRoomContext = createRoomContext; exports._RoomProvider = _RoomProvider; exports._useBroadcastEvent = _useBroadcastEvent; exports._useOthersListener = _useOthersListener; exports._useRoom = _useRoom; exports._useIsInsideRoom = _useIsInsideRoom; exports._useAddReaction = _useAddReaction; exports._useMutation = _useMutation; exports._useCreateThread = _useCreateThread; exports._useDeleteThread = _useDeleteThread; exports._useEditThreadMetadata = _useEditThreadMetadata; exports._useEventListener = _useEventListener; exports._useMyPresence = _useMyPresence; exports._useOthersMapped = _useOthersMapped; exports._useOthersMappedSuspense = _useOthersMappedSuspense; exports._useThreads = _useThreads; exports._useThreadsSuspense = _useThreadsSuspense; exports._useRoomNotificationSettings = _useRoomNotificationSettings; exports._useRoomNotificationSettingsSuspense = _useRoomNotificationSettingsSuspense; exports._useHistoryVersions = _useHistoryVersions; exports._useHistoryVersionsSuspense = _useHistoryVersionsSuspense; exports._useOther = _useOther; exports._useOthers = _useOthers; exports._useOtherSuspense = _useOtherSuspense; exports._useOthersSuspense = _useOthersSuspense; exports._useStorage = _useStorage; exports._useStorageSuspense = _useStorageSuspense; exports._useSelf = _useSelf; exports._useSelfSuspense = _useSelfSuspense; exports._useStorageRoot = _useStorageRoot; exports._useUpdateMyPresence = _useUpdateMyPresence;
4060
+ //# sourceMappingURL=chunk-DEAPV4GE.js.map