@liveblocks/react 2.8.3-tiptap1 → 2.9.0-rc1

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.
@@ -1,6 +1,6 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/version.ts
2
2
  var PKG_NAME = "@liveblocks/react";
3
- var PKG_VERSION = "2.8.3-tiptap1";
3
+ var PKG_VERSION = "2.9.0-rc1";
4
4
  var PKG_FORMAT = "cjs";
5
5
 
6
6
  // src/ClientSideSuspense.tsx
@@ -24,27 +24,37 @@ function useIsInsideRoom() {
24
24
  return room !== null;
25
25
  }
26
26
 
27
- // src/liveblocks.tsx
28
-
29
-
30
-
31
-
27
+ // src/umbrella-store.ts
32
28
 
33
29
 
34
30
 
35
31
 
36
32
 
37
33
 
38
- var _core = require('@liveblocks/core');
39
34
 
40
35
 
41
36
 
42
37
 
43
38
 
44
39
 
40
+ var _core = require('@liveblocks/core');
45
41
 
46
- var _indexjs = require('use-sync-external-store/shim/index.js');
47
- var _withselectorjs = require('use-sync-external-store/shim/with-selector.js');
42
+ // src/lib/autobind.ts
43
+ function autobind(self) {
44
+ const seen = /* @__PURE__ */ new Set();
45
+ seen.add("constructor");
46
+ let obj = self.constructor.prototype;
47
+ do {
48
+ for (const key of Reflect.ownKeys(obj)) {
49
+ if (seen.has(key)) continue;
50
+ const descriptor = Reflect.getOwnPropertyDescriptor(obj, key);
51
+ if (typeof _optionalChain([descriptor, 'optionalAccess', _ => _.value]) === "function") {
52
+ seen.add(key);
53
+ self[key] = self[key].bind(self);
54
+ }
55
+ }
56
+ } while ((obj = Reflect.getPrototypeOf(obj)) && obj !== Object.prototype);
57
+ }
48
58
 
49
59
  // src/lib/compare.ts
50
60
  function byFirstCreated(a, b) {
@@ -90,131 +100,204 @@ function matchesOperator(value, op) {
90
100
  }
91
101
  }
92
102
 
