@liveblocks/react 2.24.0-deque1 → 2.24.0

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.
@@ -107,7 +107,7 @@ import {
107
107
  kInternal as kInternal2,
108
108
  makePoller,
109
109
  raise,
110
- shallow as shallow4
110
+ shallow as shallow3
111
111
  } from "@liveblocks/core";
112
112
  import {
113
113
  createContext as createContext2,
@@ -132,8 +132,8 @@ var config = {
132
132
  USER_THREADS_MAX_STALE_TIME: 30 * SECONDS,
133
133
  HISTORY_VERSIONS_POLL_INTERVAL: 1 * MINUTES,
134
134
  HISTORY_VERSIONS_MAX_STALE_TIME: 5 * SECONDS,
135
- NOTIFICATION_SETTINGS_POLL_INTERVAL: 1 * MINUTES,
136
- NOTIFICATION_SETTINGS_MAX_STALE_TIME: 5 * SECONDS,
135
+ ROOM_SUBSCRIPTION_SETTINGS_POLL_INTERVAL: 1 * MINUTES,
136
+ ROOM_SUBSCRIPTION_SETTINGS_MAX_STALE_TIME: 5 * SECONDS,
137
137
  USER_NOTIFICATION_SETTINGS_INTERVAL: 5 * MINUTES,
138
138
  USER_NOTIFICATION_SETTINGS_MAX_STALE_TIME: 1 * MINUTES
139
139
  };
@@ -232,19 +232,23 @@ var use = (
232
232
 
233
233
  // src/umbrella-store.ts
234
234
  import {
235
+ assertNever,
235
236
  autoRetry,
236
237
  batch as batch2,
237
238
  compactObject,
238
239
  console as console2,
239
- createUserNotificationSettings,
240
+ createNotificationSettings,
240
241
  DefaultMap,
241
242
  DerivedSignal,
243
+ getMentionedIdsFromCommentBody,
244
+ getSubscriptionKey,
242
245
  kInternal,
243
246
  MutableSignal as MutableSignal2,
244
247
  nanoid,
245
248
  nn,
246
- patchUserNotificationSettings,
247
- shallow as shallow3,
249
+ patchNotificationSettings,
250
+ shallow,
251
+ shallow2,
248
252
  Signal,
249
253
  stableStringify
250
254
  } from "@liveblocks/core";
@@ -266,21 +270,6 @@ function autobind(self) {
266
270
  } while ((obj = Reflect.getPrototypeOf(obj)) && obj !== Object.prototype);
267
271
  }
268
272
 
269
- // src/lib/shallow2.ts
270
- import { isPlainObject, shallow } from "@liveblocks/core";
271
- function shallow2(a, b) {
272
- if (!isPlainObject(a) || !isPlainObject(b)) {
273
- return shallow(a, b);
274
- }
275
- const keysA = Object.keys(a);
276
- if (keysA.length !== Object.keys(b).length) {
277
- return false;
278
- }
279
- return keysA.every(
280
- (key) => Object.prototype.hasOwnProperty.call(b, key) && shallow(a[key], b[key])
281
- );
282
- }
283
-
284
273
  // src/ThreadDB.ts
285
274
  import { batch, MutableSignal, SortedList } from "@liveblocks/core";
286
275
 
@@ -431,7 +420,9 @@ var ThreadDB = class _ThreadDB {
431
420
  if (roomId !== void 0) {
432
421
  crit.push((t) => t.roomId === roomId);
433
422
  }
434
- crit.push(makeThreadsFilter(query));
423
+ if (query !== void 0) {
424
+ crit.push(makeThreadsFilter(query));
425
+ }
435
426
  return Array.from(index.filter((t) => crit.every((pred) => pred(t))));
436
427
  }
437
428
  };
@@ -667,7 +658,45 @@ function createStore_forNotifications() {
667
658
  upsert
668
659
  };
669
660
  }
