@liveblocks/react 2.7.0 → 2.8.0-beta1

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,10 +1,10 @@
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.7.0";
3
+ var PKG_VERSION = "2.8.0-beta1";
4
4
  var PKG_FORMAT = "cjs";
5
5
 
6
6
  // src/ClientSideSuspense.tsx
7
- var _react = require('react'); var React = _interopRequireWildcard(_react); var React4 = _interopRequireWildcard(_react); var React3 = _interopRequireWildcard(_react);
7
+ var _react = require('react'); var React = _interopRequireWildcard(_react); var React2 = _interopRequireWildcard(_react); var React5 = _interopRequireWildcard(_react); var React4 = _interopRequireWildcard(_react);
8
8
  function ClientSideSuspense(props) {
9
9
  const [mounted, setMounted] = React.useState(false);
10
10
  React.useEffect(() => {
@@ -13,107 +13,18 @@ function ClientSideSuspense(props) {
13
13
  return /* @__PURE__ */ React.createElement(React.Suspense, { fallback: props.fallback }, mounted ? typeof props.children === "function" ? props.children() : props.children : props.fallback);
14
14
  }
15
15
 
16
- // src/comments/errors.ts
17
- var CreateThreadError = class extends Error {
18
- constructor(cause, context) {
19
- super("Create thread failed.");
20
- this.cause = cause;
21
- this.context = context;
22
- this.name = "CreateThreadError";
23
- }
24
- };
25
- var DeleteThreadError = class extends Error {
26
- constructor(cause, context) {
27
- super("Delete thread failed.");
28
- this.cause = cause;
29
- this.context = context;
30
- this.name = "DeleteThreadError";
31
- }
32
- };
33
- var EditThreadMetadataError = class extends Error {
34
- constructor(cause, context) {
35
- super("Edit thread metadata failed.");
36
- this.cause = cause;
37
- this.context = context;
38
- this.name = "EditThreadMetadataError";
39
- }
40
- };
41
- var MarkThreadAsResolvedError = class extends Error {
42
- constructor(cause, context) {
43
- super("Mark thread as resolved failed.");
44
- this.cause = cause;
45
- this.context = context;
46
- this.name = "MarkThreadAsResolvedError";
47
- }
48
- };
49
- var MarkThreadAsUnresolvedError = class extends Error {
50
- constructor(cause, context) {
51
- super("Mark thread as unresolved failed.");
52
- this.cause = cause;
53
- this.context = context;
54
- this.name = "MarkThreadAsUnresolvedError";
55
- }
56
- };
57
- var CreateCommentError = class extends Error {
58
- constructor(cause, context) {
59
- super("Create comment failed.");
60
- this.cause = cause;
61
- this.context = context;
62
- this.name = "CreateCommentError";
63
- }
64
- };
65
- var EditCommentError = class extends Error {
66
- constructor(cause, context) {
67
- super("Edit comment failed.");
68
- this.cause = cause;
69
- this.context = context;
70
- this.name = "EditCommentError";
71
- }
72
- };
73
- var DeleteCommentError = class extends Error {
74
- constructor(cause, context) {
75
- super("Delete comment failed.");
76
- this.cause = cause;
77
- this.context = context;
78
- this.name = "DeleteCommentError";
79
- }
80
- };
81
- var AddReactionError = class extends Error {
82
- constructor(cause, context) {
83
- super("Add reaction failed.");
84
- this.cause = cause;
85
- this.context = context;
86
- this.name = "AddReactionError";
87
- }
88
- };
89
- var RemoveReactionError = class extends Error {
90
- constructor(cause, context) {
91
- super("Remove reaction failed.");
92
- this.cause = cause;
93
- this.context = context;
94
- this.name = "RemoveReactionError";
95
- }
96
- };
97
- var MarkInboxNotificationAsReadError = class extends Error {
98
- constructor(cause, context) {
99
- super("Mark inbox notification as read failed.");
100
- this.cause = cause;
101
- this.context = context;
102
- this.name = "MarkInboxNotificationAsReadError";
103
- }
104
- };
105
- var UpdateNotificationSettingsError = class extends Error {
106
- constructor(cause, context) {
107
- super("Update notification settings failed.");
108
- this.cause = cause;
109
- this.context = context;
110
- this.name = "UpdateNotificationSettingsError";
111
- }
112
- };
16
+ // src/contexts.ts
113
17
 
114
- // src/room.tsx
115
- var _client = require('@liveblocks/client');
18
+ var RoomContext = React2.createContext(null);
19
+ function useRoomOrNull() {
20
+ return React2.useContext(RoomContext);
21
+ }
22
+ function useIsInsideRoom() {
23
+ const room = useRoomOrNull();
24
+ return room !== null;
25
+ }
116
26
 
27
+ // src/liveblocks.tsx
117
28
 
118
29
 
119
30
 
@@ -123,12 +34,15 @@ var _client = require('@liveblocks/client');
123
34
 
124
35
 
125
36
 
37
+ var _core = require('@liveblocks/core');
126
38
 
127
39
 
128
40
 
129
41
 
130
- var _core = require('@liveblocks/core');
131
42
 
43
+
44
+
45
+ var _indexjs = require('use-sync-external-store/shim/index.js');
132
46
  var _withselectorjs = require('use-sync-external-store/shim/with-selector.js');
133
47
 
134
48
  // src/lib/compare.ts
@@ -204,6 +118,21 @@ async function autoRetry(promiseFn, maxTries, backoff) {
204
118
  }
205
119
  }
206
120
 
121
+ // src/lib/shallow2.ts
122
+
123
+ function shallow2(a, b) {
124
+ if (!_core.isPlainObject.call(void 0, a) || !_core.isPlainObject.call(void 0, b)) {
125
+ return _core.shallow.call(void 0, a, b);
126
+ }
127
+ const keysA = Object.keys(a);
128
+ if (keysA.length !== Object.keys(b).length) {
129
+ return false;
130
+ }
131
+ return keysA.every(
132
+ (key) => Object.prototype.hasOwnProperty.call(b, key) && _core.shallow.call(void 0, a[key], b[key])
133
+ );
134
+ }
135
+
207
136
  // src/lib/use-initial.ts
208
137
 
209
138
 
@@ -261,66 +190,102 @@ var use = (
261
190
  }
262
191
  );
263
192
 
264
- // src/liveblocks.tsx
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
193
+ // src/umbrella-store.ts
278
194
 
279
195
 
280
196
 
281
197
 
282
- var _indexjs = require('use-sync-external-store/shim/index.js');
283
198
 
284
199
 
285
- // src/umbrella-store.ts
286
200
 
287
201
  var UmbrellaStore = class {
288
202
  constructor() {
203
+ this._prevState = null;
204
+ this._stateCached = null;
289
205
  this._store = _core.createStore.call(void 0, {
290
- threads: {},
206
+ rawThreadsById: {},
291
207
  queries: {},
292
208
  optimisticUpdates: [],
293
- inboxNotifications: {},
294
- notificationSettings: {},
295
- versions: {}
209
+ inboxNotificationsById: {},
210
+ notificationSettingsByRoomId: {},
211
+ versionsByRoomId: {}
296
212
  });
297
- this.get = this.get.bind(this);
298
- this.subscribe = this.subscribe.bind(this);
213
+ this.getThreads = this.getThreads.bind(this);
214
+ this.getInboxNotifications = this.getInboxNotifications.bind(this);
215
+ this.getNotificationSettings = this.getNotificationSettings.bind(this);
216
+ this.getVersions = this.getVersions.bind(this);
217
+ this.subscribeThreads = this.subscribeThreads.bind(this);
218
+ this.subscribeInboxNotifications = this.subscribeInboxNotifications.bind(this);
219
+ this.subscribeNotificationSettings = this.subscribeNotificationSettings.bind(this);
220
+ this.subscribeVersions = this.subscribeVersions.bind(this);
221
+ this._hasOptimisticUpdates = this._hasOptimisticUpdates.bind(this);
222
+ this._subscribeOptimisticUpdates = this._subscribeOptimisticUpdates.bind(this);
299
223
  }
300
224
  get() {
301
- return this._store.get();
225
+ const rawState = this._store.get();
226
+ if (this._prevState !== rawState || this._stateCached === null) {
227
+ this._prevState = rawState;
228
+ this._stateCached = applyOptimisticUpdates(rawState);
229
+ }
230
+ return this._stateCached;
231
+ }
232
+ getThreads() {
233
+ return this.get();
234
+ }
235
+ getInboxNotifications() {
236
+ return this.get();
237
+ }
238
+ getNotificationSettings() {
239
+ return this.get();
240
+ }
241
+ getVersions() {
242
+ return this.get();
243
+ }
244
+ /**
245
+ * @private Only used by the E2E test suite.
246
+ */
247
+ _hasOptimisticUpdates() {
248
+ return this._store.get().optimisticUpdates.length > 0;
302
249
  }
303
250
  subscribe(callback) {
304
251
  return this._store.subscribe(callback);
305
252
  }
253
+ /**
254
+ * @private Only used by the E2E test suite.
255
+ */
256
+ _subscribeOptimisticUpdates(callback) {
257
+ return this.subscribe(callback);
258
+ }
259
+ subscribeThreads(callback) {
260
+ return this.subscribe(callback);
261
+ }
262
+ subscribeInboxNotifications(callback) {
263
+ return this.subscribe(callback);
264
+ }
265
+ subscribeNotificationSettings(callback) {
266
+ return this.subscribe(callback);
267
+ }
268
+ subscribeVersions(callback) {
269
+ return this.subscribe(callback);
270
+ }
306
271
  // Direct low-level cache mutations ------------------------------------------------- {{{
307
272
  updateThreadsCache(mapFn) {
308
273
  this._store.set((state) => {
309
- const threads = mapFn(state.threads);
310
- return threads !== state.threads ? { ...state, threads } : state;
274
+ const threads = mapFn(state.rawThreadsById);
275
+ return threads !== state.rawThreadsById ? { ...state, rawThreadsById: threads } : state;
311
276
  });
312
277
  }
313
278
  updateInboxNotificationsCache(mapFn) {
314
279
  this._store.set((state) => {
315
- const inboxNotifications = mapFn(state.inboxNotifications);
316
- return inboxNotifications !== state.inboxNotifications ? { ...state, inboxNotifications } : state;
280
+ const inboxNotifications = mapFn(state.inboxNotificationsById);
281
+ return inboxNotifications !== state.inboxNotificationsById ? { ...state, inboxNotificationsById: inboxNotifications } : state;
317
282
  });
318
283
  }
319
284
  setNotificationSettings(roomId, settings) {
320
285
  this._store.set((state) => ({
321
286
  ...state,
322
- notificationSettings: {
323
- ...state.notificationSettings,
287
+ notificationSettingsByRoomId: {
288
+ ...state.notificationSettingsByRoomId,
324
289
  [roomId]: settings
325
290
  }
326
291
  }));
@@ -328,8 +293,8 @@ var UmbrellaStore = class {
328
293
  setVersions(roomId, versions) {
329
294
  this._store.set((state) => ({
330
295
  ...state,
331
- versions: {
332
- ...state.versions,
296
+ versionsByRoomId: {
297
+ ...state.versionsByRoomId,
333
298
  [roomId]: versions
334
299
  }
335
300
  }));
@@ -449,6 +414,30 @@ var UmbrellaStore = class {
449
414
  });
450
415
  });
451
416
  }
417
+ patchThread(threadId, optimisticUpdateId, patch, updatedAt) {
418
+ return this.updateThread(
419
+ threadId,
420
+ optimisticUpdateId,
421
+ (thread) => ({ ...thread, ..._core.compactObject.call(void 0, patch) }),
422
+ updatedAt
423
+ );
424
+ }
425
+ addReaction(threadId, optimisticUpdateId, commentId, reaction, createdAt) {
426
+ this.updateThread(
427
+ threadId,
428
+ optimisticUpdateId,
429
+ (thread) => applyAddReaction(thread, commentId, reaction),
430
+ createdAt
431
+ );
432
+ }
433
+ removeReaction(threadId, optimisticUpdateId, commentId, emoji, userId, removedAt) {
434
+ this.updateThread(
435
+ threadId,
436
+ optimisticUpdateId,
437
+ (thread) => applyRemoveReaction(thread, commentId, emoji, userId, removedAt),
438
+ removedAt
439
+ );
440
+ }
452
441
  /**
453
442
  * Soft-deletes an existing thread by setting its `deletedAt` value,
454
443
  * replacing the corresponding optimistic update.
@@ -472,13 +461,13 @@ var UmbrellaStore = class {
472
461
  createComment(newComment, optimisticUpdateId) {
473
462
  this._store.batch(() => {
474
463
  this.removeOptimisticUpdate(optimisticUpdateId);
475
- const existingThread = this._store.get().threads[newComment.threadId];
464
+ const existingThread = this._store.get().rawThreadsById[newComment.threadId];
476
465
  if (!existingThread) {
477
466
  return;
478
467
  }
479
468
  this.updateThreadsCache((cache) => ({
480
469
  ...cache,
481
- [newComment.threadId]: upsertComment(existingThread, newComment)
470
+ [newComment.threadId]: applyUpsertComment(existingThread, newComment)
482
471
  }));
483
472
  this.updateInboxNotificationsCache((cache) => {
484
473
  const existingNotification = Object.values(cache).find(
@@ -498,6 +487,21 @@ var UmbrellaStore = class {
498
487
  });
499
488
  });
500
489
  }
490
+ editComment(threadId, optimisticUpdateId, editedComment) {
491
+ return this.updateThread(
492
+ threadId,
493
+ optimisticUpdateId,
494
+ (thread) => applyUpsertComment(thread, editedComment)
495
+ );
496
+ }
497
+ deleteComment(threadId, optimisticUpdateId, commentId, deletedAt) {
498
+ return this.updateThread(
499
+ threadId,
500
+ optimisticUpdateId,
501
+ (thread) => applyDeleteComment(thread, commentId, deletedAt),
502
+ deletedAt
503
+ );
504
+ }
501
505
  updateThreadAndNotification(thread, inboxNotification) {
502
506
  this._store.batch(() => {
503
507
  this.updateThreadsCache((cache) => {
@@ -580,25 +584,19 @@ var UmbrellaStore = class {
580
584
  }
581
585
  };
582
586
  function applyOptimisticUpdates(state) {
583
- const result = {
584
- threads: {
585
- ...state.threads
586
- },
587
- inboxNotifications: {
588
- ...state.inboxNotifications
589
- },
590
- notificationSettings: {
591
- ...state.notificationSettings
592
- }
587
+ const output = {
588
+ threads: { ...state.rawThreadsById },
589
+ inboxNotifications: { ...state.inboxNotificationsById },
590
+ notificationSettings: { ...state.notificationSettingsByRoomId }
593
591
  };
594
592
  for (const optimisticUpdate of state.optimisticUpdates) {
595
593
  switch (optimisticUpdate.type) {
596
594
  case "create-thread": {
597
- result.threads[optimisticUpdate.thread.id] = optimisticUpdate.thread;
595
+ output.threads[optimisticUpdate.thread.id] = optimisticUpdate.thread;
598
596
  break;
599
597
  }
600
598
  case "edit-thread-metadata": {
601
- const thread = result.threads[optimisticUpdate.threadId];
599
+ const thread = output.threads[optimisticUpdate.threadId];
602
600
  if (thread === void 0) {
603
601
  break;
604
602
  }
@@ -608,7 +606,7 @@ function applyOptimisticUpdates(state) {
608
606
  if (thread.updatedAt !== void 0 && thread.updatedAt > optimisticUpdate.updatedAt) {
609
607
  break;
610
608
  }
611
- result.threads[thread.id] = {
609
+ output.threads[thread.id] = {
612
610
  ...thread,
613
611
  updatedAt: optimisticUpdate.updatedAt,
614
612
  metadata: {
@@ -619,49 +617,49 @@ function applyOptimisticUpdates(state) {
619
617
  break;
620
618
  }
621
619
  case "mark-thread-as-resolved": {
622
- const thread = result.threads[optimisticUpdate.threadId];
620
+ const thread = output.threads[optimisticUpdate.threadId];
623
621
  if (thread === void 0) {
624
622
  break;
625
623
  }
626
624
  if (thread.deletedAt !== void 0) {
627
625
  break;
628
626
  }
629
- result.threads[thread.id] = {
627
+ output.threads[thread.id] = {
630
628
  ...thread,
631
629
  resolved: true
632
630
  };
633
631
  break;
634
632
  }
635
633
  case "mark-thread-as-unresolved": {
636
- const thread = result.threads[optimisticUpdate.threadId];
634
+ const thread = output.threads[optimisticUpdate.threadId];
637
635
  if (thread === void 0) {
638
636
  break;
639
637
  }
640
638
  if (thread.deletedAt !== void 0) {
641
639
  break;
642
640
  }
643
- result.threads[thread.id] = {
641
+ output.threads[thread.id] = {
644
642
  ...thread,
645
643
  resolved: false
646
644
  };
647
645
  break;
648
646
  }
649
647
  case "create-comment": {
650
- const thread = result.threads[optimisticUpdate.comment.threadId];
648
+ const thread = output.threads[optimisticUpdate.comment.threadId];
651
649
  if (thread === void 0) {
652
650
  break;
653
651
  }
654
- result.threads[thread.id] = upsertComment(
652
+ output.threads[thread.id] = applyUpsertComment(
655
653
  thread,
656
654
  optimisticUpdate.comment
657
655
  );
658
- const inboxNotification = Object.values(result.inboxNotifications).find(
656
+ const inboxNotification = Object.values(output.inboxNotifications).find(
659
657
  (notification) => notification.kind === "thread" && notification.threadId === thread.id
660
658
  );
661
659
  if (inboxNotification === void 0) {
662
660
  break;
663
661
  }
664
- result.inboxNotifications[inboxNotification.id] = {
662
+ output.inboxNotifications[inboxNotification.id] = {
665
663
  ...inboxNotification,
666
664
  notifiedAt: optimisticUpdate.comment.createdAt,
667
665
  readAt: optimisticUpdate.comment.createdAt
@@ -669,22 +667,22 @@ function applyOptimisticUpdates(state) {
669
667
  break;
670
668
  }
671
669
  case "edit-comment": {
672
- const thread = result.threads[optimisticUpdate.comment.threadId];
670
+ const thread = output.threads[optimisticUpdate.comment.threadId];
673
671
  if (thread === void 0) {
674
672
  break;
675
673
  }
676
- result.threads[thread.id] = upsertComment(
674
+ output.threads[thread.id] = applyUpsertComment(
677
675
  thread,
678
676
  optimisticUpdate.comment
679
677
  );
680
678
  break;
681
679
  }
682
680
  case "delete-comment": {
683
- const thread = result.threads[optimisticUpdate.threadId];
681
+ const thread = output.threads[optimisticUpdate.threadId];
684
682
  if (thread === void 0) {
685
683
  break;
686
684
  }
687
- result.threads[thread.id] = deleteComment(
685
+ output.threads[thread.id] = applyDeleteComment(
688
686
  thread,
689
687
  optimisticUpdate.commentId,
690
688
  optimisticUpdate.deletedAt
@@ -692,12 +690,12 @@ function applyOptimisticUpdates(state) {
692
690
  break;
693
691
  }
694
692
  case "delete-thread": {
695
- const thread = result.threads[optimisticUpdate.threadId];
693
+ const thread = output.threads[optimisticUpdate.threadId];
696
694
  if (thread === void 0) {
697
695
  break;
698
696
  }
699
- result.threads[optimisticUpdate.threadId] = {
700
- ...result.threads[optimisticUpdate.threadId],
697
+ output.threads[optimisticUpdate.threadId] = {
698
+ ...output.threads[optimisticUpdate.threadId],
701
699
  deletedAt: optimisticUpdate.deletedAt,
702
700
  updatedAt: optimisticUpdate.deletedAt,
703
701
  comments: []
@@ -705,11 +703,11 @@ function applyOptimisticUpdates(state) {
705
703
  break;
706
704
  }
707
705
  case "add-reaction": {
708
- const thread = result.threads[optimisticUpdate.threadId];
706
+ const thread = output.threads[optimisticUpdate.threadId];
709
707
  if (thread === void 0) {
710
708
  break;
711
709
  }
712
- result.threads[thread.id] = addReaction(
710
+ output.threads[thread.id] = applyAddReaction(
713
711
  thread,
714
712
  optimisticUpdate.commentId,
715
713
  optimisticUpdate.reaction
@@ -717,11 +715,11 @@ function applyOptimisticUpdates(state) {
717
715
  break;
718
716
  }
719
717
  case "remove-reaction": {
720
- const thread = result.threads[optimisticUpdate.threadId];
718
+ const thread = output.threads[optimisticUpdate.threadId];
721
719
  if (thread === void 0) {
722
720
  break;
723
721
  }
724
- result.threads[thread.id] = removeReaction(
722
+ output.threads[thread.id] = applyRemoveReaction(
725
723
  thread,
726
724
  optimisticUpdate.commentId,
727
725
  optimisticUpdate.emoji,
@@ -731,16 +729,16 @@ function applyOptimisticUpdates(state) {
731
729
  break;
732
730
  }
733
731
  case "mark-inbox-notification-as-read": {
734
- result.inboxNotifications[optimisticUpdate.inboxNotificationId] = {
735
- ...state.inboxNotifications[optimisticUpdate.inboxNotificationId],
732
+ output.inboxNotifications[optimisticUpdate.inboxNotificationId] = {
733
+ ...state.inboxNotificationsById[optimisticUpdate.inboxNotificationId],
736
734
  readAt: optimisticUpdate.readAt
737
735
  };
738
736
  break;
739
737
  }
740
738
  case "mark-all-inbox-notifications-as-read": {
741
- for (const id in result.inboxNotifications) {
742
- result.inboxNotifications[id] = {
743
- ...result.inboxNotifications[id],
739
+ for (const id in output.inboxNotifications) {
740
+ output.inboxNotifications[id] = {
741
+ ...output.inboxNotifications[id],
744
742
  readAt: optimisticUpdate.readAt
745
743
  };
746
744
  }
@@ -750,23 +748,43 @@ function applyOptimisticUpdates(state) {
750
748
  const {
751
749
  [optimisticUpdate.inboxNotificationId]: _,
752
750
  ...inboxNotifications
753
- } = result.inboxNotifications;
754
- result.inboxNotifications = inboxNotifications;
751
+ } = output.inboxNotifications;
752
+ output.inboxNotifications = inboxNotifications;
755
753
  break;
756
754
  }
757
755
  case "delete-all-inbox-notifications": {
758
- result.inboxNotifications = {};
756
+ output.inboxNotifications = {};
759
757
  break;
760
758
  }
761
759
  case "update-notification-settings": {
762
- result.notificationSettings[optimisticUpdate.roomId] = {
763
- ...result.notificationSettings[optimisticUpdate.roomId],
760
+ output.notificationSettings[optimisticUpdate.roomId] = {
761
+ ...output.notificationSettings[optimisticUpdate.roomId],
764
762
  ...optimisticUpdate.settings
765
763
  };
766
764
  }
767
765
  }
768
766
  }
769
- return result;
767
+ const cleanedThreads = (
768
+ // Don't expose any soft-deleted threads
769
+ Object.values(output.threads).filter(
770
+ (thread) => !thread.deletedAt
771
+ )
772
+ );
773
+ const cleanedNotifications = (
774
+ // Sort so that the most recent notifications are first
775
+ Object.values(output.inboxNotifications).sort(
776
+ (a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime()
777
+ )
778
+ );
779
+ return {
780
+ inboxNotifications: cleanedNotifications,
781
+ inboxNotificationsById: output.inboxNotifications,
782
+ notificationSettingsByRoomId: output.notificationSettings,
783
+ queries: state.queries,
784
+ threads: cleanedThreads,
785
+ threadsById: output.threads,
786
+ versionsByRoomId: state.versionsByRoomId
787
+ };
770
788
  }
771
789
  function applyThreadUpdates(existingThreads, updates) {
772
790
  const updatedThreads = { ...existingThreads };
@@ -819,7 +837,7 @@ function compareInboxNotifications(inboxNotificationA, inboxNotificationB) {
819
837
  }
820
838
  return 0;
821
839
  }
822
- function upsertComment(thread, comment) {
840
+ function applyUpsertComment(thread, comment) {
823
841
  if (thread.deletedAt !== void 0) {
824
842
  return thread;
825
843
  }
@@ -864,7 +882,7 @@ function upsertComment(thread, comment) {
864
882
  }
865
883
  return thread;
866
884
  }
867
- function deleteComment(thread, commentId, deletedAt) {
885
+ function applyDeleteComment(thread, commentId, deletedAt) {
868
886
  if (thread.deletedAt !== void 0) {
869
887
  return thread;
870
888
  }
@@ -881,7 +899,8 @@ function deleteComment(thread, commentId, deletedAt) {
881
899
  (comment) => comment.id === commentId ? {
882
900
  ...comment,
883
901
  deletedAt,
884
- body: void 0
902
+ body: void 0,
903
+ attachments: []
885
904
  } : comment
886
905
  );
887
906
  if (!updatedComments.some((comment) => comment.deletedAt === void 0)) {
@@ -898,7 +917,7 @@ function deleteComment(thread, commentId, deletedAt) {
898
917
  comments: updatedComments
899
918
  };
900
919
  }
901
- function addReaction(thread, commentId, reaction) {
920
+ function applyAddReaction(thread, commentId, reaction) {
902
921
  if (thread.deletedAt !== void 0) {
903
922
  return thread;
904
923
  }
@@ -925,7 +944,7 @@ function addReaction(thread, commentId, reaction) {
925
944
  comments: updatedComments
926
945
  };
927
946
  }
928
- function removeReaction(thread, commentId, emoji, userId, removedAt) {
947
+ function applyRemoveReaction(thread, commentId, emoji, userId, removedAt) {
929
948
  if (thread.deletedAt !== void 0) {
930
949
  return thread;
931
950
  }
@@ -1013,24 +1032,13 @@ function selectorFor_useInboxNotifications(state) {
1013
1032
  };
1014
1033
  }
1015
1034
  return {
1016
- inboxNotifications: selectInboxNotifications(state),
1035
+ inboxNotifications: state.inboxNotifications,
1017
1036
  isLoading: false
1018
1037
  };
1019
1038
  }
1020
- function selectUserThreads(state, options) {
1021
- const result = applyOptimisticUpdates(state);
1022
- let threads = Object.values(result.threads).filter(
1023
- (thread) => !thread.deletedAt
1024
- );
1025
- const query = options.query;
1026
- if (query) {
1027
- threads = threads.filter(makeThreadsFilter(query));
1028
- }
1029
- return threads.sort(byMostRecentlyUpdated);
1030
- }
1031
1039
  function selectUnreadInboxNotificationsCount(state) {
1032
1040
  let count = 0;
1033
- for (const notification of selectInboxNotifications(state)) {
1041
+ for (const notification of state.inboxNotifications) {
1034
1042
  if (notification.readAt === null || notification.readAt < notification.notifiedAt) {
1035
1043
  count++;
1036
1044
  }
@@ -1091,11 +1099,17 @@ function selectorFor_useRoomInfo(state, roomId) {
1091
1099
  info: state.data
1092
1100
  };
1093
1101
  }
1094
- function selectInboxNotifications(state) {
1095
- const result = applyOptimisticUpdates(state);
1096
- return Object.values(result.inboxNotifications).sort(
1097
- // Sort so that the most recent notifications are first
1098
- (a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime()
1102
+ function selectThreads(state, options) {
1103
+ let threads = state.threads;
1104
+ if (options.roomId !== null) {
1105
+ threads = threads.filter((thread) => thread.roomId === options.roomId);
1106
+ }
1107
+ const query = options.query;
1108
+ if (query) {
1109
+ threads = threads.filter(makeThreadsFilter(query));
1110
+ }
1111
+ return threads.sort(
1112
+ options.orderBy === "last-update" ? byMostRecentlyUpdated : byFirstCreated
1099
1113
  );
1100
1114
  }
1101
1115
  function getOrCreateContextBundle(client) {
@@ -1330,9 +1344,9 @@ function useInboxNotifications_withClient(client) {
1330
1344
  }, [loadInboxNotifications]);
1331
1345
  useEnableInboxNotificationsPolling();
1332
1346
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1333
- store.subscribe,
1334
- store.get,
1335
- store.get,
1347
+ store.subscribeInboxNotifications,
1348
+ store.getInboxNotifications,
1349
+ store.getInboxNotifications,
1336
1350
  selectorFor_useInboxNotifications,
1337
1351
  _core.shallow
1338
1352
  );
@@ -1352,9 +1366,9 @@ function useUnreadInboxNotificationsCount_withClient(client) {
1352
1366
  }, [loadInboxNotifications]);
1353
1367
  useEnableInboxNotificationsPolling();
1354
1368
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1355
- store.subscribe,
1356
- store.get,
1357
- store.get,
1369
+ store.subscribeInboxNotifications,
1370
+ store.getInboxNotifications,
1371
+ store.getInboxNotifications,
1358
1372
  selectorFor_useUnreadInboxNotificationsCount,
1359
1373
  _core.shallow
1360
1374
  );
@@ -1461,13 +1475,13 @@ function useInboxNotificationThread_withClient(client, inboxNotificationId) {
1461
1475
  const { store } = getExtrasForClient(client);
1462
1476
  const selector = _react.useCallback.call(void 0,
1463
1477
  (state) => {
1464
- const inboxNotification = _nullishCoalesce(state.inboxNotifications[inboxNotificationId], () => ( _core.raise.call(void 0, `Inbox notification with ID "${inboxNotificationId}" not found`)));
1478
+ const inboxNotification = _nullishCoalesce(state.inboxNotificationsById[inboxNotificationId], () => ( _core.raise.call(void 0, `Inbox notification with ID "${inboxNotificationId}" not found`)));
1465
1479
  if (inboxNotification.kind !== "thread") {
1466
1480
  _core.raise.call(void 0,
1467
1481
  `Inbox notification with ID "${inboxNotificationId}" is not of kind "thread"`
1468
1482
  );
1469
1483
  }
1470
- const thread = _nullishCoalesce(state.threads[inboxNotification.threadId], () => ( _core.raise.call(void 0,
1484
+ const thread = _nullishCoalesce(state.threadsById[inboxNotification.threadId], () => ( _core.raise.call(void 0,
1471
1485
  `Thread with ID "${inboxNotification.threadId}" not found, this inbox notification might not be of kind "thread"`
1472
1486
  )));
1473
1487
  return thread;
@@ -1475,9 +1489,9 @@ function useInboxNotificationThread_withClient(client, inboxNotificationId) {
1475
1489
  [inboxNotificationId]
1476
1490
  );
1477
1491
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1478
- store.subscribe,
1479
- store.get,
1480
- store.get,
1492
+ store.subscribeInboxNotifications,
1493
+ store.getInboxNotifications,
1494
+ store.getInboxNotifications,
1481
1495
  selector
1482
1496
  );
1483
1497
  }
@@ -1591,13 +1605,13 @@ function createSharedContext(client) {
1591
1605
  useClient: useClient2,
1592
1606
  useUser: (userId) => useUser_withClient(client, userId),
1593
1607
  useRoomInfo: (roomId) => useRoomInfo_withClient(client, roomId),
1594
- useIsInsideRoom: _useIsInsideRoom
1608
+ useIsInsideRoom
1595
1609
  },
1596
1610
  suspense: {
1597
1611
  useClient: useClient2,
1598
1612
  useUser: (userId) => useUserSuspense_withClient(client, userId),
1599
1613
  useRoomInfo: (roomId) => useRoomInfoSuspense_withClient(client, roomId),
1600
- useIsInsideRoom: _useIsInsideRoom
1614
+ useIsInsideRoom
1601
1615
  }
1602
1616
  };
1603
1617
  }
@@ -1681,18 +1695,24 @@ function useUserThreads_experimental(options = {
1681
1695
  };
1682
1696
  }
1683
1697
  return {
1684
- threads: selectUserThreads(state, options),
1698
+ threads: selectThreads(state, {
1699
+ roomId: null,
1700
+ // Do _not_ filter by roomId
1701
+ query: options.query,
1702
+ orderBy: "last-update"
1703
+ }),
1685
1704
  isLoading: false
1686
1705
  };
1687
1706
  },
1688
1707
  [queryKey, options]
1689
1708
  );
1690
1709
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1691
- store.subscribe,
1692
- store.get,
1693
- store.get,
1710
+ store.subscribeThreads,
1711
+ store.getThreads,
1712
+ store.getThreads,
1694
1713
  selector,
1695
- _core.shallow
1714
+ shallow2
1715
+ // NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
1696
1716
  );
1697
1717
  }
1698
1718
  function useUserThreadsSuspense_experimental(options = {
@@ -1710,7 +1730,7 @@ function useUserThreadsSuspense_experimental(options = {
1710
1730
  const { incrementUserThreadsQuerySubscribers } = getExtrasForClient(client);
1711
1731
  return incrementUserThreadsQuerySubscribers(queryKey);
1712
1732
  }, [client, queryKey]);
1713
- const query = store.get().queries[queryKey];
1733
+ const query = store.getThreads().queries[queryKey];
1714
1734
  if (query === void 0 || query.isLoading) {
1715
1735
  throw getUserThreads(queryKey, options);
1716
1736
  }
@@ -1720,18 +1740,24 @@ function useUserThreadsSuspense_experimental(options = {
1720
1740
  const selector = _react.useCallback.call(void 0,
1721
1741
  (state) => {
1722
1742
  return {
1723
- threads: selectUserThreads(state, options),
1743
+ threads: selectThreads(state, {
1744
+ roomId: null,
1745
+ // Do _not_ filter by roomId
1746
+ query: options.query,
1747
+ orderBy: "last-update"
1748
+ }),
1724
1749
  isLoading: false
1725
1750
  };
1726
1751
  },
1727
1752
  [options]
1728
1753
  );
1729
1754
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1730
- store.subscribe,
1731
- store.get,
1732
- store.get,
1755
+ store.subscribeThreads,
1756
+ store.getThreads,
1757
+ store.getThreads,
1733
1758
  selector,
1734
- _core.shallow
1759
+ shallow2
1760
+ // NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
1735
1761
  );
1736
1762
  }
1737
1763
  function useInboxNotifications() {
@@ -1785,6 +1811,125 @@ var _useUserThreads_experimental = useUserThreads_experimental;
1785
1811
  var _useUserThreadsSuspense_experimental = useUserThreadsSuspense_experimental;
1786
1812
  var makeUserThreadsQueryKey = (options) => `${USER_THREADS_QUERY}:${_core.stringify.call(void 0, options)}`;
1787
1813
 
1814
+ // src/types/errors.ts
1815
+ var CreateThreadError = class extends Error {
1816
+ constructor(cause, context) {
1817
+ super("Create thread failed.");
1818
+ this.cause = cause;
1819
+ this.context = context;
1820
+ this.name = "CreateThreadError";
1821
+ }
1822
+ };
1823
+ var DeleteThreadError = class extends Error {
1824
+ constructor(cause, context) {
1825
+ super("Delete thread failed.");
1826
+ this.cause = cause;
1827
+ this.context = context;
1828
+ this.name = "DeleteThreadError";
1829
+ }
1830
+ };
1831
+ var EditThreadMetadataError = class extends Error {
1832
+ constructor(cause, context) {
1833
+ super("Edit thread metadata failed.");
1834
+ this.cause = cause;
1835
+ this.context = context;
1836
+ this.name = "EditThreadMetadataError";
1837
+ }
1838
+ };
1839
+ var MarkThreadAsResolvedError = class extends Error {
1840
+ constructor(cause, context) {
1841
+ super("Mark thread as resolved failed.");
1842
+ this.cause = cause;
1843
+ this.context = context;
1844
+ this.name = "MarkThreadAsResolvedError";
1845
+ }
1846
+ };
1847
+ var MarkThreadAsUnresolvedError = class extends Error {
1848
+ constructor(cause, context) {
1849
+ super("Mark thread as unresolved failed.");
1850
+ this.cause = cause;
1851
+ this.context = context;
1852
+ this.name = "MarkThreadAsUnresolvedError";
1853
+ }
1854
+ };
1855
+ var CreateCommentError = class extends Error {
1856
+ constructor(cause, context) {
1857
+ super("Create comment failed.");
1858
+ this.cause = cause;
1859
+ this.context = context;
1860
+ this.name = "CreateCommentError";
1861
+ }
1862
+ };
1863
+ var EditCommentError = class extends Error {
1864
+ constructor(cause, context) {
1865
+ super("Edit comment failed.");
1866
+ this.cause = cause;
1867
+ this.context = context;
1868
+ this.name = "EditCommentError";
1869
+ }
1870
+ };
1871
+ var DeleteCommentError = class extends Error {
1872
+ constructor(cause, context) {
1873
+ super("Delete comment failed.");
1874
+ this.cause = cause;
1875
+ this.context = context;
1876
+ this.name = "DeleteCommentError";
1877
+ }
1878
+ };
1879
+ var AddReactionError = class extends Error {
1880
+ constructor(cause, context) {
1881
+ super("Add reaction failed.");
1882
+ this.cause = cause;
1883
+ this.context = context;
1884
+ this.name = "AddReactionError";
1885
+ }
1886
+ };
1887
+ var RemoveReactionError = class extends Error {
1888
+ constructor(cause, context) {
1889
+ super("Remove reaction failed.");
1890
+ this.cause = cause;
1891
+ this.context = context;
1892
+ this.name = "RemoveReactionError";
1893
+ }
1894
+ };
1895
+ var MarkInboxNotificationAsReadError = class extends Error {
1896
+ constructor(cause, context) {
1897
+ super("Mark inbox notification as read failed.");
1898
+ this.cause = cause;
1899
+ this.context = context;
1900
+ this.name = "MarkInboxNotificationAsReadError";
1901
+ }
1902
+ };
1903
+ var UpdateNotificationSettingsError = class extends Error {
1904
+ constructor(cause, context) {
1905
+ super("Update notification settings failed.");
1906
+ this.cause = cause;
1907
+ this.context = context;
1908
+ this.name = "UpdateNotificationSettingsError";
1909
+ }
1910
+ };
1911
+
1912
+ // src/room.tsx
1913
+ var _client = require('@liveblocks/client');
1914
+
1915
+
1916
+
1917
+
1918
+
1919
+
1920
+
1921
+
1922
+
1923
+
1924
+
1925
+
1926
+
1927
+
1928
+
1929
+
1930
+
1931
+
1932
+
1788
1933
  // src/use-scroll-to-comment-on-load-effect.ts
1789
1934
 
1790
1935
  function handleScrollToCommentOnLoad(shouldScrollOnLoad, state) {
@@ -1805,7 +1950,7 @@ function handleScrollToCommentOnLoad(shouldScrollOnLoad, state) {
1805
1950
  comment.scrollIntoView();
1806
1951
  }
1807
1952
  function useScrollToCommentOnLoadEffect(shouldScrollOnLoad, state) {
1808
- React3.useEffect(
1953
+ React4.useEffect(
1809
1954
  () => {
1810
1955
  handleScrollToCommentOnLoad(shouldScrollOnLoad, state);
1811
1956
  },
@@ -1848,20 +1993,8 @@ function alwaysNull() {
1848
1993
  function selectorFor_useOthersConnectionIds(others) {
1849
1994
  return others.map((user) => user.connectionId);
1850
1995
  }
1851
- function selectRoomThreads(roomId, state, options) {
1852
- const result = applyOptimisticUpdates(state);
1853
- let threads = Object.values(result.threads).filter(
1854
- (thread) => !thread.deletedAt
1855
- );
1856
- threads = threads.filter((thread) => thread.roomId === roomId);
1857
- const query = options.query;
1858
- if (query) {
1859
- threads = threads.filter(makeThreadsFilter(query));
1860
- }
1861
- return threads.sort(byFirstCreated);
1862
- }
1863
1996
  function selectNotificationSettings(roomId, state) {
1864
- const { notificationSettings } = applyOptimisticUpdates(state);
1997
+ const notificationSettings = state.notificationSettingsByRoomId;
1865
1998
  return _core.nn.call(void 0, notificationSettings[roomId]);
1866
1999
  }
1867
2000
  function makeMutationContext(room) {
@@ -2097,10 +2230,9 @@ function makeExtrasForClient2(client) {
2097
2230
  onMutationFailure
2098
2231
  };
2099
2232
  }
2100
- var RoomContext = React4.createContext(null);
2101
2233
  function makeRoomContextBundle(client) {
2102
2234
  function RoomProvider_withImplicitLiveblocksProvider(props) {
2103
- return /* @__PURE__ */ React4.createElement(LiveblocksProviderWithClient, { client, allowNesting: true }, /* @__PURE__ */ React4.createElement(RoomProvider, { ...props }));
2235
+ return /* @__PURE__ */ React5.createElement(LiveblocksProviderWithClient, { client, allowNesting: true }, /* @__PURE__ */ React5.createElement(RoomProvider, { ...props }));
2104
2236
  }
2105
2237
  const shared = createSharedContext(client);
2106
2238
  const bundle = {
@@ -2143,6 +2275,7 @@ function makeRoomContextBundle(client) {
2143
2275
  useRemoveReaction,
2144
2276
  useMarkThreadAsRead,
2145
2277
  useThreadSubscription,
2278
+ useAttachmentUrl,
2146
2279
  useHistoryVersions,
2147
2280
  useHistoryVersionData,
2148
2281
  useRoomNotificationSettings,
@@ -2188,6 +2321,7 @@ function makeRoomContextBundle(client) {
2188
2321
  useRemoveReaction,
2189
2322
  useMarkThreadAsRead,
2190
2323
  useThreadSubscription,
2324
+ useAttachmentUrl: useAttachmentUrlSuspense,
2191
2325
  // TODO: useHistoryVersionData: useHistoryVersionDataSuspense,
2192
2326
  useHistoryVersions: useHistoryVersionsSuspense,
2193
2327
  useRoomNotificationSettings: useRoomNotificationSettingsSuspense,
@@ -2202,10 +2336,10 @@ function makeRoomContextBundle(client) {
2202
2336
  }
2203
2337
  function RoomProvider(props) {
2204
2338
  const client = useClient();
2205
- const [cache] = React4.useState(
2339
+ const [cache] = React5.useState(
2206
2340
  () => /* @__PURE__ */ new Map()
2207
2341
  );
2208
- const stableEnterRoom = React4.useCallback(
2342
+ const stableEnterRoom = React5.useCallback(
2209
2343
  (roomId, options) => {
2210
2344
  const cached = cache.get(roomId);
2211
2345
  if (cached) return cached;
@@ -2220,7 +2354,7 @@ function RoomProvider(props) {
2220
2354
  },
2221
2355
  [client, cache]
2222
2356
  );
2223
- return /* @__PURE__ */ React4.createElement(
2357
+ return /* @__PURE__ */ React5.createElement(
2224
2358
  RoomProviderInner,
2225
2359
  {
2226
2360
  ...props,
@@ -2240,7 +2374,7 @@ function RoomProviderInner(props) {
2240
2374
  if (!isString(roomId)) {
2241
2375
  throw new Error("RoomProvider id property should be a string.");
2242
2376
  }
2243
- const majorReactVersion = parseInt(React4.version) || 1;
2377
+ const majorReactVersion = parseInt(React5.version) || 1;
2244
2378
  const oldReactVersion = majorReactVersion < 18;
2245
2379
  _core.errorIf.call(void 0,
2246
2380
  oldReactVersion && props.unstable_batchedUpdates === void 0,
@@ -2257,14 +2391,14 @@ function RoomProviderInner(props) {
2257
2391
  unstable_batchedUpdates: props.unstable_batchedUpdates,
2258
2392
  autoConnect: _nullishCoalesce(props.autoConnect, () => ( typeof window !== "undefined"))
2259
2393
  });
2260
- const [{ room }, setRoomLeavePair] = React4.useState(
2394
+ const [{ room }, setRoomLeavePair] = React5.useState(
2261
2395
  () => stableEnterRoom(roomId, {
2262
2396
  ...frozenProps,
2263
2397
  autoConnect: false
2264
2398
  // Deliberately using false here on the first render, see below
2265
2399
  })
2266
2400
  );
2267
- React4.useEffect(() => {
2401
+ React5.useEffect(() => {
2268
2402
  const { store } = getExtrasForClient2(client);
2269
2403
  async function handleCommentEvent(message) {
2270
2404
  if (message.type === _core.ServerMsgCode.THREAD_DELETED) {
@@ -2277,7 +2411,7 @@ function RoomProviderInner(props) {
2277
2411
  return;
2278
2412
  }
2279
2413
  const { thread, inboxNotification } = info;
2280
- const existingThread = store.get().threads[message.threadId];
2414
+ const existingThread = store.getThreads().threadsById[message.threadId];
2281
2415
  switch (message.type) {
2282
2416
  case _core.ServerMsgCode.COMMENT_EDITED:
2283
2417
  case _core.ServerMsgCode.THREAD_METADATA_UPDATED:
@@ -2299,11 +2433,11 @@ function RoomProviderInner(props) {
2299
2433
  (message) => void handleCommentEvent(message)
2300
2434
  );
2301
2435
  }, [client, room]);
2302
- React4.useEffect(() => {
2436
+ React5.useEffect(() => {
2303
2437
  const { getThreadsUpdates } = getExtrasForClient2(client);
2304
2438
  void getThreadsUpdates(room.id);
2305
2439
  }, [client, room.id]);
2306
- React4.useEffect(() => {
2440
+ React5.useEffect(() => {
2307
2441
  function handleIsOnline() {
2308
2442
  const { getThreadsUpdates } = getExtrasForClient2(client);
2309
2443
  void getThreadsUpdates(room.id);
@@ -2313,7 +2447,7 @@ function RoomProviderInner(props) {
2313
2447
  window.removeEventListener("online", handleIsOnline);
2314
2448
  };
2315
2449
  }, [client, room.id]);
2316
- React4.useEffect(() => {
2450
+ React5.useEffect(() => {
2317
2451
  const pair = stableEnterRoom(roomId, frozenProps);
2318
2452
  setRoomLeavePair(pair);
2319
2453
  const { room: room2, leave } = pair;
@@ -2324,7 +2458,7 @@ function RoomProviderInner(props) {
2324
2458
  leave();
2325
2459
  };
2326
2460
  }, [roomId, frozenProps, stableEnterRoom]);
2327
- return /* @__PURE__ */ React4.createElement(RoomContext.Provider, { value: room }, props.children);
2461
+ return /* @__PURE__ */ React5.createElement(RoomContext.Provider, { value: room }, props.children);
2328
2462
  }
2329
2463
  function useRoom() {
2330
2464
  const room = useRoomOrNull();
@@ -2333,10 +2467,6 @@ function useRoom() {
2333
2467
  }
2334
2468
  return room;
2335
2469
  }
2336
- function useIsInsideRoom() {
2337
- const room = useRoomOrNull();
2338
- return room !== null;
2339
- }
2340
2470
  function useStatus() {
2341
2471
  const room = useRoom();
2342
2472
  const subscribe = room.events.status.subscribe;
@@ -2361,9 +2491,9 @@ function useStorageStatusImmediate() {
2361
2491
  }
2362
2492
  function useStorageStatusSmooth() {
2363
2493
  const room = useRoom();
2364
- const [status, setStatus] = React4.useState(room.getStorageStatus);
2494
+ const [status, setStatus] = React5.useState(room.getStorageStatus);
2365
2495
  const oldStatus = useLatest(room.getStorageStatus());
2366
- React4.useEffect(() => {
2496
+ React5.useEffect(() => {
2367
2497
  let timeoutId;
2368
2498
  const unsub = room.events.storageStatus.subscribe((newStatus) => {
2369
2499
  if (oldStatus.current === "synchronizing" && newStatus === "synchronized") {
@@ -2385,7 +2515,7 @@ function useBatch() {
2385
2515
  }
2386
2516
  function useBroadcastEvent() {
2387
2517
  const room = useRoom();
2388
- return React4.useCallback(
2518
+ return React5.useCallback(
2389
2519
  (event, options = { shouldQueueEventIfNotReady: false }) => {
2390
2520
  room.broadcastEvent(event, options);
2391
2521
  },
@@ -2395,7 +2525,7 @@ function useBroadcastEvent() {
2395
2525
  function useOthersListener(callback) {
2396
2526
  const room = useRoom();
2397
2527
  const savedCallback = useLatest(callback);
2398
- React4.useEffect(
2528
+ React5.useEffect(
2399
2529
  () => room.events.others.subscribe((event) => savedCallback.current(event)),
2400
2530
  [room, savedCallback]
2401
2531
  );
@@ -2403,7 +2533,7 @@ function useOthersListener(callback) {
2403
2533
  function useLostConnectionListener(callback) {
2404
2534
  const room = useRoom();
2405
2535
  const savedCallback = useLatest(callback);
2406
- React4.useEffect(
2536
+ React5.useEffect(
2407
2537
  () => room.events.lostConnection.subscribe(
2408
2538
  (event) => savedCallback.current(event)
2409
2539
  ),
@@ -2413,7 +2543,7 @@ function useLostConnectionListener(callback) {
2413
2543
  function useErrorListener(callback) {
2414
2544
  const room = useRoom();
2415
2545
  const savedCallback = useLatest(callback);
2416
- React4.useEffect(
2546
+ React5.useEffect(
2417
2547
  () => room.events.error.subscribe((e) => savedCallback.current(e)),
2418
2548
  [room, savedCallback]
2419
2549
  );
@@ -2421,7 +2551,7 @@ function useErrorListener(callback) {
2421
2551
  function useEventListener(callback) {
2422
2552
  const room = useRoom();
2423
2553
  const savedCallback = useLatest(callback);
2424
- React4.useEffect(() => {
2554
+ React5.useEffect(() => {
2425
2555
  const listener = (eventData) => {
2426
2556
  savedCallback.current(eventData);
2427
2557
  };
@@ -2454,7 +2584,7 @@ function useSelf(maybeSelector, isEqual) {
2454
2584
  const subscribe = room.events.self.subscribe;
2455
2585
  const getSnapshot = room.getSelf;
2456
2586
  const selector = _nullishCoalesce(maybeSelector, () => ( identity));
2457
- const wrappedSelector = React4.useCallback(
2587
+ const wrappedSelector = React5.useCallback(
2458
2588
  (me) => me !== null ? selector(me) : null,
2459
2589
  [selector]
2460
2590
  );
@@ -2492,11 +2622,11 @@ function useOthers(selector, isEqual) {
2492
2622
  );
2493
2623
  }
2494
2624
  function useOthersMapped(itemSelector, itemIsEqual) {
2495
- const wrappedSelector = React4.useCallback(
2625
+ const wrappedSelector = React5.useCallback(
2496
2626
  (others) => others.map((other) => [other.connectionId, itemSelector(other)]),
2497
2627
  [itemSelector]
2498
2628
  );
2499
- const wrappedIsEqual = React4.useCallback(
2629
+ const wrappedIsEqual = React5.useCallback(
2500
2630
  (a, b) => {
2501
2631
  const eq = _nullishCoalesce(itemIsEqual, () => ( Object.is));
2502
2632
  return a.length === b.length && a.every((atuple, index) => {
@@ -2513,14 +2643,14 @@ function useOthersConnectionIds() {
2513
2643
  }
2514
2644
  var NOT_FOUND = Symbol();
2515
2645
  function useOther(connectionId, selector, isEqual) {
2516
- const wrappedSelector = React4.useCallback(
2646
+ const wrappedSelector = React5.useCallback(
2517
2647
  (others) => {
2518
2648
  const other2 = others.find((other3) => other3.connectionId === connectionId);
2519
2649
  return other2 !== void 0 ? selector(other2) : NOT_FOUND;
2520
2650
  },
2521
2651
  [connectionId, selector]
2522
2652
  );
2523
- const wrappedIsEqual = React4.useCallback(
2653
+ const wrappedIsEqual = React5.useCallback(
2524
2654
  (prev, curr) => {
2525
2655
  if (prev === NOT_FOUND || curr === NOT_FOUND) {
2526
2656
  return prev === curr;
@@ -2551,15 +2681,15 @@ function useStorageRoot() {
2551
2681
  function useStorage(selector, isEqual) {
2552
2682
  const room = useRoom();
2553
2683
  const rootOrNull = useMutableStorageRoot();
2554
- const wrappedSelector = React4.useCallback(
2684
+ const wrappedSelector = React5.useCallback(
2555
2685
  (rootOrNull2) => rootOrNull2 !== null ? selector(rootOrNull2) : null,
2556
2686
  [selector]
2557
2687
  );
2558
- const subscribe = React4.useCallback(
2688
+ const subscribe = React5.useCallback(
2559
2689
  (onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) : noop2,
2560
2690
  [room, rootOrNull]
2561
2691
  );
2562
- const getSnapshot = React4.useCallback(() => {
2692
+ const getSnapshot = React5.useCallback(() => {
2563
2693
  if (rootOrNull === null) {
2564
2694
  return null;
2565
2695
  } else {
@@ -2579,7 +2709,7 @@ function useStorage(selector, isEqual) {
2579
2709
  }
2580
2710
  function useMutation(callback, deps) {
2581
2711
  const room = useRoom();
2582
- return React4.useMemo(
2712
+ return React5.useMemo(
2583
2713
  () => {
2584
2714
  return (...args) => (
2585
2715
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
@@ -2604,16 +2734,16 @@ function useThreads(options = {
2604
2734
  const { scrollOnLoad = true } = options;
2605
2735
  const client = useClient();
2606
2736
  const room = useRoom();
2607
- const queryKey = React4.useMemo(
2737
+ const queryKey = React5.useMemo(
2608
2738
  () => generateQueryKey(room.id, options.query),
2609
2739
  [room, options]
2610
2740
  );
2611
2741
  const { store, getThreadsAndInboxNotifications, incrementQuerySubscribers } = getExtrasForClient2(client);
2612
- React4.useEffect(() => {
2742
+ React5.useEffect(() => {
2613
2743
  void getThreadsAndInboxNotifications(room, queryKey, options);
2614
2744
  return incrementQuerySubscribers(queryKey);
2615
2745
  }, [room, queryKey]);
2616
- const selector = React4.useCallback(
2746
+ const selector = React5.useCallback(
2617
2747
  (state2) => {
2618
2748
  const query = state2.queries[queryKey];
2619
2749
  if (query === void 0 || query.isLoading) {
@@ -2622,7 +2752,11 @@ function useThreads(options = {
2622
2752
  };
2623
2753
  }
2624
2754
  return {
2625
- threads: selectRoomThreads(room.id, state2, options),
2755
+ threads: selectThreads(state2, {
2756
+ roomId: room.id,
2757
+ query: options.query,
2758
+ orderBy: "age"
2759
+ }),
2626
2760
  isLoading: false,
2627
2761
  error: query.error
2628
2762
  };
@@ -2631,9 +2765,9 @@ function useThreads(options = {
2631
2765
  // eslint-disable-line react-hooks/exhaustive-deps
2632
2766
  );
2633
2767
  const state = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
2634
- store.subscribe,
2635
- store.get,
2636
- store.get,
2768
+ store.subscribeThreads,
2769
+ store.getThreads,
2770
+ store.getThreads,
2637
2771
  selector
2638
2772
  );
2639
2773
  useScrollToCommentOnLoadEffect(scrollOnLoad, state);
@@ -2643,17 +2777,18 @@ function useCommentsErrorListener(callback) {
2643
2777
  const client = useClient();
2644
2778
  const savedCallback = useLatest(callback);
2645
2779
  const { commentsErrorEventSource } = getExtrasForClient2(client);
2646
- React4.useEffect(() => {
2780
+ React5.useEffect(() => {
2647
2781
  return commentsErrorEventSource.subscribe(savedCallback.current);
2648
2782
  }, [savedCallback, commentsErrorEventSource]);
2649
2783
  }
2650
2784
  function useCreateThread() {
2651
2785
  const client = useClient();
2652
2786
  const room = useRoom();
2653
- return React4.useCallback(
2787
+ return React5.useCallback(
2654
2788
  (options) => {
2655
2789
  const body = options.body;
2656
2790
  const metadata = _nullishCoalesce(options.metadata, () => ( {}));
2791
+ const attachments = options.attachments;
2657
2792
  const threadId = _core.createThreadId.call(void 0, );
2658
2793
  const commentId = _core.createCommentId.call(void 0, );
2659
2794
  const createdAt = /* @__PURE__ */ new Date();
@@ -2665,7 +2800,8 @@ function useCreateThread() {
2665
2800
  type: "comment",
2666
2801
  userId: getCurrentUserId(room),
2667
2802
  body,
2668
- reactions: []
2803
+ reactions: [],
2804
+ attachments: _nullishCoalesce(attachments, () => ( []))
2669
2805
  };
2670
2806
  const newThread = {
2671
2807
  id: threadId,
@@ -2683,7 +2819,8 @@ function useCreateThread() {
2683
2819
  thread: newThread,
2684
2820
  roomId: room.id
2685
2821
  });
2686
- room.createThread({ threadId, commentId, body, metadata }).then(
2822
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _23 => _23.map, 'call', _24 => _24((attachment) => attachment.id)]);
2823
+ room.createThread({ threadId, commentId, body, metadata, attachmentIds }).then(
2687
2824
  (thread) => {
2688
2825
  store.createThread(optimisticUpdateId, thread);
2689
2826
  },
@@ -2707,12 +2844,12 @@ function useCreateThread() {
2707
2844
  function useDeleteThread() {
2708
2845
  const client = useClient();
2709
2846
  const room = useRoom();
2710
- return React4.useCallback(
2847
+ return React5.useCallback(
2711
2848
  (threadId) => {
2712
2849
  const { store, onMutationFailure } = getExtrasForClient2(client);
2713
- const thread = store.get().threads[threadId];
2850
+ const thread = store.getThreads().threadsById[threadId];
2714
2851
  const userId = getCurrentUserId(room);
2715
- if (_optionalChain([thread, 'optionalAccess', _23 => _23.comments, 'optionalAccess', _24 => _24[0], 'optionalAccess', _25 => _25.userId]) !== userId) {
2852
+ if (_optionalChain([thread, 'optionalAccess', _25 => _25.comments, 'optionalAccess', _26 => _26[0], 'optionalAccess', _27 => _27.userId]) !== userId) {
2716
2853
  throw new Error("Only the thread creator can delete the thread");
2717
2854
  }
2718
2855
  const optimisticUpdateId = store.addOptimisticUpdate({
@@ -2738,7 +2875,7 @@ function useDeleteThread() {
2738
2875
  function useEditThreadMetadata() {
2739
2876
  const client = useClient();
2740
2877
  const room = useRoom();
2741
- return React4.useCallback(
2878
+ return React5.useCallback(
2742
2879
  (options) => {
2743
2880
  if (!options.metadata) {
2744
2881
  return;
@@ -2756,10 +2893,10 @@ function useEditThreadMetadata() {
2756
2893
  room.editThreadMetadata({ threadId, metadata }).then(
2757
2894
  (metadata2) => (
2758
2895
  // Replace the optimistic update by the real thing
2759
- store.updateThread(
2896
+ store.patchThread(
2760
2897
  threadId,
2761
2898
  optimisticUpdateId,
2762
- (thread) => ({ ...thread, metadata: metadata2 }),
2899
+ { metadata: metadata2 },
2763
2900
  updatedAt
2764
2901
  )
2765
2902
  ),
@@ -2780,8 +2917,8 @@ function useEditThreadMetadata() {
2780
2917
  function useCreateComment() {
2781
2918
  const client = useClient();
2782
2919
  const room = useRoom();
2783
- return React4.useCallback(
2784
- ({ threadId, body }) => {
2920
+ return React5.useCallback(
2921
+ ({ threadId, body, attachments }) => {
2785
2922
  const commentId = _core.createCommentId.call(void 0, );
2786
2923
  const createdAt = /* @__PURE__ */ new Date();
2787
2924
  const comment = {
@@ -2792,14 +2929,16 @@ function useCreateComment() {
2792
2929
  createdAt,
2793
2930
  userId: getCurrentUserId(room),
2794
2931
  body,
2795
- reactions: []
2932
+ reactions: [],
2933
+ attachments: _nullishCoalesce(attachments, () => ( []))
2796
2934
  };
2797
2935
  const { store, onMutationFailure } = getExtrasForClient2(client);
2798
2936
  const optimisticUpdateId = store.addOptimisticUpdate({
2799
2937
  type: "create-comment",
2800
2938
  comment
2801
2939
  });
2802
- room.createComment({ threadId, commentId, body }).then(
2940
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _28 => _28.map, 'call', _29 => _29((attachment) => attachment.id)]);
2941
+ room.createComment({ threadId, commentId, body, attachmentIds }).then(
2803
2942
  (newComment) => {
2804
2943
  store.createComment(newComment, optimisticUpdateId);
2805
2944
  },
@@ -2822,11 +2961,11 @@ function useCreateComment() {
2822
2961
  function useEditComment() {
2823
2962
  const client = useClient();
2824
2963
  const room = useRoom();
2825
- return React4.useCallback(
2826
- ({ threadId, commentId, body }) => {
2964
+ return React5.useCallback(
2965
+ ({ threadId, commentId, body, attachments }) => {
2827
2966
  const editedAt = /* @__PURE__ */ new Date();
2828
2967
  const { store, onMutationFailure } = getExtrasForClient2(client);
2829
- const thread = store.get().threads[threadId];
2968
+ const thread = store.getThreads().threadsById[threadId];
2830
2969
  if (thread === void 0) {
2831
2970
  _core.console.warn(
2832
2971
  `Internal unexpected behavior. Cannot edit comment in thread "${threadId}" because the thread does not exist in the cache.`
@@ -2847,16 +2986,14 @@ function useEditComment() {
2847
2986
  comment: {
2848
2987
  ...comment,
2849
2988
  editedAt,
2850
- body
2989
+ body,
2990
+ attachments: _nullishCoalesce(attachments, () => ( []))
2851
2991
  }
2852
2992
  });
2853
- room.editComment({ threadId, commentId, body }).then(
2993
+ const attachmentIds = _optionalChain([attachments, 'optionalAccess', _30 => _30.map, 'call', _31 => _31((attachment) => attachment.id)]);
2994
+ room.editComment({ threadId, commentId, body, attachmentIds }).then(
2854
2995
  (editedComment) => {
2855
- store.updateThread(
2856
- threadId,
2857
- optimisticUpdateId,
2858
- (thread2) => upsertComment(thread2, editedComment)
2859
- );
2996
+ store.editComment(threadId, optimisticUpdateId, editedComment);
2860
2997
  },
2861
2998
  (err) => onMutationFailure(
2862
2999
  err,
@@ -2876,7 +3013,7 @@ function useEditComment() {
2876
3013
  function useDeleteComment() {
2877
3014
  const client = useClient();
2878
3015
  const room = useRoom();
2879
- return React4.useCallback(
3016
+ return React5.useCallback(
2880
3017
  ({ threadId, commentId }) => {
2881
3018
  const deletedAt = /* @__PURE__ */ new Date();
2882
3019
  const { store, onMutationFailure } = getExtrasForClient2(client);
@@ -2889,10 +3026,10 @@ function useDeleteComment() {
2889
3026
  });
2890
3027
  room.deleteComment({ threadId, commentId }).then(
2891
3028
  () => {
2892
- store.updateThread(
3029
+ store.deleteComment(
2893
3030
  threadId,
2894
3031
  optimisticUpdateId,
2895
- (thread) => deleteComment(thread, commentId, deletedAt),
3032
+ commentId,
2896
3033
  deletedAt
2897
3034
  );
2898
3035
  },
@@ -2913,7 +3050,7 @@ function useDeleteComment() {
2913
3050
  function useAddReaction() {
2914
3051
  const client = useClient();
2915
3052
  const room = useRoom();
2916
- return React4.useCallback(
3053
+ return React5.useCallback(
2917
3054
  ({ threadId, commentId, emoji }) => {
2918
3055
  const createdAt = /* @__PURE__ */ new Date();
2919
3056
  const userId = getCurrentUserId(room);
@@ -2930,10 +3067,11 @@ function useAddReaction() {
2930
3067
  });
2931
3068
  room.addReaction({ threadId, commentId, emoji }).then(
2932
3069
  (addedReaction) => {
2933
- store.updateThread(
3070
+ store.addReaction(
2934
3071
  threadId,
2935
3072
  optimisticUpdateId,
2936
- (thread) => addReaction(thread, commentId, addedReaction),
3073
+ commentId,
3074
+ addedReaction,
2937
3075
  createdAt
2938
3076
  );
2939
3077
  },
@@ -2955,7 +3093,7 @@ function useAddReaction() {
2955
3093
  function useRemoveReaction() {
2956
3094
  const client = useClient();
2957
3095
  const room = useRoom();
2958
- return React4.useCallback(
3096
+ return React5.useCallback(
2959
3097
  ({ threadId, commentId, emoji }) => {
2960
3098
  const userId = getCurrentUserId(room);
2961
3099
  const removedAt = /* @__PURE__ */ new Date();
@@ -2970,10 +3108,12 @@ function useRemoveReaction() {
2970
3108
  });
2971
3109
  room.removeReaction({ threadId, commentId, emoji }).then(
2972
3110
  () => {
2973
- store.updateThread(
3111
+ store.removeReaction(
2974
3112
  threadId,
2975
3113
  optimisticUpdateId,
2976
- (thread) => removeReaction(thread, commentId, emoji, userId, removedAt),
3114
+ commentId,
3115
+ emoji,
3116
+ userId,
2977
3117
  removedAt
2978
3118
  );
2979
3119
  },
@@ -2995,11 +3135,11 @@ function useRemoveReaction() {
2995
3135
  function useMarkThreadAsRead() {
2996
3136
  const client = useClient();
2997
3137
  const room = useRoom();
2998
- return React4.useCallback(
3138
+ return React5.useCallback(
2999
3139
  (threadId) => {
3000
3140
  const { store, onMutationFailure } = getExtrasForClient2(client);
3001
3141
  const inboxNotification = Object.values(
3002
- store.get().inboxNotifications
3142
+ store.getInboxNotifications().inboxNotificationsById
3003
3143
  ).find(
3004
3144
  (inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
3005
3145
  );
@@ -3036,7 +3176,7 @@ function useMarkThreadAsRead() {
3036
3176
  function useMarkThreadAsResolved() {
3037
3177
  const client = useClient();
3038
3178
  const room = useRoom();
3039
- return React4.useCallback(
3179
+ return React5.useCallback(
3040
3180
  (threadId) => {
3041
3181
  const updatedAt = /* @__PURE__ */ new Date();
3042
3182
  const { store, onMutationFailure } = getExtrasForClient2(client);
@@ -3047,10 +3187,10 @@ function useMarkThreadAsResolved() {
3047
3187
  });
3048
3188
  room.markThreadAsResolved(threadId).then(
3049
3189
  () => {
3050
- store.updateThread(
3190
+ store.patchThread(
3051
3191
  threadId,
3052
3192
  optimisticUpdateId,
3053
- (thread) => ({ ...thread, resolved: true }),
3193
+ { resolved: true },
3054
3194
  updatedAt
3055
3195
  );
3056
3196
  },
@@ -3070,7 +3210,7 @@ function useMarkThreadAsResolved() {
3070
3210
  function useMarkThreadAsUnresolved() {
3071
3211
  const client = useClient();
3072
3212
  const room = useRoom();
3073
- return React4.useCallback(
3213
+ return React5.useCallback(
3074
3214
  (threadId) => {
3075
3215
  const updatedAt = /* @__PURE__ */ new Date();
3076
3216
  const { store, onMutationFailure } = getExtrasForClient2(client);
@@ -3081,10 +3221,10 @@ function useMarkThreadAsUnresolved() {
3081
3221
  });
3082
3222
  room.markThreadAsUnresolved(threadId).then(
3083
3223
  () => {
3084
- store.updateThread(
3224
+ store.patchThread(
3085
3225
  threadId,
3086
3226
  optimisticUpdateId,
3087
- (thread) => ({ ...thread, resolved: false }),
3227
+ { resolved: false },
3088
3228
  updatedAt
3089
3229
  );
3090
3230
  },
@@ -3104,12 +3244,12 @@ function useMarkThreadAsUnresolved() {
3104
3244
  function useThreadSubscription(threadId) {
3105
3245
  const client = useClient();
3106
3246
  const { store } = getExtrasForClient2(client);
3107
- const selector = React4.useCallback(
3247
+ const selector = React5.useCallback(
3108
3248
  (state) => {
3109
- const inboxNotification = selectInboxNotifications(state).find(
3249
+ const inboxNotification = state.inboxNotifications.find(
3110
3250
  (inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
3111
3251
  );
3112
- const thread = state.threads[threadId];
3252
+ const thread = state.threadsById[threadId];
3113
3253
  if (inboxNotification === void 0 || thread === void 0) {
3114
3254
  return {
3115
3255
  status: "not-subscribed"
@@ -3123,9 +3263,9 @@ function useThreadSubscription(threadId) {
3123
3263
  [threadId]
3124
3264
  );
3125
3265
  return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
3126
- store.subscribe,
3127
- store.get,
3128
- store.get,
3266
+ store.subscribeThreads,
3267
+ store.getThreads,
3268
+ store.getThreads,
3129
3269
  selector
3130
3270
  );
3131
3271
  }
@@ -3133,13 +3273,13 @@ function useRoomNotificationSettings() {
3133
3273
  const client = useClient();
3134
3274
  const room = useRoom();
3135
3275
  const { store } = getExtrasForClient2(client);
3136
- React4.useEffect(() => {
3276
+ React5.useEffect(() => {
3137
3277
  const { getInboxNotificationSettings } = getExtrasForClient2(client);
3138
3278
  const queryKey = makeNotificationSettingsQueryKey(room.id);
3139
3279
  void getInboxNotificationSettings(room, queryKey);
3140
3280
  }, [client, room]);
3141
3281
  const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
3142
- const selector = React4.useCallback(
3282
+ const selector = React5.useCallback(
3143
3283
  (state) => {
3144
3284
  const query = state.queries[makeNotificationSettingsQueryKey(room.id)];
3145
3285
  if (query === void 0 || query.isLoading) {
@@ -3156,21 +3296,21 @@ function useRoomNotificationSettings() {
3156
3296
  [room]
3157
3297
  );
3158
3298
  const settings = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
3159
- store.subscribe,
3160
- store.get,
3161
- store.get,
3299
+ store.subscribeNotificationSettings,
3300
+ store.getThreads,
3301
+ store.getThreads,
3162
3302
  selector
3163
3303
  );
3164
- return React4.useMemo(() => {
3304
+ return React5.useMemo(() => {
3165
3305
  return [settings, updateRoomNotificationSettings];
3166
3306
  }, [settings, updateRoomNotificationSettings]);
3167
3307
  }
3168
3308
  function useHistoryVersionData(versionId) {
3169
- const [state, setState] = React4.useState({
3309
+ const [state, setState] = React5.useState({
3170
3310
  isLoading: true
3171
3311
  });
3172
3312
  const room = useRoom();
3173
- React4.useEffect(() => {
3313
+ React5.useEffect(() => {
3174
3314
  setState({ isLoading: true });
3175
3315
  const load = async () => {
3176
3316
  try {
@@ -3199,10 +3339,10 @@ function useHistoryVersions() {
3199
3339
  const room = useRoom();
3200
3340
  const queryKey = getVersionsQueryKey(room.id);
3201
3341
  const { store, getRoomVersions } = getExtrasForClient2(client);
3202
- React4.useEffect(() => {
3342
+ React5.useEffect(() => {
3203
3343
  void getRoomVersions(room);
3204
3344
  }, [room]);
3205
- const selector = React4.useCallback(
3345
+ const selector = React5.useCallback(
3206
3346
  (state2) => {
3207
3347
  const query = state2.queries[queryKey];
3208
3348
  if (query === void 0 || query.isLoading) {
@@ -3211,7 +3351,7 @@ function useHistoryVersions() {
3211
3351
  };
3212
3352
  }
3213
3353
  return {
3214
- versions: state2.versions[room.id],
3354
+ versions: state2.versionsByRoomId[room.id],
3215
3355
  isLoading: false,
3216
3356
  error: query.error
3217
3357
  };
@@ -3220,9 +3360,9 @@ function useHistoryVersions() {
3220
3360
  // eslint-disable-line react-hooks/exhaustive-deps
3221
3361
  );
3222
3362
  const state = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
3223
- store.subscribe,
3224
- store.get,
3225
- store.get,
3363
+ store.subscribeVersions,
3364
+ store.getVersions,
3365
+ store.getVersions,
3226
3366
  selector
3227
3367
  );
3228
3368
  return state;
@@ -3230,7 +3370,7 @@ function useHistoryVersions() {
3230
3370
  function useUpdateRoomNotificationSettings() {
3231
3371
  const client = useClient();
3232
3372
  const room = useRoom();
3233
- return React4.useCallback(
3373
+ return React5.useCallback(
3234
3374
  (settings) => {
3235
3375
  const { store, onMutationFailure } = getExtrasForClient2(client);
3236
3376
  const optimisticUpdateId = store.addOptimisticUpdate({
@@ -3318,57 +3458,120 @@ function useThreadsSuspense(options = {
3318
3458
  const { scrollOnLoad = true } = options;
3319
3459
  const client = useClient();
3320
3460
  const room = useRoom();
3321
- const queryKey = React4.useMemo(
3461
+ const queryKey = React5.useMemo(
3322
3462
  () => generateQueryKey(room.id, options.query),
3323
3463
  [room, options]
3324
3464
  );
3325
3465
  const { store, getThreadsAndInboxNotifications } = getExtrasForClient2(client);
3326
- const query = store.get().queries[queryKey];
3466
+ const query = store.getThreads().queries[queryKey];
3327
3467
  if (query === void 0 || query.isLoading) {
3328
3468
  throw getThreadsAndInboxNotifications(room, queryKey, options);
3329
3469
  }
3330
3470
  if (query.error) {
3331
3471
  throw query.error;
3332
3472
  }
3333
- const selector = React4.useCallback(
3473
+ const selector = React5.useCallback(
3334
3474
  (state2) => {
3335
3475
  return {
3336
- threads: selectRoomThreads(room.id, state2, options),
3476
+ threads: selectThreads(state2, {
3477
+ roomId: room.id,
3478
+ query: options.query,
3479
+ orderBy: "age"
3480
+ }),
3337
3481
  isLoading: false
3338
3482
  };
3339
3483
  },
3340
3484
  [room, queryKey]
3341
3485
  // eslint-disable-line react-hooks/exhaustive-deps
3342
3486
  );
3343
- React4.useEffect(() => {
3487
+ React5.useEffect(() => {
3344
3488
  const { incrementQuerySubscribers } = getExtrasForClient2(client);
3345
3489
  return incrementQuerySubscribers(queryKey);
3346
3490
  }, [client, queryKey]);
3347
3491
  const state = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
3348
- store.subscribe,
3349
- store.get,
3350
- store.get,
3492
+ store.subscribeThreads,
3493
+ store.getThreads,
3494
+ store.getThreads,
3351
3495
  selector
3352
3496
  );
3353
3497
  useScrollToCommentOnLoadEffect(scrollOnLoad, state);
3354
3498
  return state;
3355
3499
  }
3500
+ function selectorFor_useAttachmentUrl(state) {
3501
+ if (state === void 0 || _optionalChain([state, 'optionalAccess', _32 => _32.isLoading])) {
3502
+ return _nullishCoalesce(state, () => ( { isLoading: true }));
3503
+ }
3504
+ if (state.error) {
3505
+ return state;
3506
+ }
3507
+ _core.assert.call(void 0, state.data !== void 0, "Unexpected missing attachment URL");
3508
+ return {
3509
+ isLoading: false,
3510
+ url: state.data
3511
+ };
3512
+ }
3513
+ function useAttachmentUrl(attachmentId) {
3514
+ const room = useRoom();
3515
+ const { attachmentUrlsStore } = room[_core.kInternal];
3516
+ const getAttachmentUrlState = React5.useCallback(
3517
+ () => attachmentUrlsStore.getState(attachmentId),
3518
+ [attachmentUrlsStore, attachmentId]
3519
+ );
3520
+ React5.useEffect(() => {
3521
+ void attachmentUrlsStore.get(attachmentId);
3522
+ }, [attachmentUrlsStore, attachmentId]);
3523
+ return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
3524
+ attachmentUrlsStore.subscribe,
3525
+ getAttachmentUrlState,
3526
+ getAttachmentUrlState,
3527
+ selectorFor_useAttachmentUrl,
3528
+ _client.shallow
3529
+ );
3530
+ }
3531
+ function useAttachmentUrlSuspense(attachmentId) {
3532
+ const room = useRoom();
3533
+ const { attachmentUrlsStore } = room[_core.kInternal];
3534
+ const getAttachmentUrlState = React5.useCallback(
3535
+ () => attachmentUrlsStore.getState(attachmentId),
3536
+ [attachmentUrlsStore, attachmentId]
3537
+ );
3538
+ const attachmentUrlState = getAttachmentUrlState();
3539
+ if (!attachmentUrlState || attachmentUrlState.isLoading) {
3540
+ throw attachmentUrlsStore.get(attachmentId);
3541
+ }
3542
+ if (attachmentUrlState.error) {
3543
+ throw attachmentUrlState.error;
3544
+ }
3545
+ const state = useSyncExternalStore2(
3546
+ attachmentUrlsStore.subscribe,
3547
+ getAttachmentUrlState,
3548
+ getAttachmentUrlState
3549
+ );
3550
+ _core.assert.call(void 0, state !== void 0, "Unexpected missing state");
3551
+ _core.assert.call(void 0, !state.isLoading, "Unexpected loading state");
3552
+ _core.assert.call(void 0, !state.error, "Unexpected error state");
3553
+ return {
3554
+ isLoading: false,
3555
+ url: state.data,
3556
+ error: void 0
3557
+ };
3558
+ }
3356
3559
  function useHistoryVersionsSuspense() {
3357
3560
  const client = useClient();
3358
3561
  const room = useRoom();
3359
3562
  const queryKey = getVersionsQueryKey(room.id);
3360
3563
  const { store, getRoomVersions } = getExtrasForClient2(client);
3361
- const query = store.get().queries[queryKey];
3564
+ const query = store.getVersions().queries[queryKey];
3362
3565
  if (query === void 0 || query.isLoading) {
3363
3566
  throw getRoomVersions(room);
3364
3567
  }
3365
3568
  if (query.error) {
3366
3569
  throw query.error;
3367
3570
  }
3368
- const selector = React4.useCallback(
3571
+ const selector = React5.useCallback(
3369
3572
  (state2) => {
3370
3573
  return {
3371
- versions: state2.versions[room.id],
3574
+ versions: state2.versionsByRoomId[room.id],
3372
3575
  isLoading: false
3373
3576
  };
3374
3577
  },
@@ -3376,9 +3579,9 @@ function useHistoryVersionsSuspense() {
3376
3579
  // eslint-disable-line react-hooks/exhaustive-deps
3377
3580
  );
3378
3581
  const state = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
3379
- store.subscribe,
3380
- store.get,
3381
- store.get,
3582
+ store.subscribeVersions,
3583
+ store.getVersions,
3584
+ store.getVersions,
3382
3585
  selector
3383
3586
  );
3384
3587
  return state;
@@ -3389,14 +3592,14 @@ function useRoomNotificationSettingsSuspense() {
3389
3592
  const room = useRoom();
3390
3593
  const queryKey = makeNotificationSettingsQueryKey(room.id);
3391
3594
  const { store, getInboxNotificationSettings } = getExtrasForClient2(client);
3392
- const query = store.get().queries[queryKey];
3595
+ const query = store.getNotificationSettings().queries[queryKey];
3393
3596
  if (query === void 0 || query.isLoading) {
3394
3597
  throw getInboxNotificationSettings(room, queryKey);
3395
3598
  }
3396
3599
  if (query.error) {
3397
3600
  throw query.error;
3398
3601
  }
3399
- const selector = React4.useCallback(
3602
+ const selector = React5.useCallback(
3400
3603
  (state) => {
3401
3604
  return {
3402
3605
  isLoading: false,
@@ -3406,18 +3609,15 @@ function useRoomNotificationSettingsSuspense() {
3406
3609
  [room]
3407
3610
  );
3408
3611
  const settings = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
3409
- store.subscribe,
3410
- store.get,
3411
- store.get,
3612
+ store.subscribeNotificationSettings,
3613
+ store.getNotificationSettings,
3614
+ store.getNotificationSettings,
3412
3615
  selector
3413
3616
  );
3414
- return React4.useMemo(() => {
3617
+ return React5.useMemo(() => {
3415
3618
  return [settings, updateRoomNotificationSettings];
3416
3619
  }, [settings, updateRoomNotificationSettings]);
3417
3620
  }
3418
- function useRoomOrNull() {
3419
- return React4.useContext(RoomContext);
3420
- }
3421
3621
  function createRoomContext(client) {
3422
3622
  return getOrCreateRoomContextBundle(client);
3423
3623
  }
@@ -3546,5 +3746,7 @@ var _useUpdateMyPresence = useUpdateMyPresence;
3546
3746
 
3547
3747
 
3548
3748
 
3549
- exports.PKG_NAME = PKG_NAME; exports.PKG_VERSION = PKG_VERSION; exports.PKG_FORMAT = PKG_FORMAT; exports.ClientSideSuspense = ClientSideSuspense; exports.CreateThreadError = CreateThreadError; exports.selectRoomThreads = selectRoomThreads; exports.RoomContext = RoomContext; 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.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; 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;
3550
- //# sourceMappingURL=chunk-KNPU4P3Y.js.map
3749
+
3750
+
3751
+ 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;
3752
+ //# sourceMappingURL=chunk-BYZWUB6M.js.map