@liveblocks/react 2.7.2 → 2.8.0-beta2

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
  // src/version.ts
2
2
  var PKG_NAME = "@liveblocks/react";
3
- var PKG_VERSION = "2.7.2";
3
+ var PKG_VERSION = "2.8.0-beta2";
4
4
  var PKG_FORMAT = "esm";
5
5
 
6
6
  // src/ClientSideSuspense.tsx
@@ -27,6 +27,7 @@ function useIsInsideRoom() {
27
27
  // src/liveblocks.tsx
28
28
  import {
29
29
  assert,
30
+ autoRetry,
30
31
  createClient,
31
32
  kInternal,
32
33
  makePoller,
@@ -90,7 +91,6 @@ function matchesOperator(value, op) {
90
91
  }
91
92
 
92
93
  // src/lib/retry-error.ts
93
- import { wait } from "@liveblocks/core";
94
94
  var MAX_ERROR_RETRY_COUNT = 5;
95
95
  var ERROR_RETRY_INTERVAL = 5e3;
96
96
  function retryError(action, retryCount) {
@@ -100,23 +100,6 @@ function retryError(action, retryCount) {
100
100
  void action();
101
101
  }, timeout);
102
102
  }
103
- async function autoRetry(promiseFn, maxTries, backoff) {
104
- const fallbackBackoff = backoff.length > 0 ? backoff[backoff.length - 1] : 0;
105
- let attempt = 0;
106
- while (true) {
107
- attempt++;
108
- const promise = promiseFn();
109
- try {
110
- return await promise;
111
- } catch (err) {
112
- if (attempt >= maxTries) {
113
- throw new Error(`Failed after ${maxTries} attempts: ${String(err)}`);
114
- }
115
- }
116
- const delay = backoff[attempt - 1] ?? fallbackBackoff;
117
- await wait(delay);
118
- }
119
- }
120
103
 
121
104
  // src/lib/shallow2.ts
122
105
  import { isPlainObject as isPlainObject2, shallow } from "@liveblocks/core";
@@ -205,9 +188,6 @@ var INBOX_NOTIFICATIONS_QUERY = "INBOX_NOTIFICATIONS";
205
188
  function makeNotificationSettingsQueryKey(roomId) {
206
189
  return `${roomId}:NOTIFICATION_SETTINGS`;
207
190
  }
208
- function makeVersionsQueryKey(roomId) {
209
- return `${roomId}-VERSIONS`;
210
- }
211
191
  var UmbrellaStore = class {
212
192
  constructor() {
213
193
  this._prevState = null;
@@ -223,6 +203,7 @@ var UmbrellaStore = class {
223
203
  this.getThreads = this.getThreads.bind(this);
224
204
  this.getInboxNotifications = this.getInboxNotifications.bind(this);
225
205
  this.getInboxNotificationsAsync = this.getInboxNotificationsAsync.bind(this);
206
+ this.getVersions = this.getVersions.bind(this);
226
207
  this.subscribeThreads = this.subscribeThreads.bind(this);
227
208
  this.subscribeInboxNotifications = this.subscribeInboxNotifications.bind(this);
228
209
  this.subscribeNotificationSettings = this.subscribeNotificationSettings.bind(this);
@@ -272,19 +253,8 @@ var UmbrellaStore = class {
272
253
  settings: nn(state.notificationSettingsByRoomId[roomId])
273
254
  };
274
255
  }
275
- getVersionsAsync(roomId) {
276
- const state = this.get();
277
- const query = state.queries[makeVersionsQueryKey(roomId)];
278
- if (query === void 0 || query.isLoading) {
279
- return QUERY_STATE_LOADING;
280
- }
281
- if (query.error !== void 0) {
282
- return query;
283
- }
284
- return {
285
- isLoading: false,
286
- versions: nn(state.versionsByRoomId[roomId])
287
- };
256
+ getVersions() {
257
+ return this.get();
288
258
  }
289
259
  /**
290
260
  * @private Only used by the E2E test suite.
@@ -629,19 +599,19 @@ var UmbrellaStore = class {
629
599
  }
630
600
  };
631
601
  function internalToExternalState(state) {
632
- const computed = {
633
- threadsById: { ...state.rawThreadsById },
634
- inboxNotificationsById: { ...state.inboxNotificationsById },
635
- notificationSettingsByRoomId: { ...state.notificationSettingsByRoomId }
602
+ const output = {
603
+ threads: { ...state.rawThreadsById },
604
+ inboxNotifications: { ...state.inboxNotificationsById },
605
+ notificationSettings: { ...state.notificationSettingsByRoomId }
636
606
  };
637
607
  for (const optimisticUpdate of state.optimisticUpdates) {
638
608
  switch (optimisticUpdate.type) {
639
609
  case "create-thread": {
640
- computed.threadsById[optimisticUpdate.thread.id] = optimisticUpdate.thread;
610
+ output.threads[optimisticUpdate.thread.id] = optimisticUpdate.thread;
641
611
  break;
642
612
  }
643
613
  case "edit-thread-metadata": {
644
- const thread = computed.threadsById[optimisticUpdate.threadId];
614
+ const thread = output.threads[optimisticUpdate.threadId];
645
615
  if (thread === void 0) {
646
616
  break;
647
617
  }
@@ -651,7 +621,7 @@ function internalToExternalState(state) {
651
621
  if (thread.updatedAt !== void 0 && thread.updatedAt > optimisticUpdate.updatedAt) {
652
622
  break;
653
623
  }
654
- computed.threadsById[thread.id] = {
624
+ output.threads[thread.id] = {
655
625
  ...thread,
656
626
  updatedAt: optimisticUpdate.updatedAt,
657
627
  metadata: {
@@ -662,51 +632,49 @@ function internalToExternalState(state) {
662
632
  break;
663
633
  }
664
634
  case "mark-thread-as-resolved": {
665
- const thread = computed.threadsById[optimisticUpdate.threadId];
635
+ const thread = output.threads[optimisticUpdate.threadId];
666
636
  if (thread === void 0) {
667
637
  break;
668
638
  }
669
639
  if (thread.deletedAt !== void 0) {
670
640
  break;
671
641
  }
672
- computed.threadsById[thread.id] = {
642
+ output.threads[thread.id] = {
673
643
  ...thread,
674
644
  resolved: true
675
645
  };
676
646
  break;
677
647
  }
678
648
  case "mark-thread-as-unresolved": {
679
- const thread = computed.threadsById[optimisticUpdate.threadId];
649
+ const thread = output.threads[optimisticUpdate.threadId];
680
650
  if (thread === void 0) {
681
651
  break;
682
652
  }
683
653
  if (thread.deletedAt !== void 0) {
684
654
  break;
685
655
  }
686
- computed.threadsById[thread.id] = {
656
+ output.threads[thread.id] = {
687
657
  ...thread,
688
658
  resolved: false
689
659
  };
690
660
  break;
691
661
  }
692
662
  case "create-comment": {
693
- const thread = computed.threadsById[optimisticUpdate.comment.threadId];
663
+ const thread = output.threads[optimisticUpdate.comment.threadId];
694
664
  if (thread === void 0) {
695
665
  break;
696
666
  }
697
- computed.threadsById[thread.id] = applyUpsertComment(
667
+ output.threads[thread.id] = applyUpsertComment(
698
668
  thread,
699
669
  optimisticUpdate.comment
700
670
  );
701
- const inboxNotification = Object.values(
702
- computed.inboxNotificationsById
703
- ).find(
671
+ const inboxNotification = Object.values(output.inboxNotifications).find(
704
672
  (notification) => notification.kind === "thread" && notification.threadId === thread.id
705
673
  );
706
674
  if (inboxNotification === void 0) {
707
675
  break;
708
676
  }
709
- computed.inboxNotificationsById[inboxNotification.id] = {
677
+ output.inboxNotifications[inboxNotification.id] = {
710
678
  ...inboxNotification,
711
679
  notifiedAt: optimisticUpdate.comment.createdAt,
712
680
  readAt: optimisticUpdate.comment.createdAt
@@ -714,22 +682,22 @@ function internalToExternalState(state) {
714
682
  break;
715
683
  }
716
684
  case "edit-comment": {
717
- const thread = computed.threadsById[optimisticUpdate.comment.threadId];
685
+ const thread = output.threads[optimisticUpdate.comment.threadId];
718
686
  if (thread === void 0) {
719
687
  break;
720
688
  }
721
- computed.threadsById[thread.id] = applyUpsertComment(
689
+ output.threads[thread.id] = applyUpsertComment(
722
690
  thread,
723
691
  optimisticUpdate.comment
724
692
  );
725
693
  break;
726
694
  }
727
695
  case "delete-comment": {
728
- const thread = computed.threadsById[optimisticUpdate.threadId];
696
+ const thread = output.threads[optimisticUpdate.threadId];
729
697
  if (thread === void 0) {
730
698
  break;
731
699
  }
732
- computed.threadsById[thread.id] = applyDeleteComment(
700
+ output.threads[thread.id] = applyDeleteComment(
733
701
  thread,
734
702
  optimisticUpdate.commentId,
735
703
  optimisticUpdate.deletedAt
@@ -737,12 +705,12 @@ function internalToExternalState(state) {
737
705
  break;
738
706
  }
739
707
  case "delete-thread": {
740
- const thread = computed.threadsById[optimisticUpdate.threadId];
708
+ const thread = output.threads[optimisticUpdate.threadId];
741
709
  if (thread === void 0) {
742
710
  break;
743
711
  }
744
- computed.threadsById[optimisticUpdate.threadId] = {
745
- ...thread,
712
+ output.threads[optimisticUpdate.threadId] = {
713
+ ...output.threads[optimisticUpdate.threadId],
746
714
  deletedAt: optimisticUpdate.deletedAt,
747
715
  updatedAt: optimisticUpdate.deletedAt,
748
716
  comments: []
@@ -750,11 +718,11 @@ function internalToExternalState(state) {
750
718
  break;
751
719
  }
752
720
  case "add-reaction": {
753
- const thread = computed.threadsById[optimisticUpdate.threadId];
721
+ const thread = output.threads[optimisticUpdate.threadId];
754
722
  if (thread === void 0) {
755
723
  break;
756
724
  }
757
- computed.threadsById[thread.id] = applyAddReaction(
725
+ output.threads[thread.id] = applyAddReaction(
758
726
  thread,
759
727
  optimisticUpdate.commentId,
760
728
  optimisticUpdate.reaction
@@ -762,11 +730,11 @@ function internalToExternalState(state) {
762
730
  break;
763
731
  }
764
732
  case "remove-reaction": {
765
- const thread = computed.threadsById[optimisticUpdate.threadId];
733
+ const thread = output.threads[optimisticUpdate.threadId];
766
734
  if (thread === void 0) {
767
735
  break;
768
736
  }
769
- computed.threadsById[thread.id] = applyRemoveReaction(
737
+ output.threads[thread.id] = applyRemoveReaction(
770
738
  thread,
771
739
  optimisticUpdate.commentId,
772
740
  optimisticUpdate.emoji,
@@ -776,41 +744,36 @@ function internalToExternalState(state) {
776
744
  break;
777
745
  }
778
746
  case "mark-inbox-notification-as-read": {
779
- const ibn = computed.inboxNotificationsById[optimisticUpdate.inboxNotificationId];
780
- if (ibn === void 0) {
781
- break;
782
- }
783
- computed.inboxNotificationsById[optimisticUpdate.inboxNotificationId] = { ...ibn, readAt: optimisticUpdate.readAt };
747
+ output.inboxNotifications[optimisticUpdate.inboxNotificationId] = {
748
+ ...state.inboxNotificationsById[optimisticUpdate.inboxNotificationId],
749
+ readAt: optimisticUpdate.readAt
750
+ };
784
751
  break;
785
752
  }
786
753
  case "mark-all-inbox-notifications-as-read": {
787
- for (const id in computed.inboxNotificationsById) {
788
- const ibn = computed.inboxNotificationsById[id];
789
- if (ibn === void 0) {
790
- break;
791
- }
792
- computed.inboxNotificationsById[id] = {
793
- ...ibn,
754
+ for (const id in output.inboxNotifications) {
755
+ output.inboxNotifications[id] = {
756
+ ...output.inboxNotifications[id],
794
757
  readAt: optimisticUpdate.readAt
795
758
  };
796
759
  }
797
760
  break;
798
761
  }
799
762
  case "delete-inbox-notification": {
800
- delete computed.inboxNotificationsById[optimisticUpdate.inboxNotificationId];
763
+ const {
764
+ [optimisticUpdate.inboxNotificationId]: _,
765
+ ...inboxNotifications
766
+ } = output.inboxNotifications;
767
+ output.inboxNotifications = inboxNotifications;
801
768
  break;
802
769
  }
803
770
  case "delete-all-inbox-notifications": {
804
- computed.inboxNotificationsById = {};
771
+ output.inboxNotifications = {};
805
772
  break;
806
773
  }
807
774
  case "update-notification-settings": {
808
- const settings = computed.notificationSettingsByRoomId[optimisticUpdate.roomId];
809
- if (settings === void 0) {
810
- break;
811
- }
812
- computed.notificationSettingsByRoomId[optimisticUpdate.roomId] = {
813
- ...settings,
775
+ output.notificationSettings[optimisticUpdate.roomId] = {
776
+ ...output.notificationSettings[optimisticUpdate.roomId],
814
777
  ...optimisticUpdate.settings
815
778
  };
816
779
  }
@@ -818,26 +781,23 @@ function internalToExternalState(state) {
818
781
  }
819
782
  const cleanedThreads = (
820
783
  // Don't expose any soft-deleted threads
821
- Object.values(computed.threadsById).filter((thread) => !thread.deletedAt).filter(
822
- (thread) => (
823
- // Only keep a thread if there is at least one non-deleted comment
824
- thread.comments.some((c) => c.deletedAt === void 0)
825
- )
784
+ Object.values(output.threads).filter(
785
+ (thread) => !thread.deletedAt
826
786
  )
827
787
  );
828
788
  const cleanedNotifications = (
829
789
  // Sort so that the most recent notifications are first
830
- Object.values(computed.inboxNotificationsById).filter(
831
- (ibn) => ibn.kind === "thread" ? computed.threadsById[ibn.threadId] && computed.threadsById[ibn.threadId]?.deletedAt === void 0 : true
832
- ).sort((a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime())
790
+ Object.values(output.inboxNotifications).sort(
791
+ (a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime()
792
+ )
833
793
  );
834
794
  return {
835
795
  inboxNotifications: cleanedNotifications,
836
- inboxNotificationsById: computed.inboxNotificationsById,
837
- notificationSettingsByRoomId: computed.notificationSettingsByRoomId,
796
+ inboxNotificationsById: output.inboxNotifications,
797
+ notificationSettingsByRoomId: output.notificationSettings,
838
798
  queries: state.queries,
839
799
  threads: cleanedThreads,
840
- threadsById: computed.threadsById,
800
+ threadsById: output.threads,
841
801
  versionsByRoomId: state.versionsByRoomId
842
802
  };
843
803
  }
@@ -954,14 +914,17 @@ function applyDeleteComment(thread, commentId, deletedAt) {
954
914
  (comment) => comment.id === commentId ? {
955
915
  ...comment,
956
916
  deletedAt,
957
- body: void 0
917
+ // We optimistically remove the comment body and attachments when marking it as deleted
918
+ body: void 0,
919
+ attachments: []
958
920
  } : comment
959
921
  );
960
- if (updatedComments.every((comment) => comment.deletedAt !== void 0)) {
922
+ if (!updatedComments.some((comment) => comment.deletedAt === void 0)) {
961
923
  return {
962
924
  ...thread,
963
925
  deletedAt,
964
- updatedAt: deletedAt
926
+ updatedAt: deletedAt,
927
+ comments: []
965
928
  };
966
929
  }
967
930
  return {
@@ -1220,21 +1183,23 @@ function makeExtrasForClient(client) {
1220
1183
  void waitUntilInboxNotificationsLoaded().catch(() => {
1221
1184
  });
1222
1185
  }
1223
- function startPolling() {
1224
- pollerSubscribers++;
1225
- poller.start(POLLING_INTERVAL);
1226
- return () => {
1227
- if (pollerSubscribers <= 0) {
1228
- console.warn(
1229
- `Internal unexpected behavior. Cannot decrease subscriber count for query "${INBOX_NOTIFICATIONS_QUERY}"`
1230
- );
1231
- return;
1232
- }
1233
- pollerSubscribers--;
1234
- if (pollerSubscribers <= 0) {
1235
- poller.stop();
1236
- }
1237
- };
1186
+ function useEnableInboxNotificationsPolling() {
1187
+ useEffect3(() => {
1188
+ pollerSubscribers++;
1189
+ poller.start(POLLING_INTERVAL);
1190
+ return () => {
1191
+ if (pollerSubscribers <= 0) {
1192
+ console.warn(
1193
+ `Internal unexpected behavior. Cannot decrease subscriber count for query "${INBOX_NOTIFICATIONS_QUERY}"`
1194
+ );
1195
+ return;
1196
+ }
1197
+ pollerSubscribers--;
1198
+ if (pollerSubscribers <= 0) {
1199
+ poller.stop();
1200
+ }
1201
+ };
1202
+ }, []);
1238
1203
  }
1239
1204
  const userThreadsPoller = makePoller(refreshUserThreads);
1240
1205
  let isFetchingUserThreadsUpdates = false;
@@ -1319,7 +1284,7 @@ function makeExtrasForClient(client) {
1319
1284
  }
1320
1285
  return {
1321
1286
  store,
1322
- startPolling,
1287
+ useEnableInboxNotificationsPolling,
1323
1288
  waitUntilInboxNotificationsLoaded,
1324
1289
  loadInboxNotifications,
1325
1290
  incrementUserThreadsQuerySubscribers,
@@ -1364,9 +1329,11 @@ function makeLiveblocksContextBundle(client) {
1364
1329
  return bundle;
1365
1330
  }
1366
1331
  function useInboxNotifications_withClient(client) {
1367
- const { loadInboxNotifications, store, startPolling } = getExtrasForClient(client);
1368
- useEffect3(loadInboxNotifications, [loadInboxNotifications]);
1369
- useEffect3(startPolling, [startPolling]);
1332
+ const { loadInboxNotifications, store, useEnableInboxNotificationsPolling } = getExtrasForClient(client);
1333
+ useEffect3(() => {
1334
+ loadInboxNotifications();
1335
+ }, [loadInboxNotifications]);
1336
+ useEnableInboxNotificationsPolling();
1370
1337
  return useSyncExternalStoreWithSelector(
1371
1338
  store.subscribeInboxNotifications,
1372
1339
  store.getInboxNotificationsAsync,
@@ -1384,9 +1351,11 @@ function useInboxNotificationsSuspense_withClient(client) {
1384
1351
  return result;
1385
1352
  }
1386
1353
  function useUnreadInboxNotificationsCount_withClient(client) {
1387
- const { store, loadInboxNotifications, startPolling } = getExtrasForClient(client);
1388
- useEffect3(loadInboxNotifications, [loadInboxNotifications]);
1389
- useEffect3(startPolling, [startPolling]);
1354
+ const { store, loadInboxNotifications, useEnableInboxNotificationsPolling } = getExtrasForClient(client);
1355
+ useEffect3(() => {
1356
+ loadInboxNotifications();
1357
+ }, [loadInboxNotifications]);
1358
+ useEnableInboxNotificationsPolling();
1390
1359
  return useSyncExternalStoreWithSelector(
1391
1360
  store.subscribeInboxNotifications,
1392
1361
  store.getInboxNotificationsAsync,
@@ -1934,6 +1903,7 @@ var UpdateNotificationSettingsError = class extends Error {
1934
1903
  // src/room.tsx
1935
1904
  import { shallow as shallow4 } from "@liveblocks/client";
1936
1905
  import {
1906
+ assert as assert2,
1937
1907
  CommentsApiError,
1938
1908
  console as console3,
1939
1909
  createCommentId,
@@ -2138,7 +2108,7 @@ function makeExtrasForClient2(client) {
2138
2108
  }
2139
2109
  }
2140
2110
  async function getRoomVersions(room, { retryCount } = { retryCount: 0 }) {
2141
- const queryKey = makeVersionsQueryKey(room.id);
2111
+ const queryKey = getVersionsQueryKey(room.id);
2142
2112
  const existingRequest = requestsByQuery.get(queryKey);
2143
2113
  if (existingRequest !== void 0) return existingRequest;
2144
2114
  const request = room[kInternal2].listTextVersions();
@@ -2289,6 +2259,7 @@ function makeRoomContextBundle(client) {
2289
2259
  useRemoveReaction,
2290
2260
  useMarkThreadAsRead,
2291
2261
  useThreadSubscription,
2262
+ useAttachmentUrl,
2292
2263
  useHistoryVersions,
2293
2264
  useHistoryVersionData,
2294
2265
  useRoomNotificationSettings,
@@ -2334,6 +2305,7 @@ function makeRoomContextBundle(client) {
2334
2305
  useRemoveReaction,
2335
2306
  useMarkThreadAsRead,
2336
2307
  useThreadSubscription,
2308
+ useAttachmentUrl: useAttachmentUrlSuspense,
2337
2309
  // TODO: useHistoryVersionData: useHistoryVersionDataSuspense,
2338
2310
  useHistoryVersions: useHistoryVersionsSuspense,
2339
2311
  useRoomNotificationSettings: useRoomNotificationSettingsSuspense,
@@ -2800,6 +2772,7 @@ function useCreateThread() {
2800
2772
  (options) => {
2801
2773
  const body = options.body;
2802
2774
  const metadata = options.metadata ?? {};
2775
+ const attachments = options.attachments;
2803
2776
  const threadId = createThreadId();
2804
2777
  const commentId = createCommentId();
2805
2778
  const createdAt = /* @__PURE__ */ new Date();
@@ -2811,7 +2784,8 @@ function useCreateThread() {
2811
2784
  type: "comment",
2812
2785
  userId: getCurrentUserId(room),
2813
2786
  body,
2814
- reactions: []
2787
+ reactions: [],
2788
+ attachments: attachments ?? []
2815
2789
  };
2816
2790
  const newThread = {
2817
2791
  id: threadId,
@@ -2829,7 +2803,8 @@ function useCreateThread() {
2829
2803
  thread: newThread,
2830
2804
  roomId: room.id
2831
2805
  });
2832
- room.createThread({ threadId, commentId, body, metadata }).then(
2806
+ const attachmentIds = attachments?.map((attachment) => attachment.id);
2807
+ room.createThread({ threadId, commentId, body, metadata, attachmentIds }).then(
2833
2808
  (thread) => {
2834
2809
  store.createThread(optimisticUpdateId, thread);
2835
2810
  },
@@ -2927,7 +2902,7 @@ function useCreateComment() {
2927
2902
  const client = useClient();
2928
2903
  const room = useRoom();
2929
2904
  return React5.useCallback(
2930
- ({ threadId, body }) => {
2905
+ ({ threadId, body, attachments }) => {
2931
2906
  const commentId = createCommentId();
2932
2907
  const createdAt = /* @__PURE__ */ new Date();
2933
2908
  const comment = {
@@ -2938,14 +2913,16 @@ function useCreateComment() {
2938
2913
  createdAt,
2939
2914
  userId: getCurrentUserId(room),
2940
2915
  body,
2941
- reactions: []
2916
+ reactions: [],
2917
+ attachments: attachments ?? []
2942
2918
  };
2943
2919
  const { store, onMutationFailure } = getExtrasForClient2(client);
2944
2920
  const optimisticUpdateId = store.addOptimisticUpdate({
2945
2921
  type: "create-comment",
2946
2922
  comment
2947
2923
  });
2948
- room.createComment({ threadId, commentId, body }).then(
2924
+ const attachmentIds = attachments?.map((attachment) => attachment.id);
2925
+ room.createComment({ threadId, commentId, body, attachmentIds }).then(
2949
2926
  (newComment) => {
2950
2927
  store.createComment(newComment, optimisticUpdateId);
2951
2928
  },
@@ -2969,7 +2946,7 @@ function useEditComment() {
2969
2946
  const client = useClient();
2970
2947
  const room = useRoom();
2971
2948
  return React5.useCallback(
2972
- ({ threadId, commentId, body }) => {
2949
+ ({ threadId, commentId, body, attachments }) => {
2973
2950
  const editedAt = /* @__PURE__ */ new Date();
2974
2951
  const { store, onMutationFailure } = getExtrasForClient2(client);
2975
2952
  const thread = store.getThreads().threadsById[threadId];
@@ -2993,10 +2970,12 @@ function useEditComment() {
2993
2970
  comment: {
2994
2971
  ...comment,
2995
2972
  editedAt,
2996
- body
2973
+ body,
2974
+ attachments: attachments ?? []
2997
2975
  }
2998
2976
  });
2999
- room.editComment({ threadId, commentId, body }).then(
2977
+ const attachmentIds = attachments?.map((attachment) => attachment.id);
2978
+ room.editComment({ threadId, commentId, body, attachmentIds }).then(
3000
2979
  (editedComment) => {
3001
2980
  store.editComment(threadId, optimisticUpdateId, editedComment);
3002
2981
  },
@@ -3356,44 +3335,34 @@ function useHistoryVersionData(versionId) {
3356
3335
  function useHistoryVersions() {
3357
3336
  const client = useClient();
3358
3337
  const room = useRoom();
3338
+ const queryKey = getVersionsQueryKey(room.id);
3359
3339
  const { store, getRoomVersions } = getExtrasForClient2(client);
3360
- const getter = React5.useCallback(
3361
- () => store.getVersionsAsync(room.id),
3362
- [store, room.id]
3363
- );
3364
3340
  React5.useEffect(() => {
3365
3341
  void getRoomVersions(room);
3366
3342
  }, [room]);
3367
- const state = useSyncExternalStoreWithSelector2(
3368
- store.subscribeVersions,
3369
- getter,
3370
- getter,
3371
- identity2,
3372
- shallow4
3373
- );
3374
- return state;
3375
- }
3376
- function useHistoryVersionsSuspense() {
3377
- const client = useClient();
3378
- const room = useRoom();
3379
- const { store } = getExtrasForClient2(client);
3380
- const getter = React5.useCallback(
3381
- () => store.getVersionsAsync(room.id),
3382
- [store, room.id]
3343
+ const selector = React5.useCallback(
3344
+ (state2) => {
3345
+ const query = state2.queries[queryKey];
3346
+ if (query === void 0 || query.isLoading) {
3347
+ return {
3348
+ isLoading: true
3349
+ };
3350
+ }
3351
+ return {
3352
+ versions: state2.versionsByRoomId[room.id],
3353
+ isLoading: false,
3354
+ error: query.error
3355
+ };
3356
+ },
3357
+ [room, queryKey]
3358
+ // eslint-disable-line react-hooks/exhaustive-deps
3383
3359
  );
3384
3360
  const state = useSyncExternalStoreWithSelector2(
3385
3361
  store.subscribeVersions,
3386
- getter,
3387
- getter,
3388
- identity2,
3389
- shallow4
3362
+ store.getVersions,
3363
+ store.getVersions,
3364
+ selector
3390
3365
  );
3391
- if (state.isLoading) {
3392
- const { getRoomVersions } = getExtrasForClient2(client);
3393
- throw getRoomVersions(room);
3394
- } else if (state.error) {
3395
- throw state.error;
3396
- }
3397
3366
  return state;
3398
3367
  }
3399
3368
  function useUpdateRoomNotificationSettings() {
@@ -3526,12 +3495,104 @@ function useThreadsSuspense(options = {
3526
3495
  useScrollToCommentOnLoadEffect(scrollOnLoad, state);
3527
3496
  return state;
3528
3497
  }
3498
+ function selectorFor_useAttachmentUrl(state) {
3499
+ if (state === void 0 || state?.isLoading) {
3500
+ return state ?? { isLoading: true };
3501
+ }
3502
+ if (state.error) {
3503
+ return state;
3504
+ }
3505
+ assert2(state.data !== void 0, "Unexpected missing attachment URL");
3506
+ return {
3507
+ isLoading: false,
3508
+ url: state.data
3509
+ };
3510
+ }
3511
+ function useAttachmentUrl(attachmentId) {
3512
+ const room = useRoom();
3513
+ const { attachmentUrlsStore } = room[kInternal2];
3514
+ const getAttachmentUrlState = React5.useCallback(
3515
+ () => attachmentUrlsStore.getState(attachmentId),
3516
+ [attachmentUrlsStore, attachmentId]
3517
+ );
3518
+ React5.useEffect(() => {
3519
+ void attachmentUrlsStore.get(attachmentId);
3520
+ }, [attachmentUrlsStore, attachmentId]);
3521
+ return useSyncExternalStoreWithSelector2(
3522
+ attachmentUrlsStore.subscribe,
3523
+ getAttachmentUrlState,
3524
+ getAttachmentUrlState,
3525
+ selectorFor_useAttachmentUrl,
3526
+ shallow4
3527
+ );
3528
+ }
3529
+ function useAttachmentUrlSuspense(attachmentId) {
3530
+ const room = useRoom();
3531
+ const { attachmentUrlsStore } = room[kInternal2];
3532
+ const getAttachmentUrlState = React5.useCallback(
3533
+ () => attachmentUrlsStore.getState(attachmentId),
3534
+ [attachmentUrlsStore, attachmentId]
3535
+ );
3536
+ const attachmentUrlState = getAttachmentUrlState();
3537
+ if (!attachmentUrlState || attachmentUrlState.isLoading) {
3538
+ throw attachmentUrlsStore.get(attachmentId);
3539
+ }
3540
+ if (attachmentUrlState.error) {
3541
+ throw attachmentUrlState.error;
3542
+ }
3543
+ const state = useSyncExternalStore2(
3544
+ attachmentUrlsStore.subscribe,
3545
+ getAttachmentUrlState,
3546
+ getAttachmentUrlState
3547
+ );
3548
+ assert2(state !== void 0, "Unexpected missing state");
3549
+ assert2(!state.isLoading, "Unexpected loading state");
3550
+ assert2(!state.error, "Unexpected error state");
3551
+ return {
3552
+ isLoading: false,
3553
+ url: state.data,
3554
+ error: void 0
3555
+ };
3556
+ }
3557
+ function useHistoryVersionsSuspense() {
3558
+ const client = useClient();
3559
+ const room = useRoom();
3560
+ const queryKey = getVersionsQueryKey(room.id);
3561
+ const { store, getRoomVersions } = getExtrasForClient2(client);
3562
+ const query = store.getVersions().queries[queryKey];
3563
+ if (query === void 0 || query.isLoading) {
3564
+ throw getRoomVersions(room);
3565
+ }
3566
+ if (query.error) {
3567
+ throw query.error;
3568
+ }
3569
+ const selector = React5.useCallback(
3570
+ (state2) => {
3571
+ return {
3572
+ versions: state2.versionsByRoomId[room.id],
3573
+ isLoading: false
3574
+ };
3575
+ },
3576
+ [room, queryKey]
3577
+ // eslint-disable-line react-hooks/exhaustive-deps
3578
+ );
3579
+ const state = useSyncExternalStoreWithSelector2(
3580
+ store.subscribeVersions,
3581
+ store.getVersions,
3582
+ store.getVersions,
3583
+ selector
3584
+ );
3585
+ return state;
3586
+ }
3529
3587
  function createRoomContext(client) {
3530
3588
  return getOrCreateRoomContextBundle(client);
3531
3589
  }
3532
3590
  function generateQueryKey(roomId, options) {
3533
3591
  return `${roomId}-${stringify2(options ?? {})}`;
3534
3592
  }
3593
+ function getVersionsQueryKey(roomId) {
3594
+ return `${roomId}-VERSIONS`;
3595
+ }
3535
3596
  var _RoomProvider = RoomProvider;
3536
3597
  var _useBroadcastEvent = useBroadcastEvent;
3537
3598
  var _useOthersListener = useOthersListener;
@@ -3622,6 +3683,8 @@ export {
3622
3683
  useUpdateRoomNotificationSettings,
3623
3684
  useOthersConnectionIdsSuspense,
3624
3685
  useStorageStatusSuspense,
3686
+ useAttachmentUrl,
3687
+ useAttachmentUrlSuspense,
3625
3688
  createRoomContext,
3626
3689
  _RoomProvider,
3627
3690
  _useBroadcastEvent,
@@ -3652,4 +3715,4 @@ export {
3652
3715
  _useStorageRoot,
3653
3716
  _useUpdateMyPresence
3654
3717
  };
3655
- //# sourceMappingURL=chunk-QC6HYSYS.mjs.map
3718
+ //# sourceMappingURL=chunk-OBLKSEC3.mjs.map