670
- function createStore_forRoomNotificationSettings(updates) {
661
+ function createStore_forSubscriptions(updates, threads) {
662
+ const baseSignal = new MutableSignal2(/* @__PURE__ */ new Map());
663
+ function applyDelta(newSubscriptions, deletedSubscriptions) {
664
+ baseSignal.mutate((lut) => {
665
+ let mutated = false;
666
+ for (const s of newSubscriptions) {
667
+ lut.set(getSubscriptionKey(s), s);
668
+ mutated = true;
669
+ }
670
+ for (const s of deletedSubscriptions) {
671
+ lut.delete(getSubscriptionKey(s));
672
+ mutated = true;
673
+ }
674
+ return mutated;
675
+ });
676
+ }
677
+ function create(subscription) {
678
+ baseSignal.mutate((lut) => {
679
+ lut.set(getSubscriptionKey(subscription), subscription);
680
+ });
681
+ }
682
+ function deleteOne(subscriptionKey) {
683
+ baseSignal.mutate((lut) => {
684
+ lut.delete(subscriptionKey);
685
+ });
686
+ }
687
+ return {
688
+ signal: DerivedSignal.from(
689
+ baseSignal,
690
+ updates,
691
+ (base, updates2) => applyOptimisticUpdates_forSubscriptions(base, threads, updates2)
692
+ ),
693
+ // Mutations
694
+ applyDelta,
695
+ create,
696
+ delete: deleteOne
697
+ };
698
+ }
699
+ function createStore_forRoomSubscriptionSettings(updates) {
671
700
  const baseSignal = new MutableSignal2(/* @__PURE__ */ new Map());
672
701
  function update(roomId, settings) {
673
702
  baseSignal.mutate((lut) => {
@@ -678,7 +707,7 @@ function createStore_forRoomNotificationSettings(updates) {
678
707
  signal: DerivedSignal.from(
679
708
  baseSignal,
680
709
  updates,
681
- (base, updates2) => applyOptimisticUpdates_forSettings(base, updates2)
710
+ (base, updates2) => applyOptimisticUpdates_forRoomSubscriptionSettings(base, updates2)
682
711
  ),
683
712
  // Mutations
684
713
  update
@@ -730,9 +759,9 @@ function createStore_forPermissionHints() {
730
759
  update
731
760
  };
732
761
  }
733
- function createStore_forUserNotificationSettings(updates) {
762
+ function createStore_forNotificationSettings(updates) {
734
763
  const signal = new Signal(
735
- createUserNotificationSettings({})
764
+ createNotificationSettings({})
736
765
  );
737
766
  function update(settings) {
738
767
  signal.set(settings);
@@ -741,7 +770,7 @@ function createStore_forUserNotificationSettings(updates) {
741
770
  signal: DerivedSignal.from(
742
771
  signal,
743
772
  updates,
744
- (base, updates2) => applyOptimisticUpdates_forUserNotificationSettings(base, updates2)
773
+ (base, updates2) => applyOptimisticUpdates_forNotificationSettings(base, updates2)
745
774
  ),
746
775
  // Mutations
747
776
  update
@@ -780,16 +809,18 @@ var UmbrellaStore = class {
780
809
  //
781
810
  // Mutate inputs... ...observe clean/consistent output!
782
811
  //
783
- // .-> Base ThreadDB ---------+ +----> Clean threads by ID (Part 1)
812
+ // .-> Base ThreadDB ---------+ +-------> Clean threads by ID (Part 1)
784
813
  // / | |
785
- // mutate ----> Base Notifications --+ | | +--> Clean notifications (Part 1)
786
- // \ | | | | & notifications by ID
814
+ // mutate ----> Base Notifications --+ | | +-----> Clean notifications (Part 1)
815
+ // \ | | | | & notifications by ID
787
816
  // | \ | | Apply | |
788
- // | `-> OptimisticUpdates --+--+--> Optimistic --+-+--> Room Notification Settings (Part 2)
789
- // \ | Updates | |
790
- // `------- etc etc ---------+ | +--> History Versions (Part 3)
791
- // ^ |
792
- // | +-----> User Notification Settings (Part 4)
817
+ // | `-> OptimisticUpdates --+--+--> Optimistic -+-+-+-+-> Subscriptions (Part 2)
818
+ // \ | Updates | | |
819
+ // `------- etc etc ---------+ | | +-> History Versions (Part 3)
820
+ // ^ | |
821
+ // | | +---> Room Subscription Settings (Part 4)
822
+ // | |
823
+ // | +-------> Notification Settings (Part 5)
793
824
  // |
794
825
  // |
795
826
  // | ^ ^
@@ -807,11 +838,12 @@ var UmbrellaStore = class {
807
838
  threads;
808
839
  // Exposes its signal under `.signal` prop
809
840
  notifications;
810
- roomNotificationSettings;
841
+ subscriptions;
842
+ roomSubscriptionSettings;
811
843
  // prettier-ignore
812
844
  historyVersions;
813
845
  permissionHints;
814
- userNotificationSettings;
846
+ notificationSettings;
815
847
  optimisticUpdates;
816
848
  //
817
849
  // Output signals.
@@ -832,8 +864,8 @@ var UmbrellaStore = class {
832
864
  #userThreadsLastRequestedAt = null;
833
865
  // Room versions
834
866
  #roomVersionsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
835
- // User Notification Settings
836
- #userNotificationSettings;
867
+ // Notification Settings
868
+ #notificationSettings;
837
869
  constructor(client) {
838
870
  this.#client = client[kInternal].as();
839
871
  this.optimisticUpdates = createStore_forOptimistic(this.#client);
@@ -841,7 +873,11 @@ var UmbrellaStore = class {
841
873
  this.#notificationsPaginationState = new PaginatedResource(
842
874
  async (cursor) => {
843
875
  const result = await this.#client.getInboxNotifications({ cursor });
844
- this.updateThreadifications(result.threads, result.inboxNotifications);
876
+ this.updateThreadifications(
877
+ result.threads,
878
+ result.inboxNotifications,
879
+ result.subscriptions
880
+ );
845
881
  if (this.#notificationsLastRequestedAt === null) {
846
882
  this.#notificationsLastRequestedAt = result.requestedAt;
847
883
  }
@@ -849,19 +885,23 @@ var UmbrellaStore = class {
849
885
  return nextCursor;
850
886
  }
851
887
  );
852
- const userNotificationSettingsFetcher = async () => {
888
+ const notificationSettingsFetcher = async () => {
853
889
  const result = await this.#client.getNotificationSettings();
854
- this.userNotificationSettings.update(result);
890
+ this.notificationSettings.update(result);
855
891
  };
856
- this.userNotificationSettings = createStore_forUserNotificationSettings(
892
+ this.notificationSettings = createStore_forNotificationSettings(
857
893
  this.optimisticUpdates.signal
858
894
  );
859
- this.#userNotificationSettings = new SinglePageResource(
860
- userNotificationSettingsFetcher
895
+ this.#notificationSettings = new SinglePageResource(
896
+ notificationSettingsFetcher
861
897
  );
862
898
  this.threads = new ThreadDB();
899
+ this.subscriptions = createStore_forSubscriptions(
900
+ this.optimisticUpdates.signal,
901
+ this.threads
902
+ );
863
903
  this.notifications = createStore_forNotifications();
864
- this.roomNotificationSettings = createStore_forRoomNotificationSettings(
904
+ this.roomSubscriptionSettings = createStore_forRoomSubscriptionSettings(
865
905
  this.optimisticUpdates.signal
866
906
  );
867
907
  this.historyVersions = createStore_forHistoryVersions();
@@ -878,7 +918,15 @@ var UmbrellaStore = class {
878
918
  sortedNotifications: s.sortedNotifications,
879
919
  notificationsById: s.notificationsById
880
920
  }),
881
- shallow3
921
+ shallow
922
+ );
923
+ const threadSubscriptions = DerivedSignal.from(
924
+ notifications,
925
+ this.subscriptions.signal,
926
+ (n, s) => ({
927
+ subscriptions: s,
928
+ notifications: n.sortedNotifications
929
+ })
882
930
  );
883
931
  const loadingUserThreads = new DefaultMap(
884
932
  (queryKey) => {
@@ -890,7 +938,8 @@ var UmbrellaStore = class {
890
938
  });
891
939
  this.updateThreadifications(
892
940
  result.threads,
893
- result.inboxNotifications
941
+ result.inboxNotifications,
942
+ result.subscriptions
894
943
  );
895
944
  this.permissionHints.update(result.permissionHints);
896
945
  if (this.#userThreadsLastRequestedAt === null) {
@@ -933,7 +982,8 @@ var UmbrellaStore = class {
933
982
  });
934
983
  this.updateThreadifications(
935
984
  result.threads,
936
- result.inboxNotifications
985
+ result.inboxNotifications,
986
+ result.subscriptions
937
987
  );
938
988
  this.permissionHints.update(result.permissionHints);
939
989
  const lastRequestedAt = this.#roomThreadsLastRequestedAtByRoom.get(roomId);
@@ -983,28 +1033,30 @@ var UmbrellaStore = class {
983
1033
  }),
984
1034
  waitUntilLoaded: this.#notificationsPaginationState.waitUntilLoaded
985
1035
  };
986
- const settingsByRoomId = new DefaultMap((roomId) => {
987
- const resource = new SinglePageResource(async () => {
988
- const room = this.#client.getRoom(roomId);
989
- if (room === null) {
990
- throw new Error(`Room '${roomId}' is not available on client`);
991
- }
992
- const result = await room.getNotificationSettings();
993
- this.roomNotificationSettings.update(roomId, result);
994
- });
995
- const signal = DerivedSignal.from(() => {
996
- const result = resource.get();
997
- if (result.isLoading || result.error) {
998
- return result;
999
- } else {
1000
- return ASYNC_OK(
1001
- "settings",
1002
- nn(this.roomNotificationSettings.signal.get()[roomId])
1003
- );
1004
- }
1005
- }, shallow3);
1006
- return { signal, waitUntilLoaded: resource.waitUntilLoaded };
1007
- });
1036
+ const roomSubscriptionSettingsByRoomId = new DefaultMap(
1037
+ (roomId) => {
1038
+ const resource = new SinglePageResource(async () => {
1039
+ const room = this.#client.getRoom(roomId);
1040
+ if (room === null) {
1041
+ throw new Error(`Room '${roomId}' is not available on client`);
1042
+ }
1043
+ const result = await room.getSubscriptionSettings();
1044
+ this.roomSubscriptionSettings.update(roomId, result);
1045
+ });
1046
+ const signal = DerivedSignal.from(() => {
1047
+ const result = resource.get();
1048
+ if (result.isLoading || result.error) {
1049
+ return result;
1050
+ } else {
1051
+ return ASYNC_OK(
1052
+ "settings",
1053
+ nn(this.roomSubscriptionSettings.signal.get()[roomId])
1054
+ );
1055
+ }
1056
+ }, shallow);
1057
+ return { signal, waitUntilLoaded: resource.waitUntilLoaded };
1058
+ }
1059
+ );
1008
1060
  const versionsByRoomId = new DefaultMap(
1009
1061
  (roomId) => {
1010
1062
  const resource = new SinglePageResource(async () => {
@@ -1032,22 +1084,22 @@ var UmbrellaStore = class {
1032
1084
  Object.values(this.historyVersions.signal.get()[roomId] ?? {})
1033
1085
  );
1034
1086
  }
1035
- }, shallow3);
1087
+ }, shallow);
1036
1088
  return { signal, waitUntilLoaded: resource.waitUntilLoaded };
1037
1089
  }
1038
1090
  );
1039
- const userNotificationSettings = {
1091
+ const notificationSettings = {
1040
1092
  signal: DerivedSignal.from(() => {
1041
- const result = this.#userNotificationSettings.get();
1093
+ const result = this.#notificationSettings.get();
1042
1094
  if (result.isLoading || result.error) {
1043
1095
  return result;
1044
1096
  }
1045
1097
  return ASYNC_OK(
1046
1098
  "settings",
1047
- nn(this.userNotificationSettings.signal.get())
1099
+ nn(this.notificationSettings.signal.get())
1048
1100
  );
1049
- }, shallow3),
1050
- waitUntilLoaded: this.#userNotificationSettings.waitUntilLoaded
1101
+ }, shallow),
1102
+ waitUntilLoaded: this.#notificationSettings.waitUntilLoaded
1051
1103
  };
1052
1104
  this.outputs = {
1053
1105
  threadifications,
@@ -1056,9 +1108,10 @@ var UmbrellaStore = class {
1056
1108
  loadingUserThreads,
1057
1109
  notifications,
1058
1110
  loadingNotifications,
1059
- settingsByRoomId,
1111
+ roomSubscriptionSettingsByRoomId,
1060
1112
  versionsByRoomId,
1061
- userNotificationSettings
1113
+ notificationSettings,
1114
+ threadSubscriptions
1062
1115
  };
1063
1116
  autobind(this);
1064
1117
  }
@@ -1100,6 +1153,26 @@ var UmbrellaStore = class {
1100
1153
  this.notifications.clear();
1101
1154
  });
1102
1155
  }
1156
+ /**
1157
+ * Creates an existing subscription, replacing the corresponding
1158
+ * optimistic update.
1159
+ */
1160
+ createSubscription(subscription, optimisticId) {
1161
+ batch2(() => {
1162
+ this.optimisticUpdates.remove(optimisticId);
1163
+ this.subscriptions.create(subscription);
1164
+ });
1165
+ }
1166
+ /**
1167
+ * Deletes an existing subscription, replacing the corresponding
1168
+ * optimistic update.
1169
+ */
1170
+ deleteSubscription(subscriptionKey, optimisticId) {
1171
+ batch2(() => {
1172
+ this.optimisticUpdates.remove(optimisticId);
1173
+ this.subscriptions.delete(subscriptionKey);
1174
+ });
1175
+ }
1103
1176
  /**
1104
1177
  * Creates an new thread, replacing the corresponding optimistic update.
1105
1178
  */
@@ -1201,20 +1274,21 @@ var UmbrellaStore = class {
1201
1274
  deletedAt
1202
1275
  );
1203
1276
  }
1204
- updateThreadifications(threads, notifications, deletedThreads = [], deletedNotifications = []) {
1277
+ updateThreadifications(threads, notifications, subscriptions, deletedThreads = [], deletedNotifications = [], deletedSubscriptions = []) {
1205
1278
  batch2(() => {
1206
1279
  this.threads.applyDelta(threads, deletedThreads);
1207
1280
  this.notifications.applyDelta(notifications, deletedNotifications);
1281
+ this.subscriptions.applyDelta(subscriptions, deletedSubscriptions);
1208
1282
  });
1209
1283
  }
1210
1284
  /**
1211
- * Updates existing notification setting for a room with a new value,
1285
+ * Updates existing subscription settings for a room with a new value,
1212
1286
  * replacing the corresponding optimistic update.
1213
1287
  */
1214
- updateRoomNotificationSettings(roomId, optimisticId, settings) {
1288
+ updateRoomSubscriptionSettings(roomId, optimisticId, settings) {
1215
1289
  batch2(() => {
1216
1290
  this.optimisticUpdates.remove(optimisticId);
1217
- this.roomNotificationSettings.update(roomId, settings);
1291
+ this.roomSubscriptionSettings.update(roomId, settings);
1218
1292
  });
1219
1293
  }
1220
1294
  async fetchNotificationsDeltaUpdate(signal) {
@@ -1232,8 +1306,10 @@ var UmbrellaStore = class {
1232
1306
  this.updateThreadifications(
1233
1307
  result.threads.updated,
1234
1308
  result.inboxNotifications.updated,
1309
+ result.subscriptions.updated,
1235
1310
  result.threads.deleted,
1236
- result.inboxNotifications.deleted
1311
+ result.inboxNotifications.deleted,
1312
+ result.subscriptions.deleted
1237
1313
  );
1238
1314
  }
1239
1315
  async fetchRoomThreadsDeltaUpdate(roomId, signal) {
@@ -1249,8 +1325,10 @@ var UmbrellaStore = class {
1249
1325
  this.updateThreadifications(
1250
1326
  updates.threads.updated,
1251
1327
  updates.inboxNotifications.updated,
1328
+ updates.subscriptions.updated,
1252
1329
  updates.threads.deleted,
1253
- updates.inboxNotifications.deleted
1330
+ updates.inboxNotifications.deleted,
1331
+ updates.subscriptions.deleted
1254
1332
  );
1255
1333
  this.permissionHints.update(updates.permissionHints);
1256
1334
  if (lastRequestedAt < updates.requestedAt) {
@@ -1272,8 +1350,10 @@ var UmbrellaStore = class {
1272
1350
  this.updateThreadifications(
1273
1351
  result.threads.updated,
1274
1352
  result.inboxNotifications.updated,
1353
+ result.subscriptions.updated,
1275
1354
  result.threads.deleted,
1276
- result.inboxNotifications.deleted
1355
+ result.inboxNotifications.deleted,
1356
+ result.subscriptions.deleted
1277
1357
  );
1278
1358
  this.permissionHints.update(result.permissionHints);
1279
1359
  }
@@ -1295,31 +1375,31 @@ var UmbrellaStore = class {
1295
1375
  this.#roomVersionsLastRequestedAtByRoom.set(roomId, updates.requestedAt);
1296
1376
  }
1297
1377
  }
1298
- async refreshRoomNotificationSettings(roomId, signal) {
1378
+ async refreshRoomSubscriptionSettings(roomId, signal) {
1299
1379
  const room = nn(
1300
1380
  this.#client.getRoom(roomId),
1301
1381
  `Room with id ${roomId} is not available on client`
1302
1382
  );
1303
- const result = await room.getNotificationSettings({ signal });
1304
- this.roomNotificationSettings.update(roomId, result);
1383
+ const result = await room.getSubscriptionSettings({ signal });
1384
+ this.roomSubscriptionSettings.update(roomId, result);
1305
1385
  }
1306
1386
  /**
1307
- * Refresh User Notification Settings from poller
1387
+ * Refresh notification settings from poller
1308
1388
  */
1309
- async refreshUserNotificationSettings(signal) {
1389
+ async refreshNotificationSettings(signal) {
1310
1390
  const result = await this.#client.getNotificationSettings({
1311
1391
  signal
1312
1392
  });
1313
- this.userNotificationSettings.update(result);
1393
+ this.notificationSettings.update(result);
1314
1394
  }
1315
1395
  /**
1316
- * Updates user notification settings with a new value, replacing the
1396
+ * Updates notification settings with a new value, replacing the
1317
1397
  * corresponding optimistic update.
1318
1398
  */
1319
- updateUserNotificationSettings_confirmOptimisticUpdate(settings, optimisticUpdateId) {
1399
+ updateNotificationSettings_confirmOptimisticUpdate(settings, optimisticUpdateId) {
1320
1400
  batch2(() => {
1321
1401
  this.optimisticUpdates.remove(optimisticUpdateId);
1322
- this.userNotificationSettings.update(settings);
1402
+ this.notificationSettings.update(settings);
1323
1403
  });
1324
1404
  }
1325
1405
  };
@@ -1478,29 +1558,78 @@ function applyOptimisticUpdates_forThreadifications(baseThreadsDB, notifications
1478
1558
  threadsDB
1479
1559
  };
1480
1560
  }
1481
- function applyOptimisticUpdates_forSettings(settingsLUT, optimisticUpdates) {
1482
- const settingsByRoomId = Object.fromEntries(settingsLUT);
1561
+ function applyOptimisticUpdates_forRoomSubscriptionSettings(settingsLUT, optimisticUpdates) {
1562
+ const roomSubscriptionSettingsByRoomId = Object.fromEntries(settingsLUT);
1483
1563
  for (const optimisticUpdate of optimisticUpdates) {
1484
1564
  switch (optimisticUpdate.type) {
1485
- case "update-notification-settings": {
1486
- const settings = settingsByRoomId[optimisticUpdate.roomId];
1565
+ case "update-room-subscription-settings": {
1566
+ const settings = roomSubscriptionSettingsByRoomId[optimisticUpdate.roomId];
1487
1567
  if (settings === void 0) {
1488
1568
  break;
1489
1569
  }
1490
- settingsByRoomId[optimisticUpdate.roomId] = {
1570
+ roomSubscriptionSettingsByRoomId[optimisticUpdate.roomId] = {
1491
1571
  ...settings,
1492
1572
  ...optimisticUpdate.settings
1493
1573
  };
1494
1574
  }
1495
1575
  }
1496
1576
  }
1497
- return settingsByRoomId;
1577
+ return roomSubscriptionSettingsByRoomId;
1498
1578
  }
1499
- function applyOptimisticUpdates_forUserNotificationSettings(settings, optimisticUpdates) {
1579
+ function applyOptimisticUpdates_forSubscriptions(subscriptionsLUT, threads, optimisticUpdates) {
1580
+ const subscriptions = Object.fromEntries(subscriptionsLUT);
1581
+ for (const update of optimisticUpdates) {
1582
+ switch (update.type) {
1583
+ case "update-room-subscription-settings": {
1584
+ if (!update.settings.threads) {
1585
+ continue;
1586
+ }
1587
+ const roomThreads = threads.findMany(update.roomId, void 0, "desc");
1588
+ for (const thread of roomThreads) {
1589
+ const subscriptionKey = getSubscriptionKey("thread", thread.id);
1590
+ switch (update.settings.threads) {
1591
+ // Create subscriptions for all existing threads in the room
1592
+ case "all": {
1593
+ subscriptions[subscriptionKey] = {
1594
+ kind: "thread",
1595
+ subjectId: thread.id,
1596
+ createdAt: /* @__PURE__ */ new Date()
1597
+ };
1598
+ break;
1599
+ }
1600
+ // Delete subscriptions for all existing threads in the room
1601
+ case "none": {
1602
+ delete subscriptions[subscriptionKey];
1603
+ break;
1604
+ }
1605
+ // Create subscriptions for every threads in the room which the user participates in but doesn't have a subscription for yet
1606
+ case "replies_and_mentions": {
1607
+ if (isThreadParticipant(thread, update.userId) && !subscriptions[subscriptionKey]) {
1608
+ subscriptions[subscriptionKey] = {
1609
+ kind: "thread",
1610
+ subjectId: thread.id,
1611
+ createdAt: /* @__PURE__ */ new Date()
1612
+ };
1613
+ }
1614
+ break;
1615
+ }
1616
+ default:
1617
+ assertNever(
1618
+ update.settings.threads,
1619
+ "Unexpected thread subscription settings."
1620
+ );
1621
+ }
1622
+ }
1623
+ }
1624
+ }
1625
+ }
1626
+ return subscriptions;
1627
+ }
1628
+ function applyOptimisticUpdates_forNotificationSettings(settings, optimisticUpdates) {
1500
1629
  let outcoming = settings;
1501
1630
  for (const update of optimisticUpdates) {
1502
- if (update.type === "update-user-notification-settings") {
1503
- outcoming = patchUserNotificationSettings(outcoming, update.settings);
1631
+ if (update.type === "update-notification-settings") {
1632
+ outcoming = patchNotificationSettings(outcoming, update.settings);
1504
1633
  }
1505
1634
  }
1506
1635
  return outcoming;
@@ -1682,6 +1811,24 @@ function upsertReaction(reactions, reaction) {
1682
1811
  }
1683
1812
  return reactions;
1684
1813
  }
1814
+ function isThreadParticipant(thread, userId) {
1815
+ let isParticipant = false;
1816
+ for (const comment of thread.comments) {
1817
+ if (comment.deletedAt) {
1818
+ continue;
1819
+ }
1820
+ if (comment.userId === userId) {
1821
+ isParticipant = true;
1822
+ break;
1823
+ }
1824
+ const mentionedIds = getMentionedIdsFromCommentBody(comment.body);
1825
+ if (mentionedIds.includes(userId)) {
1826
+ isParticipant = true;
1827
+ break;
1828
+ }
1829
+ }
1830
+ return isParticipant;
1831
+ }
1685
1832
 
1686
1833
  // src/liveblocks.tsx
1687
1834
  import { jsx } from "react/jsx-runtime";
@@ -1798,13 +1945,13 @@ function makeLiveblocksExtrasForClient(client) {
1798
1945
  config.USER_THREADS_POLL_INTERVAL,
1799
1946
  { maxStaleTimeMs: config.USER_THREADS_MAX_STALE_TIME }
1800
1947
  );
1801
- const userNotificationSettingsPoller = makePoller(
1948
+ const notificationSettingsPoller = makePoller(
1802
1949
  async (signal) => {
1803
1950
  try {
1804
- return await store.refreshUserNotificationSettings(signal);
1951
+ return await store.refreshNotificationSettings(signal);
1805
1952
  } catch (err) {
1806
1953
  console.warn(
1807
- `Polling new user notification settings failed: ${String(err)}`
1954
+ `Polling new notification settings failed: ${String(err)}`
1808
1955
  );
1809
1956
  throw err;
1810
1957
  }
@@ -1816,7 +1963,7 @@ function makeLiveblocksExtrasForClient(client) {
1816
1963
  store,
1817
1964
  notificationsPoller,
1818
1965
  userThreadsPoller,
1819
- userNotificationSettingsPoller
1966
+ notificationSettingsPoller
1820
1967
  };
1821
1968
  }
1822
1969
  function makeLiveblocksContextBundle(client) {
@@ -1833,7 +1980,7 @@ function makeLiveblocksContextBundle(client) {
1833
1980
  const shared = createSharedContext(client);
1834
1981
  const bundle = {
1835
1982
  LiveblocksProvider: LiveblocksProvider2,
1836
- useInboxNotifications: () => useInboxNotifications_withClient(client, identity2, shallow4),
1983
+ useInboxNotifications: () => useInboxNotifications_withClient(client, identity2, shallow3),
1837
1984
  useUnreadInboxNotificationsCount: () => useUnreadInboxNotificationsCount_withClient(client),
1838
1985
  useMarkInboxNotificationAsRead: useMarkInboxNotificationAsRead2,
1839
1986
  useMarkAllInboxNotificationsAsRead: useMarkAllInboxNotificationsAsRead2,
@@ -1891,7 +2038,7 @@ function useInboxNotificationsSuspense_withClient(client) {
1891
2038
  ensureNotServerSide();
1892
2039
  const store = getLiveblocksExtrasForClient(client).store;
1893
2040
  use(store.outputs.loadingNotifications.waitUntilLoaded());
1894
- const result = useInboxNotifications_withClient(client, identity2, shallow4);
2041
+ const result = useInboxNotifications_withClient(client, identity2, shallow3);
1895
2042
  assert(!result.error, "Did not expect error");
1896
2043
  assert(!result.isLoading, "Did not expect loading");
1897
2044
  return result;
@@ -1900,7 +2047,7 @@ function useUnreadInboxNotificationsCount_withClient(client) {
1900
2047
  return useInboxNotifications_withClient(
1901
2048
  client,
1902
2049
  selectorFor_useUnreadInboxNotificationsCount,
1903
- shallow4
2050
+ shallow3
1904
2051
  );
1905
2052
  }
1906
2053
  function useUnreadInboxNotificationsCountSuspense_withClient(client) {
@@ -2044,12 +2191,12 @@ function useUpdateNotificationSettings_withClient(client) {
2044
2191
  (settings) => {
2045
2192
  const { store } = getLiveblocksExtrasForClient(client);
2046
2193
  const optimisticUpdateId = store.optimisticUpdates.add({
2047
- type: "update-user-notification-settings",
2194
+ type: "update-notification-settings",
2048
2195
  settings
2049
2196
  });
2050
2197
  client.updateNotificationSettings(settings).then(
2051
2198
  (settings2) => {
2052
- store.updateUserNotificationSettings_confirmOptimisticUpdate(
2199
+ store.updateNotificationSettings_confirmOptimisticUpdate(
2053
2200
  settings2,
2054
2201
  optimisticUpdateId
2055
2202
  );
@@ -2078,9 +2225,9 @@ function useUpdateNotificationSettings_withClient(client) {
2078
2225
  }
2079
2226
  function useNotificationSettings_withClient(client) {
2080
2227
  const updateNotificationSettings = useUpdateNotificationSettings_withClient(client);
2081
- const { store, userNotificationSettingsPoller: poller } = getLiveblocksExtrasForClient(client);
2228
+ const { store, notificationSettingsPoller: poller } = getLiveblocksExtrasForClient(client);
2082
2229
  useEffect3(() => {
2083
- void store.outputs.userNotificationSettings.waitUntilLoaded();
2230
+ void store.outputs.notificationSettings.waitUntilLoaded();
2084
2231
  });
2085
2232
  useEffect3(() => {
2086
2233
  poller.inc();
@@ -2089,7 +2236,7 @@ function useNotificationSettings_withClient(client) {
2089
2236
  poller.dec();
2090
2237
  };
2091
2238
  }, [poller]);
2092
- const result = useSignal(store.outputs.userNotificationSettings.signal);
2239
+ const result = useSignal(store.outputs.notificationSettings.signal);
2093
2240
  return useMemo2(() => {
2094
2241
  return [result, updateNotificationSettings];
2095
2242
  }, [result, updateNotificationSettings]);
@@ -2097,7 +2244,7 @@ function useNotificationSettings_withClient(client) {
2097
2244
  function useNotificationSettingsSuspense_withClient(client) {
2098
2245
  ensureNotServerSide();
2099
2246
  const store = getLiveblocksExtrasForClient(client).store;
2100
- use(store.outputs.userNotificationSettings.waitUntilLoaded());
2247
+ use(store.outputs.notificationSettings.waitUntilLoaded());
2101
2248
  const [result, updateNotificationSettings] = useNotificationSettings_withClient(client);
2102
2249
  assert(!result.error, "Did not expect error");
2103
2250
  assert(!result.isLoading, "Did not expect loading");
@@ -2120,7 +2267,7 @@ function useUser_withClient(client, userId) {
2120
2267
  getUserState,
2121
2268
  getUserState,
2122
2269
  selector,
2123
- shallow4
2270
+ shallow3
2124
2271
  );
2125
2272
  useEffect3(
2126
2273
  () => void usersStore.enqueue(userId)
@@ -2181,7 +2328,7 @@ function useRoomInfo_withClient(client, roomId) {
2181
2328
  getRoomInfoState,
2182
2329
  getRoomInfoState,
2183
2330
  selector,
2184
- shallow4
2331
+ shallow3
2185
2332
  );
2186
2333
  useEffect3(
2187
2334
  () => void roomsInfoStore.enqueue(roomId)
@@ -2341,7 +2488,7 @@ function useUserThreadsSuspense_experimental(options = {}) {
2341
2488
  return result;
2342
2489
  }
2343
2490
  function useInboxNotifications() {
2344
- return useInboxNotifications_withClient(useClient(), identity2, shallow4);
2491
+ return useInboxNotifications_withClient(useClient(), identity2, shallow3);
2345
2492
  }
2346
2493
  function useInboxNotificationsSuspense() {
2347
2494
  return useInboxNotificationsSuspense_withClient(useClient());
@@ -2448,7 +2595,7 @@ function useErrorListener(callback) {
2448
2595
  }
2449
2596
 
2450
2597
  // src/room.tsx
2451
- import { shallow as shallow5 } from "@liveblocks/client";
2598
+ import { shallow as shallow4 } from "@liveblocks/client";
2452
2599
  import {
2453
2600
  assert as assert2,
2454
2601
  console as console3,
@@ -2456,6 +2603,7 @@ import {
2456
2603
  createThreadId,
2457
2604
  DefaultMap as DefaultMap2,
2458
2605
  errorIf,
2606
+ getSubscriptionKey as getSubscriptionKey2,
2459
2607
  HttpError as HttpError2,
2460
2608
  kInternal as kInternal3,
2461
2609
  makePoller as makePoller2,
@@ -2615,29 +2763,36 @@ function makeRoomExtrasForClient(client) {
2615
2763
  { maxStaleTimeMs: config.HISTORY_VERSIONS_MAX_STALE_TIME }
2616
2764
  )
2617
2765
  );
2618
- const roomNotificationSettingsPollersByRoomId = new DefaultMap2(
2766
+ const roomSubscriptionSettingsPollersByRoomId = new DefaultMap2(
2619
2767
  (roomId) => makePoller2(
2620
2768
  async (signal) => {
2621
2769
  try {
2622
- return await store.refreshRoomNotificationSettings(roomId, signal);
2770
+ return await store.refreshRoomSubscriptionSettings(roomId, signal);
2623
2771
  } catch (err) {
2624
- console3.warn(`Polling notification settings for '${roomId}' failed: ${String(err)}`);
2772
+ console3.warn(`Polling subscription settings for '${roomId}' failed: ${String(err)}`);
2625
2773
  throw err;
2626
2774
  }
2627
2775
  },
2628
- config.NOTIFICATION_SETTINGS_POLL_INTERVAL,
2629
- { maxStaleTimeMs: config.NOTIFICATION_SETTINGS_MAX_STALE_TIME }
2776
+ config.ROOM_SUBSCRIPTION_SETTINGS_POLL_INTERVAL,
2777
+ { maxStaleTimeMs: config.ROOM_SUBSCRIPTION_SETTINGS_MAX_STALE_TIME }
2630
2778
  )
2631
2779
  );
2632
2780
  return {
2633
2781
  store,
2634
2782
  onMutationFailure,
2783
+ pollThreadsForRoomId: (roomId) => {
2784
+ const threadsPoller = threadsPollersByRoomId.getOrCreate(roomId);
2785
+ if (threadsPoller) {
2786
+ threadsPoller.markAsStale();
2787
+ threadsPoller.pollNowIfStale();
2788
+ }
2789
+ },
2635
2790
  getOrCreateThreadsPollerForRoomId: threadsPollersByRoomId.getOrCreate.bind(
2636
2791
  threadsPollersByRoomId
2637
2792
  ),
2638
2793
  getOrCreateVersionsPollerForRoomId: versionsPollersByRoomId.getOrCreate.bind(versionsPollersByRoomId),
2639
- getOrCreateNotificationsSettingsPollerForRoomId: roomNotificationSettingsPollersByRoomId.getOrCreate.bind(
2640
- roomNotificationSettingsPollersByRoomId
2794
+ getOrCreateSubscriptionSettingsPollerForRoomId: roomSubscriptionSettingsPollersByRoomId.getOrCreate.bind(
2795
+ roomSubscriptionSettingsPollersByRoomId
2641
2796
  )
2642
2797
  };
2643
2798
  }
@@ -2678,6 +2833,8 @@ function makeRoomContextBundle(client) {
2678
2833
  useEditThreadMetadata,
2679
2834
  useMarkThreadAsResolved,
2680
2835
  useMarkThreadAsUnresolved,
2836
+ useSubscribeToThread,
2837
+ useUnsubscribeFromThread,
2681
2838
  useCreateComment,
2682
2839
  useEditComment,
2683
2840
  useDeleteComment,
@@ -2689,7 +2846,9 @@ function makeRoomContextBundle(client) {
2689
2846
  useHistoryVersions,
2690
2847
  useHistoryVersionData,
2691
2848
  useRoomNotificationSettings,
2849
+ useRoomSubscriptionSettings,
2692
2850
  useUpdateRoomNotificationSettings,
2851
+ useUpdateRoomSubscriptionSettings,
2693
2852
  ...shared.classic,
2694
2853
  suspense: {
2695
2854
  RoomContext,
@@ -2723,6 +2882,8 @@ function makeRoomContextBundle(client) {
2723
2882
  useEditThreadMetadata,
2724
2883
  useMarkThreadAsResolved,
2725
2884
  useMarkThreadAsUnresolved,
2885
+ useSubscribeToThread,
2886
+ useUnsubscribeFromThread,
2726
2887
  useCreateComment,
2727
2888
  useEditComment,
2728
2889
  useDeleteComment,
@@ -2734,7 +2895,9 @@ function makeRoomContextBundle(client) {
2734
2895
  // TODO: useHistoryVersionData: useHistoryVersionDataSuspense,
2735
2896
  useHistoryVersions: useHistoryVersionsSuspense,
2736
2897
  useRoomNotificationSettings: useRoomNotificationSettingsSuspense,
2898
+ useRoomSubscriptionSettings: useRoomSubscriptionSettingsSuspense,
2737
2899
  useUpdateRoomNotificationSettings,
2900
+ useUpdateRoomSubscriptionSettings,
2738
2901
  ...shared.suspense
2739
2902
  }
2740
2903
  };
@@ -2813,7 +2976,11 @@ function RoomProviderInner(props) {
2813
2976
  store.deleteThread(message.threadId, null);
2814
2977
  return;
2815
2978
  }
2816
- const { thread, inboxNotification: maybeNotification } = info;
2979
+ const {
2980
+ thread,
2981
+ inboxNotification: maybeNotification,
2982
+ subscription: maybeSubscription
2983
+ } = info;
2817
2984
  const existingThread = store.outputs.threads.get().getEvenIfDeleted(message.threadId);
2818
2985
  switch (message.type) {
2819
2986
  case ServerMsgCode.COMMENT_EDITED:
@@ -2825,13 +2992,15 @@ function RoomProviderInner(props) {
2825
2992
  if (!existingThread) break;
2826
2993
  store.updateThreadifications(
2827
2994
  [thread],
2828
- maybeNotification ? [maybeNotification] : []
2995
+ maybeNotification ? [maybeNotification] : [],
2996
+ maybeSubscription ? [maybeSubscription] : []
2829
2997
  );
2830
2998
  break;
2831
2999
  case ServerMsgCode.COMMENT_CREATED:
2832
3000
  store.updateThreadifications(
2833
3001
  [thread],
2834
- maybeNotification ? [maybeNotification] : []
3002
+ maybeNotification ? [maybeNotification] : [],
3003
+ maybeSubscription ? [maybeSubscription] : []
2835
3004
  );
2836
3005
  break;
2837
3006
  default:
@@ -3088,7 +3257,7 @@ function useOthersMapped(itemSelector, itemIsEqual) {
3088
3257
  return useOthers(wrappedSelector, wrappedIsEqual);
3089
3258
  }
3090
3259
  function useOthersConnectionIds() {
3091
- return useOthers(selectorFor_useOthersConnectionIds, shallow5);
3260
+ return useOthers(selectorFor_useOthersConnectionIds, shallow4);
3092
3261
  }
3093
3262
  var NOT_FOUND = Symbol();
3094
3263
  function useOther(connectionId, selector, isEqual) {
@@ -3680,36 +3849,114 @@ function useMarkRoomThreadAsUnresolved(roomId) {
3680
3849
  [client, roomId]
3681
3850
  );
3682
3851
  }
3852
+ function useSubscribeToThread() {
3853
+ return useSubscribeToRoomThread(useRoom().id);
3854
+ }
3855
+ function useSubscribeToRoomThread(roomId) {
3856
+ const client = useClient();
3857
+ return useCallback3(
3858
+ (threadId) => {
3859
+ const subscribedAt = /* @__PURE__ */ new Date();
3860
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3861
+ const optimisticId = store.optimisticUpdates.add({
3862
+ type: "subscribe-to-thread",
3863
+ threadId,
3864
+ subscribedAt
3865
+ });
3866
+ client[kInternal3].httpClient.subscribeToThread({ roomId, threadId }).then(
3867
+ (subscription) => {
3868
+ store.createSubscription(subscription, optimisticId);
3869
+ },
3870
+ (err) => onMutationFailure(
3871
+ optimisticId,
3872
+ { type: "SUBSCRIBE_TO_THREAD_ERROR", roomId, threadId },
3873
+ err
3874
+ )
3875
+ );
3876
+ },
3877
+ [client, roomId]
3878
+ );
3879
+ }
3880
+ function useUnsubscribeFromThread() {
3881
+ return useUnsubscribeFromRoomThread(useRoom().id);
3882
+ }
3883
+ function useUnsubscribeFromRoomThread(roomId) {
3884
+ const client = useClient();
3885
+ return useCallback3(
3886
+ (threadId) => {
3887
+ const unsubscribedAt = /* @__PURE__ */ new Date();
3888
+ const { store, onMutationFailure } = getRoomExtrasForClient(client);
3889
+ const optimisticId = store.optimisticUpdates.add({
3890
+ type: "unsubscribe-from-thread",
3891
+ threadId,
3892
+ unsubscribedAt
3893
+ });
3894
+ client[kInternal3].httpClient.unsubscribeFromThread({ roomId, threadId }).then(
3895
+ () => {
3896
+ store.deleteSubscription(
3897
+ getSubscriptionKey2("thread", threadId),
3898
+ optimisticId
3899
+ );
3900
+ },
3901
+ (err) => onMutationFailure(
3902
+ optimisticId,
3903
+ { type: "UNSUBSCRIBE_FROM_THREAD_ERROR", roomId, threadId },
3904
+ err
3905
+ )
3906
+ );
3907
+ },
3908
+ [client, roomId]
3909
+ );
3910
+ }
3683
3911
  function useThreadSubscription(threadId) {
3912
+ return useRoomThreadSubscription(useRoom().id, threadId);
3913
+ }
3914
+ function useRoomThreadSubscription(roomId, threadId) {
3684
3915
  const client = useClient();
3685
3916
  const { store } = getRoomExtrasForClient(client);
3686
- const signal = store.outputs.threadifications;
3917
+ const subscriptionKey = useMemo3(
3918
+ () => getSubscriptionKey2("thread", threadId),
3919
+ [threadId]
3920
+ );
3921
+ const subscribeToThread = useSubscribeToRoomThread(roomId);
3922
+ const unsubscribeFromThread = useUnsubscribeFromRoomThread(roomId);
3923
+ const subscribe = useCallback3(
3924
+ () => subscribeToThread(threadId),
3925
+ [subscribeToThread, threadId]
3926
+ );
3927
+ const unsubscribe = useCallback3(
3928
+ () => unsubscribeFromThread(threadId),
3929
+ [unsubscribeFromThread, threadId]
3930
+ );
3931
+ const signal = store.outputs.threadSubscriptions;
3687
3932
  const selector = useCallback3(
3688
3933
  (state) => {
3689
- const notification = state.sortedNotifications.find(
3934
+ const subscription = state.subscriptions[subscriptionKey];
3935
+ const notification = state.notifications.find(
3690
3936
  (inboxNotification) => inboxNotification.kind === "thread" && inboxNotification.threadId === threadId
3691
3937
  );
3692
- const thread = state.threadsDB.get(threadId);
3693
- if (notification === void 0 || thread === void 0) {
3694
- return { status: "not-subscribed" };
3938
+ if (subscription === void 0) {
3939
+ return { status: "not-subscribed", subscribe, unsubscribe };
3695
3940
  }
3696
3941
  return {
3697
3942
  status: "subscribed",
3698
- unreadSince: notification.readAt
3943
+ unreadSince: notification?.readAt ?? null,
3944
+ subscribe,
3945
+ unsubscribe
3699
3946
  };
3700
3947
  },
3701
- [threadId]
3948
+ [subscriptionKey, threadId, subscribe, unsubscribe]
3702
3949
  );
3703
- return useSignal(signal, selector, shallow5);
3950
+ return useSignal(signal, selector, shallow4);
3704
3951
  }
3705
3952
  function useRoomNotificationSettings() {
3706
3953
  const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
3707
3954
  const client = useClient();
3708
3955
  const room = useRoom();
3709
- const { store, getOrCreateNotificationsSettingsPollerForRoomId } = getRoomExtrasForClient(client);
3710
- const poller = getOrCreateNotificationsSettingsPollerForRoomId(room.id);
3956
+ const { store, getOrCreateSubscriptionSettingsPollerForRoomId } = getRoomExtrasForClient(client);
3957
+ const poller = getOrCreateSubscriptionSettingsPollerForRoomId(room.id);
3711
3958
  useEffect5(
3712
- () => void store.outputs.settingsByRoomId.getOrCreate(room.id).waitUntilLoaded()
3959
+ () => void store.outputs.roomSubscriptionSettingsByRoomId.getOrCreate(room.id).waitUntilLoaded()
3713
3960
  // NOTE: Deliberately *not* using a dependency array here!
3714
3961
  //
3715
3962
  // It is important to call waitUntil on *every* render.
@@ -3727,18 +3974,51 @@ function useRoomNotificationSettings() {
3727
3974
  };
3728
3975
  }, [poller]);
3729
3976
  const settings = useSignal(
3730
- store.outputs.settingsByRoomId.getOrCreate(room.id).signal
3977
+ store.outputs.roomSubscriptionSettingsByRoomId.getOrCreate(room.id).signal
3731
3978
  );
3732
3979
  return useMemo3(() => {
3733
3980
  return [settings, updateRoomNotificationSettings];
3734
3981
  }, [settings, updateRoomNotificationSettings]);
3735
3982
  }
3983
+ function useRoomSubscriptionSettings() {
3984
+ const updateRoomSubscriptionSettings = useUpdateRoomSubscriptionSettings();
3985
+ const client = useClient();
3986
+ const room = useRoom();
3987
+ const { store, getOrCreateSubscriptionSettingsPollerForRoomId } = getRoomExtrasForClient(client);
3988
+ const poller = getOrCreateSubscriptionSettingsPollerForRoomId(room.id);
3989
+ useEffect5(
3990
+ () => void store.outputs.roomSubscriptionSettingsByRoomId.getOrCreate(room.id).waitUntilLoaded()
3991
+ // NOTE: Deliberately *not* using a dependency array here!
3992
+ //
3993
+ // It is important to call waitUntil on *every* render.
3994
+ // This is harmless though, on most renders, except:
3995
+ // 1. The very first render, in which case we'll want to trigger the initial page fetch.
3996
+ // 2. All other subsequent renders now "just" return the same promise (a quick operation).
3997
+ // 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
3998
+ // *next* render after that, a *new* fetch/promise will get created.
3999
+ );
4000
+ useEffect5(() => {
4001
+ poller.inc();
4002
+ poller.pollNowIfStale();
4003
+ return () => {
4004
+ poller.dec();
4005
+ };
4006
+ }, [poller]);
4007
+ const settings = useSignal(
4008
+ store.outputs.roomSubscriptionSettingsByRoomId.getOrCreate(room.id).signal
4009
+ );
4010
+ return useMemo3(() => {
4011
+ return [settings, updateRoomSubscriptionSettings];
4012
+ }, [settings, updateRoomSubscriptionSettings]);
4013
+ }
3736
4014
  function useRoomNotificationSettingsSuspense() {
3737
4015
  ensureNotServerSide();
3738
4016
  const client = useClient();
3739
4017
  const store = getRoomExtrasForClient(client).store;
3740
4018
  const room = useRoom();
3741
- use(store.outputs.settingsByRoomId.getOrCreate(room.id).waitUntilLoaded());
4019
+ use(
4020
+ store.outputs.roomSubscriptionSettingsByRoomId.getOrCreate(room.id).waitUntilLoaded()
4021
+ );
3742
4022
  const [settings, updateRoomNotificationSettings] = useRoomNotificationSettings();
3743
4023
  assert2(!settings.error, "Did not expect error");
3744
4024
  assert2(!settings.isLoading, "Did not expect loading");
@@ -3746,6 +4026,21 @@ function useRoomNotificationSettingsSuspense() {
3746
4026
  return [settings, updateRoomNotificationSettings];
3747
4027
  }, [settings, updateRoomNotificationSettings]);
3748
4028
  }
4029
+ function useRoomSubscriptionSettingsSuspense() {
4030
+ ensureNotServerSide();
4031
+ const client = useClient();
4032
+ const store = getRoomExtrasForClient(client).store;
4033
+ const room = useRoom();
4034
+ use(
4035
+ store.outputs.roomSubscriptionSettingsByRoomId.getOrCreate(room.id).waitUntilLoaded()
4036
+ );
4037
+ const [settings, updateRoomSubscriptionSettings] = useRoomSubscriptionSettings();
4038
+ assert2(!settings.error, "Did not expect error");
4039
+ assert2(!settings.isLoading, "Did not expect loading");
4040
+ return useMemo3(() => {
4041
+ return [settings, updateRoomSubscriptionSettings];
4042
+ }, [settings, updateRoomSubscriptionSettings]);
4043
+ }
3749
4044
  function useHistoryVersionData(versionId) {
3750
4045
  const [state, setState] = useState2({
3751
4046
  isLoading: true
@@ -3814,15 +4109,24 @@ function useUpdateRoomNotificationSettings() {
3814
4109
  const room = useRoom();
3815
4110
  return useCallback3(
3816
4111
  (settings) => {
3817
- const { store, onMutationFailure } = getRoomExtrasForClient(client);
4112
+ const { store, onMutationFailure, pollThreadsForRoomId } = getRoomExtrasForClient(client);
4113
+ const userId = getCurrentUserId(client);
3818
4114
  const optimisticId = store.optimisticUpdates.add({
3819
- type: "update-notification-settings",
4115
+ type: "update-room-subscription-settings",
3820
4116
  roomId: room.id,
4117
+ userId,
3821
4118
  settings
3822
4119
  });
3823
- room.updateNotificationSettings(settings).then(
3824
- (settings2) => {
3825
- store.updateRoomNotificationSettings(room.id, optimisticId, settings2);
4120
+ room.updateSubscriptionSettings(settings).then(
4121
+ (updatedSettings) => {
4122
+ store.updateRoomSubscriptionSettings(
4123
+ room.id,
4124
+ optimisticId,
4125
+ updatedSettings
4126
+ );
4127
+ if (settings.threads) {
4128
+ pollThreadsForRoomId(room.id);
4129
+ }
3826
4130
  },
3827
4131
  (err) => onMutationFailure(
3828
4132
  optimisticId,
@@ -3834,6 +4138,43 @@ function useUpdateRoomNotificationSettings() {
3834
4138
  [client, room]
3835
4139
  );
3836
4140
  }
4141
+ function useUpdateRoomSubscriptionSettings() {
4142
+ const client = useClient();
4143
+ const room = useRoom();
4144
+ return useCallback3(
4145
+ (settings) => {
4146
+ const { store, onMutationFailure, pollThreadsForRoomId } = getRoomExtrasForClient(client);
4147
+ const userId = getCurrentUserId(client);
4148
+ const optimisticId = store.optimisticUpdates.add({
4149
+ type: "update-room-subscription-settings",
4150
+ roomId: room.id,
4151
+ userId,
4152
+ settings
4153
+ });
4154
+ room.updateSubscriptionSettings(settings).then(
4155
+ (udpatedSettings) => {
4156
+ store.updateRoomSubscriptionSettings(
4157
+ room.id,
4158
+ optimisticId,
4159
+ udpatedSettings
4160
+ );
4161
+ if (settings.threads) {
4162
+ pollThreadsForRoomId(room.id);
4163
+ }
4164
+ },
4165
+ (err) => onMutationFailure(
4166
+ optimisticId,
4167
+ {
4168
+ type: "UPDATE_ROOM_SUBSCRIPTION_SETTINGS_ERROR",
4169
+ roomId: room.id
4170
+ },
4171
+ err
4172
+ )
4173
+ );
4174
+ },
4175
+ [client, room]
4176
+ );
4177
+ }
3837
4178
  function useSuspendUntilPresenceReady() {
3838
4179
  ensureNotServerSide();
3839
4180
  const room = useRoom();
@@ -3925,7 +4266,7 @@ function useRoomAttachmentUrl(attachmentId, roomId) {
3925
4266
  getAttachmentUrlState,
3926
4267
  getAttachmentUrlState,
3927
4268
  selectorFor_useAttachmentUrl,
3928
- shallow5
4269
+ shallow4
3929
4270
  );
3930
4271
  }
3931
4272
  function useAttachmentUrlSuspense(attachmentId) {
@@ -3985,7 +4326,9 @@ var _useOthersMappedSuspense = useOthersMappedSuspense;
3985
4326
  var _useThreads = useThreads;
3986
4327
  var _useThreadsSuspense = useThreadsSuspense;
3987
4328
  var _useRoomNotificationSettings = useRoomNotificationSettings;
4329
+ var _useRoomSubscriptionSettings = useRoomSubscriptionSettings;
3988
4330
  var _useRoomNotificationSettingsSuspense = useRoomNotificationSettingsSuspense;
4331
+ var _useRoomSubscriptionSettingsSuspense = useRoomSubscriptionSettingsSuspense;
3989
4332
  var _useHistoryVersions = useHistoryVersions;
3990
4333
  var _useHistoryVersionsSuspense = useHistoryVersionsSuspense;
3991
4334
  var _useOther = useOther;
@@ -4071,9 +4414,13 @@ export {
4071
4414
  useMarkRoomThreadAsResolved,
4072
4415
  useMarkThreadAsUnresolved,
4073
4416
  useMarkRoomThreadAsUnresolved,
4417
+ useSubscribeToThread,
4418
+ useUnsubscribeFromThread,
4074
4419
  useThreadSubscription,
4420
+ useRoomThreadSubscription,
4075
4421
  useHistoryVersionData,
4076
4422
  useUpdateRoomNotificationSettings,
4423
+ useUpdateRoomSubscriptionSettings,
4077
4424
  useOthersConnectionIdsSuspense,
4078
4425
  useStorageStatusSuspense,
4079
4426
  useAttachmentUrl,
@@ -4098,7 +4445,9 @@ export {
4098
4445
  _useThreads,
4099
4446
  _useThreadsSuspense,
4100
4447
  _useRoomNotificationSettings,
4448
+ _useRoomSubscriptionSettings,
4101
4449
  _useRoomNotificationSettingsSuspense,
4450
+ _useRoomSubscriptionSettingsSuspense,
4102
4451
  _useHistoryVersions,
4103
4452
  _useHistoryVersionsSuspense,
4104
4453
  _useOther,
@@ -4112,4 +4461,4 @@ export {
4112
4461
  _useStorageRoot,
4113
4462
  _useUpdateMyPresence
4114
4463
  };
4115
- //# sourceMappingURL=chunk-URVBSXYW.js.map
4464
+ //# sourceMappingURL=chunk-N6OQQVYV.js.map