93
- // src/lib/retry-error.ts
94
- var MAX_ERROR_RETRY_COUNT = 5;
95
- var ERROR_RETRY_INTERVAL = 5e3;
96
- function retryError(action, retryCount) {
97
- if (retryCount >= MAX_ERROR_RETRY_COUNT) return;
98
- const timeout = Math.pow(2, retryCount) * ERROR_RETRY_INTERVAL;
99
- setTimeout(() => {
100
- void action();
101
- }, timeout);
103
+ // src/umbrella-store.ts
104
+ var ASYNC_OK = Object.freeze({ isLoading: false, data: void 0 });
105
+ function makeRoomThreadsQueryKey(roomId, query) {
106
+ return `${roomId}-${_core.stringify.call(void 0, _nullishCoalesce(query, () => ( {})))}`;
102
107
  }
103
-
104
- // src/lib/shallow2.ts
105
-
106
- function shallow2(a, b) {
107
- if (!_core.isPlainObject.call(void 0, a) || !_core.isPlainObject.call(void 0, b)) {
108
- return _core.shallow.call(void 0, a, b);
108
+ function makeUserThreadsQueryKey(query) {
109
+ return `USER_THREADS:${_core.stringify.call(void 0, _nullishCoalesce(query, () => ( {})))}`;
110
+ }
111
+ function makeNotificationSettingsQueryKey(roomId) {
112
+ return `${roomId}:NOTIFICATION_SETTINGS`;
113
+ }
114
+ function makeVersionsQueryKey(roomId) {
115
+ return `${roomId}-VERSIONS`;
116
+ }
117
+ function selectThreads(state, options) {
118
+ let threads = state.threads;
119
+ if (options.roomId !== null) {
120
+ threads = threads.filter((thread) => thread.roomId === options.roomId);
109
121
  }
110
- const keysA = Object.keys(a);
111
- if (keysA.length !== Object.keys(b).length) {
112
- return false;
122
+ const query = options.query;
123
+ if (query) {
124
+ threads = threads.filter(makeThreadsFilter(query));
113
125
  }
114
- return keysA.every(
115
- (key) => Object.prototype.hasOwnProperty.call(b, key) && _core.shallow.call(void 0, a[key], b[key])
126
+ return threads.sort(
127
+ options.orderBy === "last-update" ? byMostRecentlyUpdated : byFirstCreated
116
128
  );
117
129
  }
118
-
119
- // src/lib/use-initial.ts
120
-
121
-
122
- // src/lib/use-latest.ts
123
-
124
- function useLatest(value) {
125
- const ref = _react.useRef.call(void 0, value);
126
- _react.useEffect.call(void 0, () => {
127
- ref.current = value;
128
- }, [value]);
129
- return ref;
130
- }
131
-
132
- // src/lib/use-initial.ts
133
- var noop = (state) => state;
134
- function useInitial(value) {
135
- return _react.useReducer.call(void 0, noop, value)[0];
136
- }
137
- function useInitialUnlessFunction(latestValue) {
138
- const frozenValue = useInitial(latestValue);
139
- if (typeof frozenValue === "function") {
140
- const ref = useLatest(latestValue);
141
- return _react.useCallback.call(void 0, (...args) => ref.current(...args), [
142
- ref
143
- ]);
144
- } else {
145
- return frozenValue;
130
+ function usify(promise) {
131
+ if ("status" in promise) {
132
+ return promise;
146
133
  }
134
+ const usable = promise;
135
+ usable.status = "pending";
136
+ usable.then(
137
+ (value) => {
138
+ usable.status = "fulfilled";
139
+ usable.value = value;
140
+ },
141
+ (err) => {
142
+ usable.status = "rejected";
143
+ usable.reason = err;
144
+ }
145
+ );
146
+ return usable;
147
147
  }
148
-
149
- // src/lib/use-polyfill.ts
150
- var use = (
151
- // React.use ||
152
- (promise) => {
153
- if (promise.status === "pending") {
154
- throw promise;
155
- } else if (promise.status === "fulfilled") {
156
- return promise.value;
157
- } else if (promise.status === "rejected") {
158
- throw promise.reason;
159
- } else {
160
- promise.status = "pending";
161
- promise.then(
162
- (v) => {
163
- promise.status = "fulfilled";
164
- promise.value = v;
165
- },
166
- (e) => {
167
- promise.status = "rejected";
168
- promise.reason = e;
169
- }
170
- );
171
- throw promise;
148
+ var noop = Promise.resolve();
149
+ var ASYNC_LOADING = Object.freeze({ isLoading: true });
150
+ var PaginatedResource = class {
151
+ constructor(fetchPage) {
152
+ this._cachedPromise = null;
153
+ this._paginationState = null;
154
+ this._fetchPage = fetchPage;
155
+ this._eventSource = _core.makeEventSource.call(void 0, );
156
+ this._pendingFetchMore = null;
157
+ this.observable = this._eventSource.observable;
158
+ autobind(this);
159
+ }
160
+ patchPaginationState(patch) {
161
+ const state = this._paginationState;
162
+ if (state === null) return;
163
+ this._paginationState = { ...state, ...patch };
164
+ this._eventSource.notify();
165
+ }
166
+ async _fetchMore() {
167
+ const state = this._paginationState;
168
+ if (!_optionalChain([state, 'optionalAccess', _2 => _2.cursor])) {
169
+ throw new Error("_fetchMore should not get called while in this state");
170
+ }
171
+ this.patchPaginationState({ isFetchingMore: true });
172
+ try {
173
+ const nextCursor = await this._fetchPage(state.cursor);
174
+ this.patchPaginationState({
175
+ cursor: nextCursor,
176
+ fetchMoreError: void 0,
177
+ isFetchingMore: false
178
+ });
179
+ } catch (err) {
180
+ this.patchPaginationState({
181
+ isFetchingMore: false,
182
+ fetchMoreError: err
183
+ });
172
184
  }
173
185
  }
174
- );
175
-
176
- // src/umbrella-store.ts
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
- var ASYNC_LOADING = Object.freeze({ isLoading: true });
186
- var ASYNC_OK = Object.freeze({ isLoading: false, data: void 0 });
187
- function makeNotificationSettingsQueryKey(roomId) {
188
- return `${roomId}:NOTIFICATION_SETTINGS`;
189
- }
190
- function makeVersionsQueryKey(roomId) {
191
- return `${roomId}-VERSIONS`;
192
- }
186
+ fetchMore() {
187
+ const state = this._paginationState;
188
+ if (_optionalChain([state, 'optionalAccess', _3 => _3.cursor]) === null) {
189
+ return noop;
190
+ }
191
+ if (!this._pendingFetchMore) {
192
+ this._pendingFetchMore = this._fetchMore().finally(() => {
193
+ this._pendingFetchMore = null;
194
+ });
195
+ }
196
+ return this._pendingFetchMore;
197
+ }
198
+ get() {
199
+ const usable = this._cachedPromise;
200
+ if (usable === null || usable.status === "pending") {
201
+ return ASYNC_LOADING;
202
+ }
203
+ if (usable.status === "rejected") {
204
+ return { isLoading: false, error: usable.reason };
205
+ }
206
+ const state = this._paginationState;
207
+ return {
208
+ isLoading: false,
209
+ data: {
210
+ fetchMore: this.fetchMore,
211
+ isFetchingMore: state.isFetchingMore,
212
+ fetchMoreError: state.fetchMoreError,
213
+ hasFetchedAll: state.cursor === null
214
+ }
215
+ };
216
+ }
217
+ waitUntilLoaded() {
218
+ if (this._cachedPromise) {
219
+ return this._cachedPromise;
220
+ }
221
+ const initialFetcher = _core.autoRetry.call(void 0,
222
+ () => this._fetchPage(
223
+ /* cursor */
224
+ void 0
225
+ ),
226
+ 5,
227
+ [5e3, 5e3, 1e4, 15e3]
228
+ );
229
+ const promise = usify(
230
+ initialFetcher.then((cursor) => {
231
+ this._paginationState = {
232
+ cursor,
233
+ isFetchingMore: false,
234
+ fetchMoreError: void 0
235
+ };
236
+ })
237
+ );
238
+ promise.then(
239
+ () => this._eventSource.notify(),
240
+ () => {
241
+ this._eventSource.notify();
242
+ setTimeout(() => {
243
+ this._cachedPromise = null;
244
+ this._eventSource.notify();
245
+ }, 5e3);
246
+ }
247
+ );
248
+ this._cachedPromise = promise;
249
+ return promise;
250
+ }
251
+ };
193
252
  var UmbrellaStore = class {
194
- constructor() {
253
+ constructor(client) {
195
254
  this._prevState = null;
196
255
  this._stateCached = null;
256
+ // Notifications
257
+ this._notificationsLastRequestedAt = null;
258
+ // Room Threads
259
+ this._roomThreadsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
260
+ this._roomThreads = /* @__PURE__ */ new Map();
261
+ // User Threads
262
+ this._userThreadsLastRequestedAt = null;
263
+ this._userThreads = /* @__PURE__ */ new Map();
264
+ const inboxFetcher = async (cursor) => {
265
+ if (client === void 0) {
266
+ throw new (0, _core.StopRetrying)(
267
+ "Client is required in order to load threads for the room"
268
+ );
269
+ }
270
+ const result = await client.getInboxNotifications({ cursor });
271
+ this.updateThreadsAndNotifications(
272
+ result.threads,
273
+ // TODO: Figure out how to remove this casting
274
+ result.inboxNotifications
275
+ );
276
+ if (this._notificationsLastRequestedAt === null) {
277
+ this._notificationsLastRequestedAt = result.requestedAt;
278
+ }
279
+ const nextCursor = result.nextCursor;
280
+ return nextCursor;
281
+ };
282
+ this._client = client;
283
+ this._notifications = new PaginatedResource(inboxFetcher);
284
+ this._notifications.observable.subscribe(
285
+ () => (
286
+ // Note that the store itself does not change, but it's only vehicle at
287
+ // the moment to trigger a re-render, so we'll do a no-op update here.
288
+ this._store.set((store) => ({ ...store }))
289
+ )
290
+ );
197
291
  this._store = _core.createStore.call(void 0, {
198
292
  rawThreadsById: {},
199
- // queries: {},
200
- query1: void 0,
201
- queries2: {},
202
293
  queries3: {},
203
294
  queries4: {},
204
295
  optimisticUpdates: [],
205
- inboxNotificationsById: {},
206
- notificationSettingsByRoomId: {},
296
+ notificationsById: {},
297
+ settingsByRoomId: {},
207
298
  versionsByRoomId: {}
208
299
  });
209
- this.getFullState = this.getFullState.bind(this);
210
- this.getInboxNotificationsAsync = this.getInboxNotificationsAsync.bind(this);
211
- this.subscribeThreads = this.subscribeThreads.bind(this);
212
- this.subscribeUserThreads = this.subscribeUserThreads.bind(this);
213
- this.subscribeThreadsOrInboxNotifications = this.subscribeThreadsOrInboxNotifications.bind(this);
214
- this.subscribeNotificationSettings = this.subscribeNotificationSettings.bind(this);
215
- this.subscribeVersions = this.subscribeVersions.bind(this);
216
- this._hasOptimisticUpdates = this._hasOptimisticUpdates.bind(this);
217
- this._subscribeOptimisticUpdates = this._subscribeOptimisticUpdates.bind(this);
300
+ autobind(this);
218
301
  }
219
302
  get() {
220
303
  const rawState = this._store.get();
@@ -231,45 +314,79 @@ var UmbrellaStore = class {
231
314
  return this.get();
232
315
  }
233
316
  /**
234
- * Returns the async result of the given queryKey. If the query is success,
235
- * then it will return the entire store's state in the payload.
317
+ * Returns the async result of the given query and room id. If the query is success,
318
+ * then it will return the threads that match that provided query and room id.
319
+ *
236
320
  */
237
- // TODO: This return type is a bit weird! Feels like we haven't found the
238
- // right abstraction here yet.
239
- getThreadsAsync(queryKey) {
240
- const internalState = this._store.get();
241
- const query = internalState.queries2[queryKey];
242
- if (query === void 0 || query.isLoading) {
321
+ // XXXX Find a better name for that doesn't associate to 'async'
322
+ getRoomThreadsAsync(roomId, query) {
323
+ const queryKey = makeRoomThreadsQueryKey(roomId, query);
324
+ const paginatedResource = this._roomThreads.get(queryKey);
325
+ if (paginatedResource === void 0) {
243
326
  return ASYNC_LOADING;
244
327
  }
245
- if (query.error) {
246
- return query;
328
+ const asyncResult = paginatedResource.get();
329
+ if (asyncResult.isLoading || asyncResult.error) {
330
+ return asyncResult;
247
331
  }
248
- return { isLoading: false, fullState: this.getFullState() };
332
+ const threads = selectThreads(this.getFullState(), {
333
+ roomId,
334
+ query,
335
+ orderBy: "age"
336
+ });
337
+ const page = asyncResult.data;
338
+ return {
339
+ isLoading: false,
340
+ threads,
341
+ hasFetchedAll: page.hasFetchedAll,
342
+ isFetchingMore: page.isFetchingMore,
343
+ fetchMoreError: page.fetchMoreError,
344
+ fetchMore: page.fetchMore
345
+ };
249
346
  }
250
- getUserThreadsAsync(queryKey) {
251
- const internalState = this._store.get();
252
- const query = internalState.queries2[queryKey];
253
- if (query === void 0 || query.isLoading) {
347
+ // XXXX - Find a better name for that doesn't associate to 'async'
348
+ getUserThreadsAsync(query) {
349
+ const queryKey = makeUserThreadsQueryKey(query);
350
+ const paginatedResource = this._userThreads.get(queryKey);
351
+ if (paginatedResource === void 0) {
254
352
  return ASYNC_LOADING;
255
353
  }
256
- if (query.error) {
257
- return query;
354
+ const asyncResult = paginatedResource.get();
355
+ if (asyncResult.isLoading || asyncResult.error) {
356
+ return asyncResult;
258
357
  }
259
- return { isLoading: false, fullState: this.getFullState() };
358
+ const threads = selectThreads(this.getFullState(), {
359
+ roomId: null,
360
+ // Do _not_ filter by roomId
361
+ query,
362
+ orderBy: "last-update"
363
+ });
364
+ const page = asyncResult.data;
365
+ return {
366
+ isLoading: false,
367
+ threads,
368
+ hasFetchedAll: page.hasFetchedAll,
369
+ isFetchingMore: page.isFetchingMore,
370
+ fetchMoreError: page.fetchMoreError,
371
+ fetchMore: page.fetchMore
372
+ };
260
373
  }
261
374
  // NOTE: This will read the async result, but WILL NOT start loading at the moment!
375
+ // XXXX - Find a better name for that doesn't associate to 'async'
262
376
  getInboxNotificationsAsync() {
263
- const internalState = this._store.get();
264
- const query = internalState.query1;
265
- if (query === void 0 || query.isLoading) {
266
- return ASYNC_LOADING;
377
+ const asyncResult = this._notifications.get();
378
+ if (asyncResult.isLoading || asyncResult.error) {
379
+ return asyncResult;
267
380
  }
268
- if (query.error !== void 0) {
269
- return query;
270
- }
271
- const inboxNotifications = this.getFullState().inboxNotifications;
272
- return { isLoading: false, inboxNotifications };
381
+ const page = asyncResult.data;
382
+ return {
383
+ isLoading: false,
384
+ inboxNotifications: this.getFullState().notifications,
385
+ hasFetchedAll: page.hasFetchedAll,
386
+ isFetchingMore: page.isFetchingMore,
387
+ fetchMoreError: page.fetchMoreError,
388
+ fetchMore: page.fetchMore
389
+ };
273
390
  }
274
391
  // NOTE: This will read the async result, but WILL NOT start loading at the moment!
275
392
  getNotificationSettingsAsync(roomId) {
@@ -283,7 +400,7 @@ var UmbrellaStore = class {
283
400
  }
284
401
  return {
285
402
  isLoading: false,
286
- settings: _core.nn.call(void 0, state.notificationSettingsByRoomId[roomId])
403
+ settings: _core.nn.call(void 0, state.settingsByRoomId[roomId])
287
404
  };
288
405
  }
289
406
  getVersionsAsync(roomId) {
@@ -339,15 +456,15 @@ var UmbrellaStore = class {
339
456
  }
340
457
  updateInboxNotificationsCache(mapFn) {
341
458
  this._store.set((state) => {
342
- const inboxNotifications = mapFn(state.inboxNotificationsById);
343
- return inboxNotifications !== state.inboxNotificationsById ? { ...state, inboxNotificationsById: inboxNotifications } : state;
459
+ const inboxNotifications = mapFn(state.notificationsById);
460
+ return inboxNotifications !== state.notificationsById ? { ...state, notificationsById: inboxNotifications } : state;
344
461
  });
345
462
  }
346
463
  setNotificationSettings(roomId, settings) {
347
464
  this._store.set((state) => ({
348
465
  ...state,
349
- notificationSettingsByRoomId: {
350
- ...state.notificationSettingsByRoomId,
466
+ settingsByRoomId: {
467
+ ...state.settingsByRoomId,
351
468
  [roomId]: settings
352
469
  }
353
470
  }));
@@ -361,21 +478,6 @@ var UmbrellaStore = class {
361
478
  }
362
479
  }));
363
480
  }
364
- setQuery1State(queryState) {
365
- this._store.set((state) => ({
366
- ...state,
367
- query1: queryState
368
- }));
369
- }
370
- setQuery2State(queryKey, queryState) {
371
- this._store.set((state) => ({
372
- ...state,
373
- queries2: {
374
- ...state.queries2,
375
- [queryKey]: queryState
376
- }
377
- }));
378
- }
379
481
  setQuery3State(queryKey, queryState) {
380
482
  this._store.set((state) => ({
381
483
  ...state,
@@ -602,7 +704,7 @@ var UmbrellaStore = class {
602
704
  }
603
705
  });
604
706
  }
605
- updateThreadsAndNotifications(threads, inboxNotifications, deletedThreads, deletedInboxNotifications) {
707
+ updateThreadsAndNotifications(threads, inboxNotifications, deletedThreads = [], deletedInboxNotifications = []) {
606
708
  this._store.batch(() => {
607
709
  this.updateThreadsCache(
608
710
  (cache) => applyThreadUpdates(cache, {
@@ -622,12 +724,14 @@ var UmbrellaStore = class {
622
724
  * Updates existing notification setting for a room with a new value,
623
725
  * replacing the corresponding optimistic update.
624
726
  */
727
+ // XXXX Rename this helper method
625
728
  updateRoomInboxNotificationSettings2(roomId, optimisticUpdateId, settings) {
626
729
  this._store.batch(() => {
627
730
  this.removeOptimisticUpdate(optimisticUpdateId);
628
731
  this.setNotificationSettings(roomId, settings);
629
732
  });
630
733
  }
734
+ // XXXX Rename this helper method
631
735
  updateRoomInboxNotificationSettings(roomId, settings, queryKey) {
632
736
  this._store.batch(() => {
633
737
  this.setQuery3OK(queryKey);
@@ -653,29 +757,6 @@ var UmbrellaStore = class {
653
757
  (cache) => cache.filter((ou) => ou.id !== optimisticUpdateId)
654
758
  );
655
759
  }
656
- //
657
- // Query State APIs
658
- //
659
- // Query 1
660
- setQuery1Loading() {
661
- this.setQuery1State(ASYNC_LOADING);
662
- }
663
- setQuery1OK() {
664
- this.setQuery1State(ASYNC_OK);
665
- }
666
- setQuery1Error(error) {
667
- this.setQuery1State({ isLoading: false, error });
668
- }
669
- // Query 2
670
- setQuery2Loading(queryKey) {
671
- this.setQuery2State(queryKey, ASYNC_LOADING);
672
- }
673
- setQuery2OK(queryKey) {
674
- this.setQuery2State(queryKey, ASYNC_OK);
675
- }
676
- setQuery2Error(queryKey, error) {
677
- this.setQuery2State(queryKey, { isLoading: false, error });
678
- }
679
760
  // Query 3
680
761
  setQuery3Loading(queryKey) {
681
762
  this.setQuery3State(queryKey, ASYNC_LOADING);
@@ -696,12 +777,162 @@ var UmbrellaStore = class {
696
777
  setQuery4Error(queryKey, error) {
697
778
  this.setQuery4State(queryKey, { isLoading: false, error });
698
779
  }
780
+ async fetchNotificationsDeltaUpdate() {
781
+ const lastRequestedAt = this._notificationsLastRequestedAt;
782
+ if (lastRequestedAt === null) {
783
+ _core.console.warn("Notifications polled before first page loaded");
784
+ return;
785
+ }
786
+ const client = _core.nn.call(void 0,
787
+ this._client,
788
+ "Client is required in order to load notifications for the room"
789
+ );
790
+ const result = await client.getInboxNotificationsSince(lastRequestedAt);
791
+ if (lastRequestedAt < result.requestedAt) {
792
+ this._notificationsLastRequestedAt = result.requestedAt;
793
+ }
794
+ this.updateThreadsAndNotifications(
795
+ result.threads.updated,
796
+ result.inboxNotifications.updated,
797
+ result.threads.deleted,
798
+ result.inboxNotifications.deleted
799
+ );
800
+ }
801
+ waitUntilNotificationsLoaded() {
802
+ return this._notifications.waitUntilLoaded();
803
+ }
804
+ waitUntilRoomThreadsLoaded(roomId, query) {
805
+ const threadsFetcher = async (cursor) => {
806
+ if (this._client === void 0) {
807
+ throw new (0, _core.StopRetrying)(
808
+ "Client is required in order to load threads for the room"
809
+ );
810
+ }
811
+ const room = this._client.getRoom(roomId);
812
+ if (room === null) {
813
+ throw new (0, _core.StopRetrying)(
814
+ `Room with id ${roomId} is not available on client`
815
+ );
816
+ }
817
+ const result = await room.getThreads({ cursor, query });
818
+ this.updateThreadsAndNotifications(
819
+ result.threads,
820
+ // TODO: Figure out how to remove this casting
821
+ result.inboxNotifications
822
+ );
823
+ const lastRequestedAt = this._roomThreadsLastRequestedAtByRoom.get(roomId);
824
+ if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
825
+ this._roomThreadsLastRequestedAtByRoom.set(roomId, result.requestedAt);
826
+ }
827
+ return result.nextCursor;
828
+ };
829
+ const queryKey = makeRoomThreadsQueryKey(roomId, query);
830
+ let paginatedResource = this._roomThreads.get(queryKey);
831
+ if (paginatedResource === void 0) {
832
+ paginatedResource = new PaginatedResource(threadsFetcher);
833
+ }
834
+ paginatedResource.observable.subscribe(
835
+ () => (
836
+ // Note that the store itself does not change, but it's only vehicle at
837
+ // the moment to trigger a re-render, so we'll do a no-op update here.
838
+ this._store.set((store) => ({ ...store }))
839
+ )
840
+ );
841
+ this._roomThreads.set(queryKey, paginatedResource);
842
+ return paginatedResource.waitUntilLoaded();
843
+ }
844
+ async fetchRoomThreadsDeltaUpdate(roomId) {
845
+ const lastRequestedAt = this._roomThreadsLastRequestedAtByRoom.get(roomId);
846
+ if (lastRequestedAt === void 0) {
847
+ _core.console.warn("Room threads polled before first page loaded");
848
+ return;
849
+ }
850
+ const client = _core.nn.call(void 0,
851
+ this._client,
852
+ "Client is required in order to load notifications for the room"
853
+ );
854
+ const room = _core.nn.call(void 0,
855
+ client.getRoom(roomId),
856
+ `Room with id ${roomId} is not available on client`
857
+ );
858
+ const updates = await room.getThreadsSince({
859
+ since: lastRequestedAt
860
+ });
861
+ this.updateThreadsAndNotifications(
862
+ updates.threads.updated,
863
+ updates.inboxNotifications.updated,
864
+ updates.threads.deleted,
865
+ updates.inboxNotifications.deleted
866
+ );
867
+ if (lastRequestedAt < updates.requestedAt) {
868
+ this._roomThreadsLastRequestedAtByRoom.set(roomId, updates.requestedAt);
869
+ }
870
+ }
871
+ waitUntilUserThreadsLoaded(query) {
872
+ const queryKey = makeUserThreadsQueryKey(query);
873
+ const threadsFetcher = async (cursor) => {
874
+ if (this._client === void 0) {
875
+ throw new (0, _core.StopRetrying)(
876
+ "Client is required in order to load threads for the room"
877
+ );
878
+ }
879
+ const result = await this._client[_core.kInternal].getUserThreads_experimental({
880
+ cursor,
881
+ query
882
+ });
883
+ this.updateThreadsAndNotifications(
884
+ result.threads,
885
+ // TODO: Figure out how to remove this casting
886
+ result.inboxNotifications
887
+ );
888
+ if (this._userThreadsLastRequestedAt === null) {
889
+ this._userThreadsLastRequestedAt = result.requestedAt;
890
+ }
891
+ return result.nextCursor;
892
+ };
893
+ let paginatedResource = this._userThreads.get(queryKey);
894
+ if (paginatedResource === void 0) {
895
+ paginatedResource = new PaginatedResource(threadsFetcher);
896
+ }
897
+ paginatedResource.observable.subscribe(
898
+ () => (
899
+ // Note that the store itself does not change, but it's only vehicle at
900
+ // the moment to trigger a re-render, so we'll do a no-op update here.
901
+ this._store.set((store) => ({ ...store }))
902
+ )
903
+ );
904
+ this._userThreads.set(queryKey, paginatedResource);
905
+ return paginatedResource.waitUntilLoaded();
906
+ }
907
+ async fetchUserThreadsDeltaUpdate() {
908
+ const lastRequestedAt = this._userThreadsLastRequestedAt;
909
+ if (lastRequestedAt === null) {
910
+ _core.console.warn("User threads polled before first page loaded");
911
+ return;
912
+ }
913
+ const client = _core.nn.call(void 0,
914
+ this._client,
915
+ "Client is required in order to load threads for the user"
916
+ );
917
+ const result = await client[_core.kInternal].getUserThreadsSince_experimental({
918
+ since: lastRequestedAt
919
+ });
920
+ if (lastRequestedAt < result.requestedAt) {
921
+ this._notificationsLastRequestedAt = result.requestedAt;
922
+ }
923
+ this.updateThreadsAndNotifications(
924
+ result.threads.updated,
925
+ result.inboxNotifications.updated,
926
+ result.threads.deleted,
927
+ result.inboxNotifications.deleted
928
+ );
929
+ }
699
930
  };
700
931
  function internalToExternalState(state) {
701
932
  const computed = {
702
933
  threadsById: { ...state.rawThreadsById },
703
- inboxNotificationsById: { ...state.inboxNotificationsById },
704
- notificationSettingsByRoomId: { ...state.notificationSettingsByRoomId }
934
+ notificationsById: { ...state.notificationsById },
935
+ settingsByRoomId: { ...state.settingsByRoomId }
705
936
  };
706
937
  for (const optimisticUpdate of state.optimisticUpdates) {
707
938
  switch (optimisticUpdate.type) {
@@ -768,14 +999,14 @@ function internalToExternalState(state) {
768
999
  optimisticUpdate.comment
769
1000
  );
770
1001
  const inboxNotification = Object.values(
771
- computed.inboxNotificationsById
1002
+ computed.notificationsById
772
1003
  ).find(
773
1004
  (notification) => notification.kind === "thread" && notification.threadId === thread.id
774
1005
  );
775
1006
  if (inboxNotification === void 0) {
776
1007
  break;
777
1008
  }
778
- computed.inboxNotificationsById[inboxNotification.id] = {
1009
+ computed.notificationsById[inboxNotification.id] = {
779
1010
  ...inboxNotification,
780
1011
  notifiedAt: optimisticUpdate.comment.createdAt,
781
1012
  readAt: optimisticUpdate.comment.createdAt
@@ -845,20 +1076,23 @@ function internalToExternalState(state) {
845
1076
  break;
846
1077
  }
847
1078
  case "mark-inbox-notification-as-read": {
848
- const ibn = computed.inboxNotificationsById[optimisticUpdate.inboxNotificationId];
1079
+ const ibn = computed.notificationsById[optimisticUpdate.inboxNotificationId];
849
1080
  if (ibn === void 0) {
850
1081
  break;
851
1082
  }
852
- computed.inboxNotificationsById[optimisticUpdate.inboxNotificationId] = { ...ibn, readAt: optimisticUpdate.readAt };
1083
+ computed.notificationsById[optimisticUpdate.inboxNotificationId] = {
1084
+ ...ibn,
1085
+ readAt: optimisticUpdate.readAt
1086
+ };
853
1087
  break;
854
1088
  }
855
1089
  case "mark-all-inbox-notifications-as-read": {
856
- for (const id in computed.inboxNotificationsById) {
857
- const ibn = computed.inboxNotificationsById[id];
1090
+ for (const id in computed.notificationsById) {
1091
+ const ibn = computed.notificationsById[id];
858
1092
  if (ibn === void 0) {
859
1093
  break;
860
1094
  }
861
- computed.inboxNotificationsById[id] = {
1095
+ computed.notificationsById[id] = {
862
1096
  ...ibn,
863
1097
  readAt: optimisticUpdate.readAt
864
1098
  };
@@ -866,19 +1100,19 @@ function internalToExternalState(state) {
866
1100
  break;
867
1101
  }
868
1102
  case "delete-inbox-notification": {
869
- delete computed.inboxNotificationsById[optimisticUpdate.inboxNotificationId];
1103
+ delete computed.notificationsById[optimisticUpdate.inboxNotificationId];
870
1104
  break;
871
1105
  }
872
1106
  case "delete-all-inbox-notifications": {
873
- computed.inboxNotificationsById = {};
1107
+ computed.notificationsById = {};
874
1108
  break;
875
1109
  }
876
1110
  case "update-notification-settings": {
877
- const settings = computed.notificationSettingsByRoomId[optimisticUpdate.roomId];
1111
+ const settings = computed.settingsByRoomId[optimisticUpdate.roomId];
878
1112
  if (settings === void 0) {
879
1113
  break;
880
1114
  }
881
- computed.notificationSettingsByRoomId[optimisticUpdate.roomId] = {
1115
+ computed.settingsByRoomId[optimisticUpdate.roomId] = {
882
1116
  ...settings,
883
1117
  ...optimisticUpdate.settings
884
1118
  };
@@ -896,15 +1130,14 @@ function internalToExternalState(state) {
896
1130
  );
897
1131
  const cleanedNotifications = (
898
1132
  // Sort so that the most recent notifications are first
899
- Object.values(computed.inboxNotificationsById).filter(
900
- (ibn) => ibn.kind === "thread" ? computed.threadsById[ibn.threadId] && _optionalChain([computed, 'access', _ => _.threadsById, 'access', _2 => _2[ibn.threadId], 'optionalAccess', _3 => _3.deletedAt]) === void 0 : true
1133
+ Object.values(computed.notificationsById).filter(
1134
+ (ibn) => ibn.kind === "thread" ? computed.threadsById[ibn.threadId] && _optionalChain([computed, 'access', _4 => _4.threadsById, 'access', _5 => _5[ibn.threadId], 'optionalAccess', _6 => _6.deletedAt]) === void 0 : true
901
1135
  ).sort((a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime())
902
1136
  );
903
1137
  return {
904
- inboxNotifications: cleanedNotifications,
905
- inboxNotificationsById: computed.inboxNotificationsById,
906
- notificationSettingsByRoomId: computed.notificationSettingsByRoomId,
907
- queries2: state.queries2,
1138
+ notifications: cleanedNotifications,
1139
+ notificationsById: computed.notificationsById,
1140
+ settingsByRoomId: computed.settingsByRoomId,
908
1141
  queries3: state.queries3,
909
1142
  queries4: state.queries4,
910
1143
  threads: cleanedThreads,
@@ -978,7 +1211,7 @@ function applyUpsertComment(thread, comment) {
978
1211
  );
979
1212
  if (existingComment === void 0) {
980
1213
  const updatedAt = new Date(
981
- Math.max(_optionalChain([thread, 'access', _4 => _4.updatedAt, 'optionalAccess', _5 => _5.getTime, 'call', _6 => _6()]) || 0, comment.createdAt.getTime())
1214
+ Math.max(_optionalChain([thread, 'access', _7 => _7.updatedAt, 'optionalAccess', _8 => _8.getTime, 'call', _9 => _9()]) || 0, comment.createdAt.getTime())
982
1215
  );
983
1216
  const updatedThread = {
984
1217
  ...thread,
@@ -998,8 +1231,8 @@ function applyUpsertComment(thread, comment) {
998
1231
  ...thread,
999
1232
  updatedAt: new Date(
1000
1233
  Math.max(
1001
- _optionalChain([thread, 'access', _7 => _7.updatedAt, 'optionalAccess', _8 => _8.getTime, 'call', _9 => _9()]) || 0,
1002
- _optionalChain([comment, 'access', _10 => _10.editedAt, 'optionalAccess', _11 => _11.getTime, 'call', _12 => _12()]) || comment.createdAt.getTime()
1234
+ _optionalChain([thread, 'access', _10 => _10.updatedAt, 'optionalAccess', _11 => _11.getTime, 'call', _12 => _12()]) || 0,
1235
+ _optionalChain([comment, 'access', _13 => _13.editedAt, 'optionalAccess', _14 => _14.getTime, 'call', _15 => _15()]) || comment.createdAt.getTime()
1003
1236
  )
1004
1237
  ),
1005
1238
  comments: updatedComments
@@ -1065,7 +1298,7 @@ function applyAddReaction(thread, commentId, reaction) {
1065
1298
  return {
1066
1299
  ...thread,
1067
1300
  updatedAt: new Date(
1068
- Math.max(reaction.createdAt.getTime(), _optionalChain([thread, 'access', _13 => _13.updatedAt, 'optionalAccess', _14 => _14.getTime, 'call', _15 => _15()]) || 0)
1301
+ Math.max(reaction.createdAt.getTime(), _optionalChain([thread, 'access', _16 => _16.updatedAt, 'optionalAccess', _17 => _17.getTime, 'call', _18 => _18()]) || 0)
1069
1302
  ),
1070
1303
  comments: updatedComments
1071
1304
  };
@@ -1098,7 +1331,7 @@ function applyRemoveReaction(thread, commentId, emoji, userId, removedAt) {
1098
1331
  return {
1099
1332
  ...thread,
1100
1333
  updatedAt: new Date(
1101
- Math.max(removedAt.getTime(), _optionalChain([thread, 'access', _16 => _16.updatedAt, 'optionalAccess', _17 => _17.getTime, 'call', _18 => _18()]) || 0)
1334
+ Math.max(removedAt.getTime(), _optionalChain([thread, 'access', _19 => _19.updatedAt, 'optionalAccess', _20 => _20.getTime, 'call', _21 => _21()]) || 0)
1102
1335
  ),
1103
1336
  comments: updatedComments
1104
1337
  };
@@ -1125,9 +1358,100 @@ function upsertReaction(reactions, reaction) {
1125
1358
  } : existingReaction2
1126
1359
  );
1127
1360
  }
1128
- return reactions;
1361
+ return reactions;
1362
+ }
1363
+
1364
+ // src/liveblocks.tsx
1365
+
1366
+
1367
+
1368
+
1369
+
1370
+
1371
+
1372
+
1373
+
1374
+
1375
+
1376
+
1377
+
1378
+
1379
+
1380
+ var _indexjs = require('use-sync-external-store/shim/index.js');
1381
+ var _withselectorjs = require('use-sync-external-store/shim/with-selector.js');
1382
+
1383
+ // src/lib/shallow2.ts
1384
+
1385
+ function shallow2(a, b) {
1386
+ if (!_core.isPlainObject.call(void 0, a) || !_core.isPlainObject.call(void 0, b)) {
1387
+ return _core.shallow.call(void 0, a, b);
1388
+ }
1389
+ const keysA = Object.keys(a);
1390
+ if (keysA.length !== Object.keys(b).length) {
1391
+ return false;
1392
+ }
1393
+ return keysA.every(
1394
+ (key) => Object.prototype.hasOwnProperty.call(b, key) && _core.shallow.call(void 0, a[key], b[key])
1395
+ );
1396
+ }
1397
+
1398
+ // src/lib/use-initial.ts
1399
+
1400
+
1401
+ // src/lib/use-latest.ts
1402
+
1403
+ function useLatest(value) {
1404
+ const ref = _react.useRef.call(void 0, value);
1405
+ _react.useEffect.call(void 0, () => {
1406
+ ref.current = value;
1407
+ }, [value]);
1408
+ return ref;
1409
+ }
1410
+
1411
+ // src/lib/use-initial.ts
1412
+ var noop2 = (state) => state;
1413
+ function useInitial(value) {
1414
+ return _react.useReducer.call(void 0, noop2, value)[0];
1415
+ }
1416
+ function useInitialUnlessFunction(latestValue) {
1417
+ const frozenValue = useInitial(latestValue);
1418
+ if (typeof frozenValue === "function") {
1419
+ const ref = useLatest(latestValue);
1420
+ return _react.useCallback.call(void 0, (...args) => ref.current(...args), [
1421
+ ref
1422
+ ]);
1423
+ } else {
1424
+ return frozenValue;
1425
+ }
1129
1426
  }
1130
1427
 
1428
+ // src/lib/use-polyfill.ts
1429
+ var use = (
1430
+ // React.use ||
1431
+ (promise) => {
1432
+ if (promise.status === "pending") {
1433
+ throw promise;
1434
+ } else if (promise.status === "fulfilled") {
1435
+ return promise.value;
1436
+ } else if (promise.status === "rejected") {
1437
+ throw promise.reason;
1438
+ } else {
1439
+ promise.status = "pending";
1440
+ promise.then(
1441
+ (v) => {
1442
+ promise.status = "fulfilled";
1443
+ promise.value = v;
1444
+ },
1445
+ (e) => {
1446
+ promise.status = "rejected";
1447
+ promise.reason = e;
1448
+ }
1449
+ );
1450
+ throw promise;
1451
+ }
1452
+ }
1453
+ );
1454
+
1131
1455
  // src/liveblocks.tsx
1132
1456
  var ClientContext = _react.createContext.call(void 0, null);
1133
1457
  function missingUserError(userId) {
@@ -1145,7 +1469,6 @@ var _umbrellaStores = /* @__PURE__ */ new WeakMap();
1145
1469
  var _extras = /* @__PURE__ */ new WeakMap();
1146
1470
  var _bundles = /* @__PURE__ */ new WeakMap();
1147
1471
  var POLLING_INTERVAL = 60 * 1e3;
1148
- var USER_THREADS_QUERY = "USER_THREADS";
1149
1472
  function selectUnreadInboxNotificationsCount(inboxNotifications) {
1150
1473
  let count = 0;
1151
1474
  for (const notification of inboxNotifications) {
@@ -1165,7 +1488,7 @@ function selectorFor_useUnreadInboxNotificationsCount(result) {
1165
1488
  };
1166
1489
  }
1167
1490
  function selectorFor_useUser(state, userId) {
1168
- if (state === void 0 || _optionalChain([state, 'optionalAccess', _19 => _19.isLoading])) {
1491
+ if (state === void 0 || _optionalChain([state, 'optionalAccess', _22 => _22.isLoading])) {
1169
1492
  return _nullishCoalesce(state, () => ( { isLoading: true }));
1170
1493
  }
1171
1494
  if (state.error) {
@@ -1183,7 +1506,7 @@ function selectorFor_useUser(state, userId) {
1183
1506
  };
1184
1507
  }
1185
1508
  function selectorFor_useRoomInfo(state, roomId) {
1186
- if (state === void 0 || _optionalChain([state, 'optionalAccess', _20 => _20.isLoading])) {
1509
+ if (state === void 0 || _optionalChain([state, 'optionalAccess', _23 => _23.isLoading])) {
1187
1510
  return _nullishCoalesce(state, () => ( { isLoading: true }));
1188
1511
  }
1189
1512
  if (state.error) {
@@ -1200,19 +1523,6 @@ function selectorFor_useRoomInfo(state, roomId) {
1200
1523
  info: state.data
1201
1524
  };
1202
1525
  }
1203
- function selectThreads(state, options) {
1204
- let threads = state.threads;
1205
- if (options.roomId !== null) {
1206
- threads = threads.filter((thread) => thread.roomId === options.roomId);
1207
- }
1208
- const query = options.query;
1209
- if (query) {
1210
- threads = threads.filter(makeThreadsFilter(query));
1211
- }
1212
- return threads.sort(
1213
- options.orderBy === "last-update" ? byMostRecentlyUpdated : byFirstCreated
1214
- );
1215
- }
1216
1526
  function getOrCreateContextBundle(client) {
1217
1527
  let bundle = _bundles.get(client);
1218
1528
  if (!bundle) {
@@ -1224,187 +1534,74 @@ function getOrCreateContextBundle(client) {
1224
1534
  function getUmbrellaStoreForClient(client) {
1225
1535
  let store = _umbrellaStores.get(client);
1226
1536
  if (!store) {
1227
- store = new UmbrellaStore();
1537
+ store = new UmbrellaStore(client);
1228
1538
  _umbrellaStores.set(client, store);
1229
1539
  }
1230
1540
  return store;
1231
1541
  }
1232
- function getExtrasForClient(client) {
1542
+ function getLiveblocksExtrasForClient(client) {
1233
1543
  let extras = _extras.get(client);
1234
1544
  if (!extras) {
1235
- extras = makeExtrasForClient(client);
1545
+ extras = makeLiveblocksExtrasForClient(client);
1236
1546
  _extras.set(client, extras);
1237
1547
  }
1238
1548
  return extras;
1239
1549
  }
1240
- function makeExtrasForClient(client) {
1241
- const store = getUmbrellaStoreForClient(client);
1242
- let lastRequestedAt;
1243
- async function fetchInboxNotifications() {
1244
- if (lastRequestedAt === void 0) {
1245
- const result = await client.getInboxNotifications();
1246
- store.batch(() => {
1247
- store.updateThreadsAndNotifications(
1248
- result.threads,
1249
- result.inboxNotifications,
1250
- [],
1251
- []
1252
- );
1253
- store.setQuery1OK();
1254
- });
1255
- lastRequestedAt = result.requestedAt;
1256
- } else {
1257
- const result = await client.getInboxNotificationsSince({
1258
- since: lastRequestedAt
1259
- });
1260
- store.batch(() => {
1261
- store.updateThreadsAndNotifications(
1262
- result.threads.updated,
1263
- result.inboxNotifications.updated,
1264
- result.threads.deleted,
1265
- result.inboxNotifications.deleted
1266
- );
1267
- store.setQuery1OK();
1268
- });
1269
- if (lastRequestedAt < result.requestedAt) {
1270
- lastRequestedAt = result.requestedAt;
1271
- }
1272
- }
1273
- }
1274
- let pollerSubscribers = 0;
1550
+ function makeDeltaPoller_Notifications(store) {
1275
1551
  const poller = _core.makePoller.call(void 0, async () => {
1276
1552
  try {
1277
- await waitUntilInboxNotificationsLoaded();
1278
- await fetchInboxNotifications();
1553
+ await store.waitUntilNotificationsLoaded();
1554
+ await store.fetchNotificationsDeltaUpdate();
1279
1555
  } catch (err) {
1280
1556
  console.warn(`Polling new inbox notifications failed: ${String(err)}`);
1281
1557
  }
1282
- });
1283
- const waitUntilInboxNotificationsLoaded = _core.memoizeOnSuccess.call(void 0, async () => {
1284
- store.setQuery1Loading();
1285
- try {
1286
- await _core.autoRetry.call(void 0,
1287
- () => fetchInboxNotifications(),
1288
- 5,
1289
- [5e3, 5e3, 1e4, 15e3]
1290
- );
1291
- } catch (err) {
1292
- store.setQuery1Error(err);
1293
- throw err;
1294
- }
1295
- });
1296
- function loadInboxNotifications() {
1297
- void waitUntilInboxNotificationsLoaded().catch(() => {
1298
- });
1299
- }
1300
- function startPolling() {
1558
+ }, POLLING_INTERVAL);
1559
+ let pollerSubscribers = 0;
1560
+ return () => {
1301
1561
  pollerSubscribers++;
1302
- poller.start(POLLING_INTERVAL);
1562
+ poller.enable(pollerSubscribers > 0);
1303
1563
  return () => {
1304
- if (pollerSubscribers <= 0) {
1305
- console.warn(
1306
- "Unexpected internal error: cannot decrease subscriber count for inbox notifications."
1307
- );
1308
- return;
1309
- }
1310
1564
  pollerSubscribers--;
1311
- if (pollerSubscribers <= 0) {
1312
- poller.stop();
1313
- }
1565
+ poller.enable(pollerSubscribers > 0);
1314
1566
  };
1315
- }
1316
- const userThreadsPoller = _core.makePoller.call(void 0, refreshUserThreads);
1317
- let isFetchingUserThreadsUpdates = false;
1318
- async function refreshUserThreads() {
1319
- const since = userThreadslastRequestedAt;
1320
- if (since === void 0 || isFetchingUserThreadsUpdates) {
1321
- return;
1322
- }
1567
+ };
1568
+ }
1569
+ function makeDeltaPoller_UserThreads(store) {
1570
+ const poller = _core.makePoller.call(void 0, async () => {
1323
1571
  try {
1324
- isFetchingUserThreadsUpdates = true;
1325
- const updates = await client[_core.kInternal].getThreadsSince({
1326
- since
1327
- });
1328
- isFetchingUserThreadsUpdates = false;
1329
- store.batch(() => {
1330
- store.updateThreadsAndNotifications(
1331
- updates.threads.updated,
1332
- [],
1333
- updates.threads.deleted,
1334
- []
1335
- );
1336
- store.setQuery2OK(USER_THREADS_QUERY);
1337
- });
1338
- userThreadslastRequestedAt = updates.requestedAt;
1572
+ await store.fetchUserThreadsDeltaUpdate();
1339
1573
  } catch (err) {
1340
- isFetchingUserThreadsUpdates = false;
1341
- return;
1574
+ console.warn(`Polling new user threads failed: ${String(err)}`);
1342
1575
  }
1343
- }
1344
- const userThreadsSubscribersByQuery = /* @__PURE__ */ new Map();
1345
- const userThreadsRequestsByQuery = /* @__PURE__ */ new Map();
1346
- function incrementUserThreadsQuerySubscribers(queryKey) {
1347
- const subscribers = _nullishCoalesce(userThreadsSubscribersByQuery.get(queryKey), () => ( 0));
1348
- userThreadsSubscribersByQuery.set(queryKey, subscribers + 1);
1349
- userThreadsPoller.start(POLLING_INTERVAL);
1576
+ }, POLLING_INTERVAL);
1577
+ let pollerSubscribers = 0;
1578
+ return () => {
1579
+ pollerSubscribers++;
1580
+ poller.enable(pollerSubscribers > 0);
1350
1581
  return () => {
1351
- const subscribers2 = userThreadsSubscribersByQuery.get(queryKey);
1352
- if (subscribers2 === void 0 || subscribers2 <= 0) {
1353
- console.warn(
1354
- `Internal unexpected behavior. Cannot decrease subscriber count for query "${queryKey}"`
1355
- );
1356
- return;
1357
- }
1358
- userThreadsSubscribersByQuery.set(queryKey, subscribers2 - 1);
1359
- let totalSubscribers = 0;
1360
- for (const subscribers3 of userThreadsSubscribersByQuery.values()) {
1361
- totalSubscribers += subscribers3;
1362
- }
1363
- if (totalSubscribers <= 0) {
1364
- userThreadsPoller.stop();
1365
- }
1582
+ pollerSubscribers--;
1583
+ poller.enable(pollerSubscribers > 0);
1366
1584
  };
1367
- }
1368
- let userThreadslastRequestedAt;
1369
- async function getUserThreads(queryKey, options, { retryCount } = { retryCount: 0 }) {
1370
- const existingRequest = userThreadsRequestsByQuery.get(queryKey);
1371
- if (existingRequest !== void 0) return existingRequest;
1372
- const request = client[_core.kInternal].getThreads(options);
1373
- userThreadsRequestsByQuery.set(queryKey, request);
1374
- store.setQuery2Loading(queryKey);
1375
- try {
1376
- const result = await request;
1377
- store.batch(() => {
1378
- store.updateThreadsAndNotifications(
1379
- result.threads,
1380
- result.inboxNotifications,
1381
- [],
1382
- []
1383
- );
1384
- store.setQuery2OK(queryKey);
1385
- });
1386
- if (userThreadslastRequestedAt === void 0 || userThreadslastRequestedAt < result.requestedAt) {
1387
- userThreadslastRequestedAt = result.requestedAt;
1388
- }
1389
- userThreadsPoller.start(POLLING_INTERVAL);
1390
- } catch (err) {
1391
- userThreadsRequestsByQuery.delete(queryKey);
1392
- retryError(() => {
1393
- void getUserThreads(queryKey, options, {
1394
- retryCount: retryCount + 1
1395
- });
1396
- }, retryCount);
1397
- store.setQuery2Error(queryKey, err);
1398
- }
1399
- return;
1400
- }
1585
+ };
1586
+ }
1587
+ function makeLiveblocksExtrasForClient(client) {
1588
+ const store = getUmbrellaStoreForClient(client);
1401
1589
  return {
1402
1590
  store,
1403
- startPolling,
1404
- waitUntilInboxNotificationsLoaded,
1405
- loadInboxNotifications,
1406
- incrementUserThreadsQuerySubscribers,
1407
- getUserThreads
1591
+ /**
1592
+ * Sub/unsub pair to start the process of watching for new incoming inbox
1593
+ * notifications through a stream of delta updates. Call the unsub function
1594
+ * returned to stop this subscription when unmounting. Currently
1595
+ * implemented by a periodic poller.
1596
+ */
1597
+ subscribeToNotificationsDeltaUpdates: makeDeltaPoller_Notifications(store),
1598
+ /**
1599
+ * Sub/unsub pair to start the process of watching for new user threads
1600
+ * through a stream of delta updates. Call the unsub function returned to
1601
+ * stop this subscription when unmounting. Currently implemented by
1602
+ * a periodic poller.
1603
+ */
1604
+ subscribeToUserThreadsDeltaUpdates: makeDeltaPoller_UserThreads(store)
1408
1605
  };
1409
1606
  }
1410
1607
  function makeLiveblocksContextBundle(client) {
@@ -1420,7 +1617,7 @@ function makeLiveblocksContextBundle(client) {
1420
1617
  const shared = createSharedContext(client);
1421
1618
  const bundle = {
1422
1619
  LiveblocksProvider: LiveblocksProvider2,
1423
- useInboxNotifications: () => useInboxNotifications_withClient(client),
1620
+ useInboxNotifications: () => useInboxNotifications_withClient(client, identity, _core.shallow),
1424
1621
  useUnreadInboxNotificationsCount: () => useUnreadInboxNotificationsCount_withClient(client),
1425
1622
  useMarkInboxNotificationAsRead: useMarkInboxNotificationAsRead2,
1426
1623
  useMarkAllInboxNotificationsAsRead: useMarkAllInboxNotificationsAsRead2,
@@ -1444,41 +1641,42 @@ function makeLiveblocksContextBundle(client) {
1444
1641
  };
1445
1642
  return bundle;
1446
1643
  }
1447
- function useInboxNotifications_withClient(client) {
1448
- const { loadInboxNotifications, store, startPolling } = getExtrasForClient(client);
1449
- _react.useEffect.call(void 0, loadInboxNotifications, [loadInboxNotifications]);
1450
- _react.useEffect.call(void 0, startPolling, [startPolling]);
1644
+ function useInboxNotifications_withClient(client, selector, isEqual) {
1645
+ const {
1646
+ store,
1647
+ subscribeToNotificationsDeltaUpdates: subscribeToDeltaUpdates
1648
+ } = getLiveblocksExtrasForClient(client);
1649
+ _react.useEffect.call(void 0, () => {
1650
+ void store.waitUntilNotificationsLoaded().catch(() => {
1651
+ });
1652
+ });
1653
+ _react.useEffect.call(void 0, subscribeToDeltaUpdates, [subscribeToDeltaUpdates]);
1451
1654
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1452
1655
  store.subscribeThreadsOrInboxNotifications,
1453
1656
  store.getInboxNotificationsAsync,
1454
1657
  store.getInboxNotificationsAsync,
1455
- identity,
1456
- _core.shallow
1658
+ selector,
1659
+ isEqual
1457
1660
  );
1458
1661
  }
1459
1662
  function useInboxNotificationsSuspense_withClient(client) {
1460
- const { waitUntilInboxNotificationsLoaded } = getExtrasForClient(client);
1461
- use(waitUntilInboxNotificationsLoaded());
1462
- const result = useInboxNotifications_withClient(client);
1663
+ const store = getLiveblocksExtrasForClient(client).store;
1664
+ use(store.waitUntilNotificationsLoaded());
1665
+ const result = useInboxNotifications_withClient(client, identity, _core.shallow);
1463
1666
  _core.assert.call(void 0, !result.error, "Did not expect error");
1464
1667
  _core.assert.call(void 0, !result.isLoading, "Did not expect loading");
1465
1668
  return result;
1466
1669
  }
1467
1670
  function useUnreadInboxNotificationsCount_withClient(client) {
1468
- const { store, loadInboxNotifications, startPolling } = getExtrasForClient(client);
1469
- _react.useEffect.call(void 0, loadInboxNotifications, [loadInboxNotifications]);
1470
- _react.useEffect.call(void 0, startPolling, [startPolling]);
1471
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1472
- store.subscribeThreadsOrInboxNotifications,
1473
- store.getInboxNotificationsAsync,
1474
- store.getInboxNotificationsAsync,
1671
+ return useInboxNotifications_withClient(
1672
+ client,
1475
1673
  selectorFor_useUnreadInboxNotificationsCount,
1476
1674
  _core.shallow
1477
1675
  );
1478
1676
  }
1479
1677
  function useUnreadInboxNotificationsCountSuspense_withClient(client) {
1480
- const { waitUntilInboxNotificationsLoaded } = getExtrasForClient(client);
1481
- use(waitUntilInboxNotificationsLoaded());
1678
+ const store = getLiveblocksExtrasForClient(client).store;
1679
+ use(store.waitUntilNotificationsLoaded());
1482
1680
  const result = useUnreadInboxNotificationsCount_withClient(client);
1483
1681
  _core.assert.call(void 0, !result.isLoading, "Did not expect loading");
1484
1682
  _core.assert.call(void 0, !result.error, "Did not expect error");
@@ -1487,7 +1685,7 @@ function useUnreadInboxNotificationsCountSuspense_withClient(client) {
1487
1685
  function useMarkInboxNotificationAsRead_withClient(client) {
1488
1686
  return _react.useCallback.call(void 0,
1489
1687
  (inboxNotificationId) => {
1490
- const { store } = getExtrasForClient(client);
1688
+ const { store } = getLiveblocksExtrasForClient(client);
1491
1689
  const readAt = /* @__PURE__ */ new Date();
1492
1690
  const optimisticUpdateId = store.addOptimisticUpdate({
1493
1691
  type: "mark-inbox-notification-as-read",
@@ -1512,7 +1710,7 @@ function useMarkInboxNotificationAsRead_withClient(client) {
1512
1710
  }
1513
1711
  function useMarkAllInboxNotificationsAsRead_withClient(client) {
1514
1712
  return _react.useCallback.call(void 0, () => {
1515
- const { store } = getExtrasForClient(client);
1713
+ const { store } = getLiveblocksExtrasForClient(client);
1516
1714
  const readAt = /* @__PURE__ */ new Date();
1517
1715
  const optimisticUpdateId = store.addOptimisticUpdate({
1518
1716
  type: "mark-all-inbox-notifications-as-read",
@@ -1534,7 +1732,7 @@ function useMarkAllInboxNotificationsAsRead_withClient(client) {
1534
1732
  function useDeleteInboxNotification_withClient(client) {
1535
1733
  return _react.useCallback.call(void 0,
1536
1734
  (inboxNotificationId) => {
1537
- const { store } = getExtrasForClient(client);
1735
+ const { store } = getLiveblocksExtrasForClient(client);
1538
1736
  const deletedAt = /* @__PURE__ */ new Date();
1539
1737
  const optimisticUpdateId = store.addOptimisticUpdate({
1540
1738
  type: "delete-inbox-notification",
@@ -1558,7 +1756,7 @@ function useDeleteInboxNotification_withClient(client) {
1558
1756
  }
1559
1757
  function useDeleteAllInboxNotifications_withClient(client) {
1560
1758
  return _react.useCallback.call(void 0, () => {
1561
- const { store } = getExtrasForClient(client);
1759
+ const { store } = getLiveblocksExtrasForClient(client);
1562
1760
  const deletedAt = /* @__PURE__ */ new Date();
1563
1761
  const optimisticUpdateId = store.addOptimisticUpdate({
1564
1762
  type: "delete-all-inbox-notifications",
@@ -1575,11 +1773,11 @@ function useDeleteAllInboxNotifications_withClient(client) {
1575
1773
  }, [client]);
1576
1774
  }
1577
1775
  function useInboxNotificationThread_withClient(client, inboxNotificationId) {
1578
- const { store } = getExtrasForClient(client);
1776
+ const { store } = getLiveblocksExtrasForClient(client);
1579
1777
  const getter = store.getFullState;
1580
1778
  const selector = _react.useCallback.call(void 0,
1581
1779
  (state) => {
1582
- const inboxNotification = _nullishCoalesce(state.inboxNotificationsById[inboxNotificationId], () => ( _core.raise.call(void 0, `Inbox notification with ID "${inboxNotificationId}" not found`)));
1780
+ const inboxNotification = _nullishCoalesce(state.notificationsById[inboxNotificationId], () => ( _core.raise.call(void 0, `Inbox notification with ID "${inboxNotificationId}" not found`)));
1583
1781
  if (inboxNotification.kind !== "thread") {
1584
1782
  _core.raise.call(void 0,
1585
1783
  `Inbox notification with ID "${inboxNotificationId}" is not of kind "thread"`
@@ -1722,7 +1920,7 @@ function createSharedContext(client) {
1722
1920
  }
1723
1921
  function useEnsureNoLiveblocksProvider(options) {
1724
1922
  const existing = useClientOrNull();
1725
- if (!_optionalChain([options, 'optionalAccess', _21 => _21.allowNesting]) && existing !== null) {
1923
+ if (!_optionalChain([options, 'optionalAccess', _24 => _24.allowNesting]) && existing !== null) {
1726
1924
  throw new Error(
1727
1925
  "You cannot nest multiple LiveblocksProvider instances in the same React tree."
1728
1926
  );
@@ -1774,40 +1972,32 @@ function useUserThreads_experimental(options = {
1774
1972
  metadata: {}
1775
1973
  }
1776
1974
  }) {
1777
- const queryKey = React.default.useMemo(
1778
- () => makeUserThreadsQueryKey(options.query),
1779
- [options]
1780
- );
1781
1975
  const client = useClient();
1782
- const { store, incrementUserThreadsQuerySubscribers, getUserThreads } = getExtrasForClient(client);
1783
- _react.useEffect.call(void 0, () => {
1784
- void getUserThreads(queryKey, options);
1785
- return incrementUserThreadsQuerySubscribers(queryKey);
1786
- }, [queryKey, incrementUserThreadsQuerySubscribers, getUserThreads, options]);
1787
- const getter = _react.useCallback.call(void 0,
1788
- () => store.getUserThreadsAsync(queryKey),
1789
- [store, queryKey]
1790
- );
1791
- const selector = _react.useCallback.call(void 0,
1792
- (result) => {
1793
- if (!result.fullState) {
1794
- return result;
1795
- }
1796
- const threads = selectThreads(result.fullState, {
1797
- roomId: null,
1798
- // Do _not_ filter by roomId
1799
- query: options.query,
1800
- orderBy: "last-update"
1976
+ const { store, subscribeToUserThreadsDeltaUpdates: subscribeToDeltaUpdates } = getLiveblocksExtrasForClient(client);
1977
+ _react.useEffect.call(void 0,
1978
+ () => {
1979
+ void store.waitUntilUserThreadsLoaded(options.query).catch(() => {
1801
1980
  });
1802
- return { isLoading: false, threads };
1803
- },
1804
- [options]
1981
+ }
1982
+ // NOTE: Deliberately *not* using a dependency array here!
1983
+ //
1984
+ // It is important to call waitUntil on *every* render.
1985
+ // This is harmless though, on most renders, except:
1986
+ // 1. The very first render, in which case we'll want to trigger the initial page fetch.
1987
+ // 2. All other subsequent renders now "just" return the same promise (a quick operation).
1988
+ // 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
1989
+ // *next* render after that, a *new* fetch/promise will get created.
1990
+ );
1991
+ _react.useEffect.call(void 0, subscribeToDeltaUpdates, [subscribeToDeltaUpdates]);
1992
+ const getter = _react.useCallback.call(void 0,
1993
+ () => store.getUserThreadsAsync(options.query),
1994
+ [store, options.query]
1805
1995
  );
1806
1996
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1807
1997
  store.subscribeUserThreads,
1808
1998
  getter,
1809
1999
  getter,
1810
- selector,
2000
+ identity,
1811
2001
  shallow2
1812
2002
  // NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
1813
2003
  );
@@ -1817,49 +2007,16 @@ function useUserThreadsSuspense_experimental(options = {
1817
2007
  metadata: {}
1818
2008
  }
1819
2009
  }) {
1820
- const queryKey = React.default.useMemo(
1821
- () => makeUserThreadsQueryKey(options.query),
1822
- [options]
1823
- );
1824
2010
  const client = useClient();
1825
- const { store, getUserThreads } = getExtrasForClient(client);
1826
- React.default.useEffect(() => {
1827
- const { incrementUserThreadsQuerySubscribers } = getExtrasForClient(client);
1828
- return incrementUserThreadsQuerySubscribers(queryKey);
1829
- }, [client, queryKey]);
1830
- const query = store.getFullState().queries2[queryKey];
1831
- if (query === void 0 || query.isLoading) {
1832
- throw getUserThreads(queryKey, options);
1833
- }
1834
- if (query.error) {
1835
- throw query.error;
1836
- }
1837
- const getter = store.getFullState;
1838
- const selector = _react.useCallback.call(void 0,
1839
- (state) => {
1840
- return {
1841
- threads: selectThreads(state, {
1842
- roomId: null,
1843
- // Do _not_ filter by roomId
1844
- query: options.query,
1845
- orderBy: "last-update"
1846
- }),
1847
- isLoading: false
1848
- };
1849
- },
1850
- [options]
1851
- );
1852
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1853
- store.subscribeUserThreads,
1854
- getter,
1855
- getter,
1856
- selector,
1857
- shallow2
1858
- // NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
1859
- );
2011
+ const { store } = getLiveblocksExtrasForClient(client);
2012
+ use(store.waitUntilUserThreadsLoaded(options.query));
2013
+ const result = useUserThreads_experimental(options);
2014
+ _core.assert.call(void 0, !result.error, "Did not expect error");
2015
+ _core.assert.call(void 0, !result.isLoading, "Did not expect loading");
2016
+ return result;
1860
2017
  }
1861
2018
  function useInboxNotifications() {
1862
- return useInboxNotifications_withClient(useClient());
2019
+ return useInboxNotifications_withClient(useClient(), identity, _core.shallow);
1863
2020
  }
1864
2021
  function useInboxNotificationsSuspense() {
1865
2022
  return useInboxNotificationsSuspense_withClient(useClient());
@@ -1907,7 +2064,6 @@ var _useUser = useUser;
1907
2064
  var _useUserSuspense = useUserSuspense;
1908
2065
  var _useUserThreads_experimental = useUserThreads_experimental;
1909
2066
  var _useUserThreadsSuspense_experimental = useUserThreadsSuspense_experimental;
1910
- var makeUserThreadsQueryKey = (options) => `${USER_THREADS_QUERY}:${_core.stringify.call(void 0, options)}`;
1911
2067
 
1912
2068
  // src/types/errors.ts
1913
2069
  var CreateThreadError = class extends Error {
@@ -2008,7 +2164,7 @@ var UpdateNotificationSettingsError = class extends Error {
2008
2164
  };
2009
2165
 
2010
2166
  // src/room.tsx
2011
- var _client = require('@liveblocks/client');
2167
+ var _client2 = require('@liveblocks/client');
2012
2168
 
2013
2169
 
2014
2170
 
@@ -2026,6 +2182,16 @@ var _client = require('@liveblocks/client');
2026
2182
 
2027
2183
 
2028
2184
 
2185
+ // src/lib/retry-error.ts
2186
+ var MAX_ERROR_RETRY_COUNT = 5;
2187
+ var ERROR_RETRY_INTERVAL = 5e3;
2188
+ function retryError(action, retryCount) {
2189
+ if (retryCount >= MAX_ERROR_RETRY_COUNT) return;
2190
+ const timeout = Math.pow(2, retryCount) * ERROR_RETRY_INTERVAL;
2191
+ setTimeout(() => {
2192
+ void action();
2193
+ }, timeout);
2194
+ }
2029
2195
 
2030
2196
  // src/use-scroll-to-comment-on-load-effect.ts
2031
2197
 
@@ -2058,7 +2224,7 @@ function useScrollToCommentOnLoadEffect(shouldScrollOnLoad, state) {
2058
2224
 
2059
2225
  // src/room.tsx
2060
2226
  var SMOOTH_DELAY = 1e3;
2061
- var noop2 = () => {
2227
+ var noop3 = () => {
2062
2228
  };
2063
2229
  var identity2 = (x) => x;
2064
2230
  var missing_unstable_batchedUpdates = (reactVersion, roomId) => `We noticed you\u2019re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you\u2019re ready to upgrade to React 18:
@@ -2126,12 +2292,34 @@ function getCurrentUserId(room) {
2126
2292
  }
2127
2293
  function handleApiError(err) {
2128
2294
  const message = `Request failed with status ${err.status}: ${err.message}`;
2129
- if (_optionalChain([err, 'access', _22 => _22.details, 'optionalAccess', _23 => _23.error]) === "FORBIDDEN") {
2295
+ if (_optionalChain([err, 'access', _25 => _25.details, 'optionalAccess', _26 => _26.error]) === "FORBIDDEN") {
2130
2296
  const detailedMessage = [message, err.details.suggestion, err.details.docs].filter(Boolean).join("\n");
2131
2297
  _core.console.error(detailedMessage);
2132
2298
  }
2133
2299
  return new Error(message);
2134
2300
  }
2301
+ function makeDeltaPoller_RoomThreads(client) {
2302
+ const store = getUmbrellaStoreForClient(client);
2303
+ const poller = _core.makePoller.call(void 0, async () => {
2304
+ const roomIds = client[_core.kInternal].getRoomIds();
2305
+ await Promise.allSettled(
2306
+ roomIds.map((roomId) => {
2307
+ const room = client.getRoom(roomId);
2308
+ if (room === null) return;
2309
+ return store.fetchRoomThreadsDeltaUpdate(room.id);
2310
+ })
2311
+ );
2312
+ }, POLLING_INTERVAL2);
2313
+ let pollerSubscribers = 0;
2314
+ return () => {
2315
+ pollerSubscribers++;
2316
+ poller.enable(pollerSubscribers > 0);
2317
+ return () => {
2318
+ pollerSubscribers--;
2319
+ poller.enable(pollerSubscribers > 0);
2320
+ };
2321
+ };
2322
+ }
2135
2323
  var _extras2 = /* @__PURE__ */ new WeakMap();
2136
2324
  var _bundles2 = /* @__PURE__ */ new WeakMap();
2137
2325
  function getOrCreateRoomContextBundle(client) {
@@ -2142,78 +2330,17 @@ function getOrCreateRoomContextBundle(client) {
2142
2330
  }
2143
2331
  return bundle;
2144
2332
  }
2145
- function getExtrasForClient2(client) {
2333
+ function getRoomExtrasForClient(client) {
2146
2334
  let extras = _extras2.get(client);
2147
2335
  if (!extras) {
2148
- extras = makeExtrasForClient2(client);
2336
+ extras = makeRoomExtrasForClient(client);
2149
2337
  _extras2.set(client, extras);
2150
2338
  }
2151
2339
  return extras;
2152
2340
  }
2153
- function makeExtrasForClient2(client) {
2341
+ function makeRoomExtrasForClient(client) {
2154
2342
  const store = getUmbrellaStoreForClient(client);
2155
- const DEFAULT_DEDUPING_INTERVAL = 2e3;
2156
- const lastRequestedAtByRoom = /* @__PURE__ */ new Map();
2157
2343
  const requestsByQuery = /* @__PURE__ */ new Map();
2158
- const requestStatusByRoom = /* @__PURE__ */ new Map();
2159
- const subscribersByQuery = /* @__PURE__ */ new Map();
2160
- const poller = _core.makePoller.call(void 0, refreshThreadsAndNotifications);
2161
- async function refreshThreadsAndNotifications() {
2162
- const requests = [];
2163
- client[_core.kInternal].getRoomIds().map((roomId) => {
2164
- const room = client.getRoom(roomId);
2165
- if (room === null) return;
2166
- requests.push(getThreadsUpdates(room.id));
2167
- });
2168
- await Promise.allSettled(requests);
2169
- }
2170
- function incrementQuerySubscribers(queryKey) {
2171
- const subscribers = _nullishCoalesce(subscribersByQuery.get(queryKey), () => ( 0));
2172
- subscribersByQuery.set(queryKey, subscribers + 1);
2173
- poller.start(POLLING_INTERVAL2);
2174
- return () => {
2175
- const subscribers2 = subscribersByQuery.get(queryKey);
2176
- if (subscribers2 === void 0 || subscribers2 <= 0) {
2177
- _core.console.warn(
2178
- `Internal unexpected behavior. Cannot decrease subscriber count for query "${queryKey}"`
2179
- );
2180
- return;
2181
- }
2182
- subscribersByQuery.set(queryKey, subscribers2 - 1);
2183
- let totalSubscribers = 0;
2184
- for (const subscribers3 of subscribersByQuery.values()) {
2185
- totalSubscribers += subscribers3;
2186
- }
2187
- if (totalSubscribers <= 0) {
2188
- poller.stop();
2189
- }
2190
- };
2191
- }
2192
- async function getThreadsUpdates(roomId) {
2193
- const room = client.getRoom(roomId);
2194
- if (room === null) return;
2195
- const since = lastRequestedAtByRoom.get(room.id);
2196
- if (since === void 0) return;
2197
- const isFetchingThreadsUpdates = _nullishCoalesce(requestStatusByRoom.get(room.id), () => ( false));
2198
- if (isFetchingThreadsUpdates === true) return;
2199
- try {
2200
- requestStatusByRoom.set(room.id, true);
2201
- const updates = await room.getThreadsSince({ since });
2202
- setTimeout(() => {
2203
- requestStatusByRoom.set(room.id, false);
2204
- }, DEFAULT_DEDUPING_INTERVAL);
2205
- store.updateThreadsAndNotifications(
2206
- updates.threads.updated,
2207
- updates.inboxNotifications.updated,
2208
- updates.threads.deleted,
2209
- updates.inboxNotifications.deleted
2210
- );
2211
- lastRequestedAtByRoom.set(room.id, updates.requestedAt);
2212
- } catch (err) {
2213
- requestStatusByRoom.set(room.id, false);
2214
- return;
2215
- }
2216
- }
2217
2344
  async function getRoomVersions(room, { retryCount } = { retryCount: 0 }) {
2218
2345
  const queryKey = makeVersionsQueryKey(room.id);
2219
2346
  const existingRequest = requestsByQuery.get(queryKey);
@@ -2243,40 +2370,6 @@ function makeExtrasForClient2(client) {
2243
2370
  }
2244
2371
  return;
2245
2372
  }
2246
- async function getThreadsAndInboxNotifications(room, queryKey, options, { retryCount } = { retryCount: 0 }) {
2247
- const existingRequest = requestsByQuery.get(queryKey);
2248
- if (existingRequest !== void 0) return existingRequest;
2249
- const request = room.getThreads(options);
2250
- requestsByQuery.set(queryKey, request);
2251
- store.setQuery2Loading(queryKey);
2252
- try {
2253
- const result = await request;
2254
- store.batch(() => {
2255
- store.updateThreadsAndNotifications(
2256
- result.threads,
2257
- // TODO: Figure out how to remove this casting
2258
- result.inboxNotifications,
2259
- [],
2260
- []
2261
- );
2262
- store.setQuery2OK(queryKey);
2263
- });
2264
- const lastRequestedAt = lastRequestedAtByRoom.get(room.id);
2265
- if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
2266
- lastRequestedAtByRoom.set(room.id, result.requestedAt);
2267
- }
2268
- poller.start(POLLING_INTERVAL2);
2269
- } catch (err) {
2270
- requestsByQuery.delete(queryKey);
2271
- retryError(() => {
2272
- void getThreadsAndInboxNotifications(room, queryKey, options, {
2273
- retryCount: retryCount + 1
2274
- });
2275
- }, retryCount);
2276
- store.setQuery2Error(queryKey, err);
2277
- }
2278
- return;
2279
- }
2280
2373
  async function getInboxNotificationSettings(room, { retryCount } = { retryCount: 0 }) {
2281
2374
  const queryKey = makeNotificationSettingsQueryKey(room.id);
2282
2375
  const existingRequest = requestsByQuery.get(queryKey);
@@ -2314,10 +2407,8 @@ function makeExtrasForClient2(client) {
2314
2407
  }
2315
2408
  return {
2316
2409
  store,
2317
- incrementQuerySubscribers,
2410
+ subscribeToRoomThreadsDeltaUpdates: makeDeltaPoller_RoomThreads(client),
2318
2411
  commentsErrorEventSource,
2319
- getThreadsUpdates,
2320
- getThreadsAndInboxNotifications,
2321
2412
  getInboxNotificationSettings,
2322
2413
  getRoomVersions,
2323
2414
  onMutationFailure
@@ -2492,7 +2583,7 @@ function RoomProviderInner(props) {
2492
2583
  })
2493
2584
  );
2494
2585
  React5.useEffect(() => {
2495
- const { store } = getExtrasForClient2(client);
2586
+ const { store } = getRoomExtrasForClient(client);
2496
2587
  async function handleCommentEvent(message) {
2497
2588
  if (message.type === _core.ServerMsgCode.THREAD_DELETED) {
2498
2589
  store.deleteThread(message.threadId, null);
@@ -2527,13 +2618,15 @@ function RoomProviderInner(props) {
2527
2618
  );
2528
2619
  }, [client, room]);
2529
2620
  React5.useEffect(() => {
2530
- const { getThreadsUpdates } = getExtrasForClient2(client);
2531
- void getThreadsUpdates(room.id);
2621
+ const store = getRoomExtrasForClient(client).store;
2622
+ void store.fetchRoomThreadsDeltaUpdate(room.id).catch(() => {
2623
+ });
2532
2624
  }, [client, room.id]);
2533
2625
  React5.useEffect(() => {
2534
2626
  function handleIsOnline() {
2535
- const { getThreadsUpdates } = getExtrasForClient2(client);
2536
- void getThreadsUpdates(room.id);
2627
+ const store = getRoomExtrasForClient(client).store;
2628
+ void store.fetchRoomThreadsDeltaUpdate(room.id).catch(() => {
2629
+ });
2537
2630
  }
2538
2631
  window.addEventListener("online", handleIsOnline);
2539
2632
  return () => {
@@ -2568,7 +2661,7 @@ function useStatus() {
2568
2661
  return useSyncExternalStore2(subscribe, getSnapshot, getServerSnapshot);
2569
2662
  }
2570
2663
  function useStorageStatus(options) {
2571
- const smooth = useInitial(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _24 => _24.smooth]), () => ( false)));
2664
+ const smooth = useInitial(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _27 => _27.smooth]), () => ( false)));
2572
2665
  if (smooth) {
2573
2666
  return useStorageStatusSmooth();
2574
2667
  } else {
@@ -2732,7 +2825,7 @@ function useOthersMapped(itemSelector, itemIsEqual) {
2732
2825
  return useOthers(wrappedSelector, wrappedIsEqual);
2733
2826
  }
2734
2827
  function useOthersConnectionIds() {
2735
- return useOthers(selectorFor_useOthersConnectionIds, _client.shallow);
2828
+ return useOthers(selectorFor_useOthersConnectionIds, _client2.shallow);
2736
2829
  }
2737
2830
  var NOT_FOUND = Symbol();
2738
2831
  function useOther(connectionId, selector, isEqual) {
@@ -2779,7 +2872,7 @@ function useStorage(selector, isEqual) {
2779
2872
  [selector]
2780
2873
  );
2781
2874
  const subscribe = React5.useCallback(
2782
- (onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) : noop2,
2875
+ (onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) : noop3,
2783
2876
  [room, rootOrNull]
2784
2877
  );
2785
2878
  const getSnapshot = React5.useCallback(() => {
@@ -2827,40 +2920,33 @@ function useThreads(options = {
2827
2920
  const { scrollOnLoad = true } = options;
2828
2921
  const client = useClient();
2829
2922
  const room = useRoom();
2830
- const queryKey = React5.useMemo(
2831
- () => generateQueryKey(room.id, options.query),
2832
- [room, options]
2833
- );
2834
- const { store, getThreadsAndInboxNotifications, incrementQuerySubscribers } = getExtrasForClient2(client);
2835
- React5.useEffect(() => {
2836
- void getThreadsAndInboxNotifications(room, queryKey, options);
2837
- return incrementQuerySubscribers(queryKey);
2838
- }, [room, queryKey]);
2839
- const getter = React5.useCallback(
2840
- () => store.getThreadsAsync(queryKey),
2841
- [store, queryKey]
2842
- );
2843
- const selector = React5.useCallback(
2844
- (result) => {
2845
- if (!result.fullState) {
2846
- return result;
2847
- }
2848
- const threads = selectThreads(result.fullState, {
2849
- roomId: room.id,
2850
- query: options.query,
2851
- orderBy: "age"
2923
+ const { store, subscribeToRoomThreadsDeltaUpdates: subscribeToDeltaUpdates } = getRoomExtrasForClient(client);
2924
+ React5.useEffect(
2925
+ () => {
2926
+ void store.waitUntilRoomThreadsLoaded(room.id, options.query).catch(() => {
2852
2927
  });
2853
- return { isLoading: false, threads };
2854
- },
2855
- [room.id, queryKey]
2856
- // eslint-disable-line react-hooks/exhaustive-deps
2928
+ }
2929
+ // NOTE: Deliberately *not* using a dependency array here!
2930
+ //
2931
+ // It is important to call waitUntil on *every* render.
2932
+ // This is harmless though, on most renders, except:
2933
+ // 1. The very first render, in which case we'll want to trigger the initial page fetch.
2934
+ // 2. All other subsequent renders now "just" return the same promise (a quick operation).
2935
+ // 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
2936
+ // *next* render after that, a *new* fetch/promise will get created.
2937
+ );
2938
+ React5.useEffect(subscribeToDeltaUpdates, [subscribeToDeltaUpdates]);
2939
+ const getter = React5.useCallback(
2940
+ () => store.getRoomThreadsAsync(room.id, options.query),
2941
+ [store, room.id, options.query]
2857
2942
  );
2858
2943
  const state = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
2859
2944
  store.subscribeThreads,
2860
2945
  getter,
2861
2946
  getter,
2862
- selector,
2947
+ identity2,
2863
2948
  shallow2
2949
+ // NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
2864
2950
  );
2865
2951
  useScrollToCommentOnLoadEffect(scrollOnLoad, state);
2866
2952
  return state;
@@ -2868,7 +2954,7 @@ function useThreads(options = {
2868
2954
  function useCommentsErrorListener(callback) {
2869
2955
  const client = useClient();
2870
2956
  const savedCallback = useLatest(callback);
2871
- const { commentsErrorEventSource } = getExtrasForClient2(client);
2957
+ const { commentsErrorEventSource } = getRoomExtrasForClient(client);
2872
2958
  React5.useEffect(() => {
2873
2959
  return commentsErrorEventSource.subscribe(savedCallback.current);
2874
2960
  }, [savedCallback, commentsErrorEventSource]);
@@ -2905,13 +2991,13 @@ function useCreateThread() {
2905
2991
  comments: [newComment],
2906
2992
  resolved: false
2907
2993
  };
2908
- const { store, onMutationFailure } = getExtrasForClient2(client);
2994
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
2909
2995
  const optimisticUpdateId = store.addOptimisticUpdate({
2910
2996
  type: "create-thread",
2911
2997
  thread: newThread,
2912
2998
  roomId: room.id
2913
2999
  });
2914
- const attachmentIds = _optionalChain([attachments, 'optionalAccess', _25 => _25.map, 'call', _26 => _26((attachment) => attachment.id)]);
3000
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _28 => _28.map, 'call', _29 => _29((attachment) => attachment.id)]);
2915
3001
  room.createThread({ threadId, commentId, body, metadata, attachmentIds }).then(
2916
3002
  (thread) => {
2917
3003
  store.createThread(optimisticUpdateId, thread);
@@ -2938,10 +3024,10 @@ function useDeleteThread() {
2938
3024
  const room = useRoom();
2939
3025
  return React5.useCallback(
2940
3026
  (threadId) => {
2941
- const { store, onMutationFailure } = getExtrasForClient2(client);
3027
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
2942
3028
  const thread = store.getFullState().threadsById[threadId];
2943
3029
  const userId = getCurrentUserId(room);
2944
- if (_optionalChain([thread, 'optionalAccess', _27 => _27.comments, 'optionalAccess', _28 => _28[0], 'optionalAccess', _29 => _29.userId]) !== userId) {
3030
+ if (_optionalChain([thread, 'optionalAccess', _30 => _30.comments, 'optionalAccess', _31 => _31[0], 'optionalAccess', _32 => _32.userId]) !== userId) {
2945
3031
  throw new Error("Only the thread creator can delete the thread");
2946
3032
  }
2947
3033
  const optimisticUpdateId = store.addOptimisticUpdate({
@@ -2975,7 +3061,7 @@ function useEditThreadMetadata() {
2975
3061
  const threadId = options.threadId;
2976
3062
  const metadata = options.metadata;
2977
3063
  const updatedAt = /* @__PURE__ */ new Date();
2978
- const { store, onMutationFailure } = getExtrasForClient2(client);
3064
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
2979
3065
  const optimisticUpdateId = store.addOptimisticUpdate({
2980
3066
  type: "edit-thread-metadata",
2981
3067
  metadata,
@@ -3024,12 +3110,12 @@ function useCreateComment() {
3024
3110
  reactions: [],
3025
3111
  attachments: _nullishCoalesce(attachments, () => ( []))
3026
3112
  };
3027
- const { store, onMutationFailure } = getExtrasForClient2(client);
3113
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3028
3114
  const optimisticUpdateId = store.addOptimisticUpdate({
3029
3115
  type: "create-comment",
3030
3116
  comment
3031
3117
  });
3032
- const attachmentIds = _optionalChain([attachments, 'optionalAccess', _30 => _30.map, 'call', _31 => _31((attachment) => attachment.id)]);
3118
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _33 => _33.map, 'call', _34 => _34((attachment) => attachment.id)]);
3033
3119
  room.createComment({ threadId, commentId, body, attachmentIds }).then(
3034
3120
  (newComment) => {
3035
3121
  store.createComment(newComment, optimisticUpdateId);
@@ -3056,7 +3142,7 @@ function useEditComment() {
3056
3142
  return React5.useCallback(
3057
3143
  ({ threadId, commentId, body, attachments }) => {
3058
3144
  const editedAt = /* @__PURE__ */ new Date();
3059
- const { store, onMutationFailure } = getExtrasForClient2(client);
3145
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3060
3146
  const thread = store.getFullState().threadsById[threadId];
3061
3147
  if (thread === void 0) {
3062
3148
  _core.console.warn(
@@ -3082,7 +3168,7 @@ function useEditComment() {
3082
3168
  attachments: _nullishCoalesce(attachments, () => ( []))
3083
3169
  }
3084
3170
  });
3085
- const attachmentIds = _optionalChain([attachments, 'optionalAccess', _32 => _32.map, 'call', _33 => _33((attachment) => attachment.id)]);
3171
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _35 => _35.map, 'call', _36 => _36((attachment) => attachment.id)]);
3086
3172
  room.editComment({ threadId, commentId, body, attachmentIds }).then(
3087
3173
  (editedComment) => {
3088
3174
  store.editComment(threadId, optimisticUpdateId, editedComment);
@@ -3108,7 +3194,7 @@ function useDeleteComment() {
3108
3194
  return React5.useCallback(
3109
3195
  ({ threadId, commentId }) => {
3110
3196
  const deletedAt = /* @__PURE__ */ new Date();
3111
- const { store, onMutationFailure } = getExtrasForClient2(client);
3197
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3112
3198
  const optimisticUpdateId = store.addOptimisticUpdate({
3113
3199
  type: "delete-comment",
3114
3200
  threadId,
@@ -3146,7 +3232,7 @@ function useAddReaction() {
3146
3232
  ({ threadId, commentId, emoji }) => {
3147
3233
  const createdAt = /* @__PURE__ */ new Date();
3148
3234
  const userId = getCurrentUserId(room);
3149
- const { store, onMutationFailure } = getExtrasForClient2(client);
3235
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3150
3236
  const optimisticUpdateId = store.addOptimisticUpdate({
3151
3237
  type: "add-reaction",
3152
3238
  threadId,
@@ -3189,7 +3275,7 @@ function useRemoveReaction() {
3189
3275
  ({ threadId, commentId, emoji }) => {
3190
3276
  const userId = getCurrentUserId(room);
3191
3277
  const removedAt = /* @__PURE__ */ new Date();
3192
- const { store, onMutationFailure } = getExtrasForClient2(client);
3278
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3193
3279
  const optimisticUpdateId = store.addOptimisticUpdate({
3194
3280
  type: "remove-reaction",
3195
3281
  threadId,
@@ -3229,9 +3315,9 @@ function useMarkThreadAsRead() {
3229
3315
  const room = useRoom();
3230
3316
  return React5.useCallback(
3231
3317
  (threadId) => {
3232
- const { store, onMutationFailure } = getExtrasForClient2(client);
3318
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3233
3319
  const inboxNotification = Object.values(
3234
- store.getFullState().inboxNotificationsById
3320
+ store.getFullState().notificationsById
3235
3321
  ).find(
3236
3322
  (inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
3237
3323
  );
@@ -3271,7 +3357,7 @@ function useMarkThreadAsResolved() {
3271
3357
  return React5.useCallback(
3272
3358
  (threadId) => {
3273
3359
  const updatedAt = /* @__PURE__ */ new Date();
3274
- const { store, onMutationFailure } = getExtrasForClient2(client);
3360
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3275
3361
  const optimisticUpdateId = store.addOptimisticUpdate({
3276
3362
  type: "mark-thread-as-resolved",
3277
3363
  threadId,
@@ -3305,7 +3391,7 @@ function useMarkThreadAsUnresolved() {
3305
3391
  return React5.useCallback(
3306
3392
  (threadId) => {
3307
3393
  const updatedAt = /* @__PURE__ */ new Date();
3308
- const { store, onMutationFailure } = getExtrasForClient2(client);
3394
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3309
3395
  const optimisticUpdateId = store.addOptimisticUpdate({
3310
3396
  type: "mark-thread-as-unresolved",
3311
3397
  threadId,
@@ -3335,10 +3421,10 @@ function useMarkThreadAsUnresolved() {
3335
3421
  }
3336
3422
  function useThreadSubscription(threadId) {
3337
3423
  const client = useClient();
3338
- const { store } = getExtrasForClient2(client);
3424
+ const { store } = getRoomExtrasForClient(client);
3339
3425
  const selector = React5.useCallback(
3340
3426
  (state) => {
3341
- const inboxNotification = state.inboxNotifications.find(
3427
+ const inboxNotification = state.notifications.find(
3342
3428
  (inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
3343
3429
  );
3344
3430
  const thread = state.threadsById[threadId];
@@ -3365,13 +3451,13 @@ function useRoomNotificationSettings() {
3365
3451
  const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
3366
3452
  const client = useClient();
3367
3453
  const room = useRoom();
3368
- const { store } = getExtrasForClient2(client);
3454
+ const { store } = getRoomExtrasForClient(client);
3369
3455
  const getter = React5.useCallback(
3370
3456
  () => store.getNotificationSettingsAsync(room.id),
3371
3457
  [store, room.id]
3372
3458
  );
3373
3459
  React5.useEffect(() => {
3374
- const { getInboxNotificationSettings } = getExtrasForClient2(client);
3460
+ const { getInboxNotificationSettings } = getRoomExtrasForClient(client);
3375
3461
  void getInboxNotificationSettings(room);
3376
3462
  }, [client, room]);
3377
3463
  const settings = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
@@ -3379,7 +3465,7 @@ function useRoomNotificationSettings() {
3379
3465
  getter,
3380
3466
  getter,
3381
3467
  identity2,
3382
- _client.shallow
3468
+ _client2.shallow
3383
3469
  );
3384
3470
  return React5.useMemo(() => {
3385
3471
  return [settings, updateRoomNotificationSettings];
@@ -3389,7 +3475,7 @@ function useRoomNotificationSettingsSuspense() {
3389
3475
  const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
3390
3476
  const client = useClient();
3391
3477
  const room = useRoom();
3392
- const { store } = getExtrasForClient2(client);
3478
+ const { store } = getRoomExtrasForClient(client);
3393
3479
  const getter = React5.useCallback(
3394
3480
  () => store.getNotificationSettingsAsync(room.id),
3395
3481
  [store, room.id]
@@ -3399,10 +3485,10 @@ function useRoomNotificationSettingsSuspense() {
3399
3485
  getter,
3400
3486
  getter,
3401
3487
  identity2,
3402
- _client.shallow
3488
+ _client2.shallow
3403
3489
  );
3404
3490
  if (settings.isLoading) {
3405
- const { getInboxNotificationSettings } = getExtrasForClient2(client);
3491
+ const { getInboxNotificationSettings } = getRoomExtrasForClient(client);
3406
3492
  throw getInboxNotificationSettings(room);
3407
3493
  } else if (settings.error) {
3408
3494
  throw settings.error;
@@ -3443,7 +3529,7 @@ function useHistoryVersionData(versionId) {
3443
3529
  function useHistoryVersions() {
3444
3530
  const client = useClient();
3445
3531
  const room = useRoom();
3446
- const { store, getRoomVersions } = getExtrasForClient2(client);
3532
+ const { store, getRoomVersions } = getRoomExtrasForClient(client);
3447
3533
  const getter = React5.useCallback(
3448
3534
  () => store.getVersionsAsync(room.id),
3449
3535
  [store, room.id]
@@ -3456,14 +3542,14 @@ function useHistoryVersions() {
3456
3542
  getter,
3457
3543
  getter,
3458
3544
  identity2,
3459
- _client.shallow
3545
+ _client2.shallow
3460
3546
  );
3461
3547
  return state;
3462
3548
  }
3463
3549
  function useHistoryVersionsSuspense() {
3464
3550
  const client = useClient();
3465
3551
  const room = useRoom();
3466
- const { store } = getExtrasForClient2(client);
3552
+ const { store } = getRoomExtrasForClient(client);
3467
3553
  const getter = React5.useCallback(
3468
3554
  () => store.getVersionsAsync(room.id),
3469
3555
  [store, room.id]
@@ -3473,10 +3559,10 @@ function useHistoryVersionsSuspense() {
3473
3559
  getter,
3474
3560
  getter,
3475
3561
  identity2,
3476
- _client.shallow
3562
+ _client2.shallow
3477
3563
  );
3478
3564
  if (state.isLoading) {
3479
- const { getRoomVersions } = getExtrasForClient2(client);
3565
+ const { getRoomVersions } = getRoomExtrasForClient(client);
3480
3566
  throw getRoomVersions(room);
3481
3567
  } else if (state.error) {
3482
3568
  throw state.error;
@@ -3488,7 +3574,7 @@ function useUpdateRoomNotificationSettings() {
3488
3574
  const room = useRoom();
3489
3575
  return React5.useCallback(
3490
3576
  (settings) => {
3491
- const { store, onMutationFailure } = getExtrasForClient2(client);
3577
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3492
3578
  const optimisticUpdateId = store.addOptimisticUpdate({
3493
3579
  type: "update-notification-settings",
3494
3580
  roomId: room.id,
@@ -3571,50 +3657,17 @@ function useStorageStatusSuspense(options) {
3571
3657
  function useThreadsSuspense(options = {
3572
3658
  query: { metadata: {} }
3573
3659
  }) {
3574
- const { scrollOnLoad = true } = options;
3575
3660
  const client = useClient();
3576
3661
  const room = useRoom();
3577
- const queryKey = React5.useMemo(
3578
- () => generateQueryKey(room.id, options.query),
3579
- [room, options]
3580
- );
3581
- const { store, getThreadsAndInboxNotifications } = getExtrasForClient2(client);
3582
- const query = store.getFullState().queries2[queryKey];
3583
- if (query === void 0 || query.isLoading) {
3584
- throw getThreadsAndInboxNotifications(room, queryKey, options);
3585
- }
3586
- if (query.error) {
3587
- throw query.error;
3588
- }
3589
- const selector = React5.useCallback(
3590
- (state2) => {
3591
- return {
3592
- threads: selectThreads(state2, {
3593
- roomId: room.id,
3594
- query: options.query,
3595
- orderBy: "age"
3596
- }),
3597
- isLoading: false
3598
- };
3599
- },
3600
- [room, queryKey]
3601
- // eslint-disable-line react-hooks/exhaustive-deps
3602
- );
3603
- React5.useEffect(() => {
3604
- const { incrementQuerySubscribers } = getExtrasForClient2(client);
3605
- return incrementQuerySubscribers(queryKey);
3606
- }, [client, queryKey]);
3607
- const state = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
3608
- store.subscribeThreads,
3609
- store.getFullState,
3610
- store.getFullState,
3611
- selector
3612
- );
3613
- useScrollToCommentOnLoadEffect(scrollOnLoad, state);
3614
- return state;
3662
+ const { store } = getRoomExtrasForClient(client);
3663
+ use(store.waitUntilRoomThreadsLoaded(room.id, options.query));
3664
+ const result = useThreads(options);
3665
+ _core.assert.call(void 0, !result.error, "Did not expect error");
3666
+ _core.assert.call(void 0, !result.isLoading, "Did not expect loading");
3667
+ return result;
3615
3668
  }
3616
3669
  function selectorFor_useAttachmentUrl(state) {
3617
- if (state === void 0 || _optionalChain([state, 'optionalAccess', _34 => _34.isLoading])) {
3670
+ if (state === void 0 || _optionalChain([state, 'optionalAccess', _37 => _37.isLoading])) {
3618
3671
  return _nullishCoalesce(state, () => ( { isLoading: true }));
3619
3672
  }
3620
3673
  if (state.error) {
@@ -3641,7 +3694,7 @@ function useAttachmentUrl(attachmentId) {
3641
3694
  getAttachmentUrlState,
3642
3695
  getAttachmentUrlState,
3643
3696
  selectorFor_useAttachmentUrl,
3644
- _client.shallow
3697
+ _client2.shallow
3645
3698
  );
3646
3699
  }
3647
3700
  function useAttachmentUrlSuspense(attachmentId) {
@@ -3675,9 +3728,6 @@ function useAttachmentUrlSuspense(attachmentId) {
3675
3728
  function createRoomContext(client) {
3676
3729
  return getOrCreateRoomContextBundle(client);
3677
3730
  }
3678
- function generateQueryKey(roomId, options) {
3679
- return `${roomId}-${_core.stringify.call(void 0, _nullishCoalesce(options, () => ( {})))}`;
3680
- }
3681
3731
  var _RoomProvider = RoomProvider;
3682
3732
  var _useBroadcastEvent = useBroadcastEvent;
3683
3733
  var _useOthersListener = useOthersListener;
@@ -3799,5 +3849,5 @@ var _useUpdateMyPresence = useUpdateMyPresence;
3799
3849
 
3800
3850
 
3801
3851
 
3802
- exports.PKG_NAME = PKG_NAME; exports.PKG_VERSION = PKG_VERSION; exports.PKG_FORMAT = PKG_FORMAT; exports.ClientSideSuspense = ClientSideSuspense; exports.RoomContext = RoomContext; exports.ClientContext = ClientContext; exports.selectThreads = selectThreads; exports.getUmbrellaStoreForClient = getUmbrellaStoreForClient; 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.CreateThreadError = CreateThreadError; exports.useStatus = useStatus; 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.useCreateComment = useCreateComment; exports.useEditComment = useEditComment; exports.useDeleteComment = useDeleteComment; exports.useRemoveReaction = useRemoveReaction; exports.useMarkThreadAsRead = useMarkThreadAsRead; exports.useMarkThreadAsResolved = useMarkThreadAsResolved; exports.useMarkThreadAsUnresolved = useMarkThreadAsUnresolved; exports.useThreadSubscription = useThreadSubscription; exports.useRoomNotificationSettings = useRoomNotificationSettings; exports.useHistoryVersionData = useHistoryVersionData; exports.useUpdateRoomNotificationSettings = useUpdateRoomNotificationSettings; exports.useOthersConnectionIdsSuspense = useOthersConnectionIdsSuspense; exports.useStorageStatusSuspense = useStorageStatusSuspense; exports.useAttachmentUrl = useAttachmentUrl; exports.useAttachmentUrlSuspense = useAttachmentUrlSuspense; 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._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;
3803
- //# sourceMappingURL=chunk-3DYM4PT5.js.map
3852
+ exports.PKG_NAME = PKG_NAME; exports.PKG_VERSION = PKG_VERSION; exports.PKG_FORMAT = PKG_FORMAT; exports.ClientSideSuspense = ClientSideSuspense; exports.RoomContext = RoomContext; exports.selectThreads = selectThreads; exports.ClientContext = ClientContext; exports.getUmbrellaStoreForClient = getUmbrellaStoreForClient; 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.CreateThreadError = CreateThreadError; exports.useStatus = useStatus; 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.useCreateComment = useCreateComment; exports.useEditComment = useEditComment; exports.useDeleteComment = useDeleteComment; exports.useRemoveReaction = useRemoveReaction; exports.useMarkThreadAsRead = useMarkThreadAsRead; exports.useMarkThreadAsResolved = useMarkThreadAsResolved; exports.useMarkThreadAsUnresolved = useMarkThreadAsUnresolved; exports.useThreadSubscription = useThreadSubscription; exports.useRoomNotificationSettings = useRoomNotificationSettings; exports.useHistoryVersionData = useHistoryVersionData; exports.useUpdateRoomNotificationSettings = useUpdateRoomNotificationSettings; exports.useOthersConnectionIdsSuspense = useOthersConnectionIdsSuspense; exports.useStorageStatusSuspense = useStorageStatusSuspense; exports.useAttachmentUrl = useAttachmentUrl; exports.useAttachmentUrlSuspense = useAttachmentUrlSuspense; 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._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;
3853
+ //# sourceMappingURL=chunk-7P6EIISH.js.map