@liveblocks/react 2.17.0 → 2.18.0-yjsfactory

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.
@@ -98,6 +98,9 @@ function useSignal(signal, selector, isEqual) {
98
98
  }
99
99
 
100
100
  // src/liveblocks.tsx
101
+ import {
102
+ HttpError
103
+ } from "@liveblocks/core";
101
104
  import {
102
105
  assert,
103
106
  createClient,
@@ -130,7 +133,9 @@ var config = {
130
133
  HISTORY_VERSIONS_POLL_INTERVAL: 1 * MINUTES,
131
134
  HISTORY_VERSIONS_MAX_STALE_TIME: 5 * SECONDS,
132
135
  NOTIFICATION_SETTINGS_POLL_INTERVAL: 1 * MINUTES,
133
- NOTIFICATION_SETTINGS_MAX_STALE_TIME: 5 * SECONDS
136
+ NOTIFICATION_SETTINGS_MAX_STALE_TIME: 5 * SECONDS,
137
+ USER_NOTIFICATION_SETTINGS_INTERVAL: 5 * MINUTES,
138
+ USER_NOTIFICATION_SETTINGS_MAX_STALE_TIME: 1 * MINUTES
134
139
  };
135
140
 
136
141
  // src/lib/AsyncResult.ts
@@ -233,6 +238,8 @@ import {
233
238
  console as console2,
234
239
  DefaultMap,
235
240
  DerivedSignal,
241
+ entries,
242
+ keys,
236
243
  kInternal,
237
244
  MutableSignal as MutableSignal2,
238
245
  nanoid,
@@ -723,6 +730,26 @@ function createStore_forPermissionHints() {
723
730
  update
724
731
  };
725
732
  }
733
+ function createStore_forUserNotificationSettings(updates) {
734
+ const signal = new Signal({});
735
+ function update(settings) {
736
+ signal.set((prevSettings) => {
737
+ return {
738
+ ...prevSettings,
739
+ ...settings
740
+ };
741
+ });
742
+ }
743
+ return {
744
+ signal: DerivedSignal.from(
745
+ signal,
746
+ updates,
747
+ (base, updates2) => applyOptimisticUpdates_forUserNotificationSettings(base, updates2)
748
+ ),
749
+ // Mutations
750
+ update
751
+ };
752
+ }
726
753
  function createStore_forOptimistic(client) {
727
754
  const signal = new Signal([]);
728
755
  const syncSource = client[kInternal].createSyncSource();
@@ -756,15 +783,17 @@ var UmbrellaStore = class {
756
783
  //
757
784
  // Mutate inputs... ...observe clean/consistent output!
758
785
  //
759
- // .-> Base ThreadDB ---------+ +----> Clean threads by ID (Part 1)
786
+ // .-> Base ThreadDB ---------+ +----> Clean threads by ID (Part 1)
760
787
  // / | |
761
- // mutate ----> Base Notifications --+ | | +--> Clean notifications (Part 1)
788
+ // mutate ----> Base Notifications --+ | | +--> Clean notifications (Part 1)
762
789
  // \ | | | | & notifications by ID
763
790
  // | \ | | Apply | |
764
- // | `-> OptimisticUpdates --+--+--> Optimistic --+-+--> Notification Settings (Part 2)
765
- // \ | Updates |
766
- // `------- etc etc ---------+ +--> History Versions (Part 3)
767
- // ^
791
+ // | `-> OptimisticUpdates --+--+--> Optimistic --+-+--> Room Notification Settings (Part 2)
792
+ // \ | Updates | |
793
+ // `------- etc etc ---------+ | +--> History Versions (Part 3)
794
+ // ^ |
795
+ // | +-----> User Notification Settings (Part 4)
796
+ // |
768
797
  // |
769
798
  // | ^ ^
770
799
  // Signal | |
@@ -785,6 +814,7 @@ var UmbrellaStore = class {
785
814
  // prettier-ignore
786
815
  historyVersions;
787
816
  permissionHints;
817
+ userNotificationSettings;
788
818
  optimisticUpdates;
789
819
  //
790
820
  // Output signals.
@@ -805,6 +835,8 @@ var UmbrellaStore = class {
805
835
  #userThreadsLastRequestedAt = null;
806
836
  // Room versions
807
837
  #roomVersionsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
838
+ // User Notification Settings
839
+ #userNotificationSettings;
808
840
  constructor(client) {
809
841
  this.#client = client[kInternal].as();
810
842
  this.optimisticUpdates = createStore_forOptimistic(this.#client);
@@ -820,6 +852,16 @@ var UmbrellaStore = class {
820
852
  return nextCursor;
821
853
  }
822
854
  );
855
+ const userNotificationSettingsFetcher = async () => {
856
+ const result = await this.#client.getNotificationSettings();
857
+ this.userNotificationSettings.update(result);
858
+ };
859
+ this.userNotificationSettings = createStore_forUserNotificationSettings(
860
+ this.optimisticUpdates.signal
861
+ );
862
+ this.#userNotificationSettings = new SinglePageResource(
863
+ userNotificationSettingsFetcher
864
+ );
823
865
  this.threads = new ThreadDB();
824
866
  this.notifications = createStore_forNotifications();
825
867
  this.roomNotificationSettings = createStore_forRoomNotificationSettings(
@@ -997,6 +1039,19 @@ var UmbrellaStore = class {
997
1039
  return { signal, waitUntilLoaded: resource.waitUntilLoaded };
998
1040
  }
999
1041
  );
1042
+ const userNotificationSettings = {
1043
+ signal: DerivedSignal.from(() => {
1044
+ const result = this.#userNotificationSettings.get();
1045
+ if (result.isLoading || result.error) {
1046
+ return result;
1047
+ }
1048
+ return ASYNC_OK(
1049
+ "settings",
1050
+ nn(this.userNotificationSettings.signal.get())
1051
+ );
1052
+ }, shallow3),
1053
+ waitUntilLoaded: this.#userNotificationSettings.waitUntilLoaded
1054
+ };
1000
1055
  this.outputs = {
1001
1056
  threadifications,
1002
1057
  threads,
@@ -1005,7 +1060,8 @@ var UmbrellaStore = class {
1005
1060
  notifications,
1006
1061
  loadingNotifications,
1007
1062
  settingsByRoomId,
1008
- versionsByRoomId
1063
+ versionsByRoomId,
1064
+ userNotificationSettings
1009
1065
  };
1010
1066
  autobind(this);
1011
1067
  }
@@ -1250,6 +1306,25 @@ var UmbrellaStore = class {
1250
1306
  const result = await room.getNotificationSettings({ signal });
1251
1307
  this.roomNotificationSettings.update(roomId, result);
1252
1308
  }
1309
+ /**
1310
+ * Refresh User Notification Settings from poller
1311
+ */
1312
+ async refreshUserNotificationSettings(signal) {
1313
+ const result = await this.#client.getNotificationSettings({
1314
+ signal
1315
+ });
1316
+ this.userNotificationSettings.update(result);
1317
+ }
1318
+ /**
1319
+ * Updates user notification settings with a new value, replacing the
1320
+ * corresponding optimistic update.
1321
+ */
1322
+ updateUserNotificationSettings_confirmOptimisticUpdate(settings, optimisticUpdateId) {
1323
+ batch2(() => {
1324
+ this.optimisticUpdates.remove(optimisticUpdateId);
1325
+ this.userNotificationSettings.update(settings);
1326
+ });
1327
+ }
1253
1328
  };
1254
1329
  function applyOptimisticUpdates_forThreadifications(baseThreadsDB, notificationsLUT, optimisticUpdates) {
1255
1330
  const threadsDB = baseThreadsDB.clone();
@@ -1424,6 +1499,33 @@ function applyOptimisticUpdates_forSettings(settingsLUT, optimisticUpdates) {
1424
1499
  }
1425
1500
  return settingsByRoomId;
1426
1501
  }
1502
+ function applyOptimisticUpdates_forUserNotificationSettings(baseSettings, optimisticUpdates) {
1503
+ const outcomingSettings = { ...baseSettings };
1504
+ for (const optimisticUpdate of optimisticUpdates) {
1505
+ switch (optimisticUpdate.type) {
1506
+ case "update-user-notification-settings": {
1507
+ const incomingSettings = optimisticUpdate.settings;
1508
+ for (const channelKey of keys(incomingSettings)) {
1509
+ const key = channelKey;
1510
+ const channelUpdates = incomingSettings[key];
1511
+ if (channelUpdates) {
1512
+ const realChannelUpdates = Object.fromEntries(
1513
+ entries(channelUpdates).filter(
1514
+ ([_, value]) => value !== void 0
1515
+ )
1516
+ );
1517
+ outcomingSettings[key] = {
1518
+ ...outcomingSettings[key],
1519
+ ...realChannelUpdates
1520
+ };
1521
+ }
1522
+ }
1523
+ break;
1524
+ }
1525
+ }
1526
+ }
1527
+ return outcomingSettings;
1528
+ }
1427
1529
  function compareInboxNotifications(inboxNotificationA, inboxNotificationB) {
1428
1530
  if (inboxNotificationA.notifiedAt > inboxNotificationB.notifiedAt) {
1429
1531
  return 1;
@@ -1717,10 +1819,25 @@ function makeLiveblocksExtrasForClient(client) {
1717
1819
  config.USER_THREADS_POLL_INTERVAL,
1718
1820
  { maxStaleTimeMs: config.USER_THREADS_MAX_STALE_TIME }
1719
1821
  );
1822
+ const userNotificationSettingsPoller = makePoller(
1823
+ async (signal) => {
1824
+ try {
1825
+ return await store.refreshUserNotificationSettings(signal);
1826
+ } catch (err) {
1827
+ console.warn(
1828
+ `Polling new user notification settings failed: ${String(err)}`
1829
+ );
1830
+ throw err;
1831
+ }
1832
+ },
1833
+ config.USER_NOTIFICATION_SETTINGS_INTERVAL,
1834
+ { maxStaleTimeMs: config.USER_NOTIFICATION_SETTINGS_MAX_STALE_TIME }
1835
+ );
1720
1836
  return {
1721
1837
  store,
1722
1838
  notificationsPoller,
1723
- userThreadsPoller
1839
+ userThreadsPoller,
1840
+ userNotificationSettingsPoller
1724
1841
  };
1725
1842
  }
1726
1843
  function makeLiveblocksContextBundle(client) {
@@ -1729,6 +1846,7 @@ function makeLiveblocksContextBundle(client) {
1729
1846
  const useMarkAllInboxNotificationsAsRead2 = () => useMarkAllInboxNotificationsAsRead_withClient(client);
1730
1847
  const useDeleteInboxNotification2 = () => useDeleteInboxNotification_withClient(client);
1731
1848
  const useDeleteAllInboxNotifications2 = () => useDeleteAllInboxNotifications_withClient(client);
1849
+ const useUpdateNotificationSettings2 = () => useUpdateNotificationSettings_withClient(client);
1732
1850
  function LiveblocksProvider2(props) {
1733
1851
  useEnsureNoLiveblocksProvider();
1734
1852
  return /* @__PURE__ */ jsx(ClientContext.Provider, { value: client, children: props.children });
@@ -1742,6 +1860,8 @@ function makeLiveblocksContextBundle(client) {
1742
1860
  useMarkAllInboxNotificationsAsRead: useMarkAllInboxNotificationsAsRead2,
1743
1861
  useDeleteInboxNotification: useDeleteInboxNotification2,
1744
1862
  useDeleteAllInboxNotifications: useDeleteAllInboxNotifications2,
1863
+ useNotificationSettings: () => useNotificationSettings_withClient(client),
1864
+ useUpdateNotificationSettings: useUpdateNotificationSettings2,
1745
1865
  useInboxNotificationThread: useInboxNotificationThread2,
1746
1866
  useUserThreads_experimental,
1747
1867
  ...shared.classic,
@@ -1754,6 +1874,8 @@ function makeLiveblocksContextBundle(client) {
1754
1874
  useDeleteInboxNotification: useDeleteInboxNotification2,
1755
1875
  useDeleteAllInboxNotifications: useDeleteAllInboxNotifications2,
1756
1876
  useInboxNotificationThread: useInboxNotificationThread2,
1877
+ useNotificationSettings: () => useNotificationSettingsSuspense_withClient(client),
1878
+ useUpdateNotificationSettings: useUpdateNotificationSettings2,
1757
1879
  useUserThreads_experimental: useUserThreadsSuspense_experimental,
1758
1880
  ...shared.suspense
1759
1881
  }
@@ -1938,6 +2060,72 @@ function useInboxNotificationThread_withClient(client, inboxNotificationId) {
1938
2060
  )
1939
2061
  );
1940
2062
  }
2063
+ function useUpdateNotificationSettings_withClient(client) {
2064
+ return useCallback2(
2065
+ (settings) => {
2066
+ const { store } = getLiveblocksExtrasForClient(client);
2067
+ const optimisticUpdateId = store.optimisticUpdates.add({
2068
+ type: "update-user-notification-settings",
2069
+ settings
2070
+ });
2071
+ client.updateNotificationSettings(settings).then(
2072
+ (settings2) => {
2073
+ store.updateUserNotificationSettings_confirmOptimisticUpdate(
2074
+ settings2,
2075
+ optimisticUpdateId
2076
+ );
2077
+ },
2078
+ (err) => {
2079
+ store.optimisticUpdates.remove(optimisticUpdateId);
2080
+ if (err instanceof HttpError) {
2081
+ if (err.status === 422) {
2082
+ const msg = [err.details?.error, err.details?.reason].filter(Boolean).join("\n");
2083
+ console.error(msg);
2084
+ }
2085
+ client[kInternal2].emitError(
2086
+ {
2087
+ type: "UPDATE_USER_NOTIFICATION_SETTINGS_ERROR"
2088
+ },
2089
+ err
2090
+ );
2091
+ } else {
2092
+ throw err;
2093
+ }
2094
+ }
2095
+ );
2096
+ },
2097
+ [client]
2098
+ );
2099
+ }
2100
+ function useNotificationSettings_withClient(client) {
2101
+ const updateNotificationSettings = useUpdateNotificationSettings_withClient(client);
2102
+ const { store, userNotificationSettingsPoller: poller } = getLiveblocksExtrasForClient(client);
2103
+ useEffect3(() => {
2104
+ void store.outputs.userNotificationSettings.waitUntilLoaded();
2105
+ });
2106
+ useEffect3(() => {
2107
+ poller.inc();
2108
+ poller.pollNowIfStale();
2109
+ return () => {
2110
+ poller.dec();
2111
+ };
2112
+ }, [poller]);
2113
+ const result = useSignal(store.outputs.userNotificationSettings.signal);
2114
+ return useMemo2(() => {
2115
+ return [result, updateNotificationSettings];
2116
+ }, [result, updateNotificationSettings]);
2117
+ }
2118
+ function useNotificationSettingsSuspense_withClient(client) {
2119
+ ensureNotServerSide();
2120
+ const store = getLiveblocksExtrasForClient(client).store;
2121
+ use(store.outputs.userNotificationSettings.waitUntilLoaded());
2122
+ const [result, updateNotificationSettings] = useNotificationSettings_withClient(client);
2123
+ assert(!result.error, "Did not expect error");
2124
+ assert(!result.isLoading, "Did not expect loading");
2125
+ return useMemo2(() => {
2126
+ return [result, updateNotificationSettings];
2127
+ }, [result, updateNotificationSettings]);
2128
+ }
1941
2129
  function useUser_withClient(client, userId) {
1942
2130
  const usersStore = client[kInternal2].usersStore;
1943
2131
  const getUserState = useCallback2(
@@ -2203,6 +2391,15 @@ function useUnreadInboxNotificationsCount() {
2203
2391
  function useUnreadInboxNotificationsCountSuspense() {
2204
2392
  return useUnreadInboxNotificationsCountSuspense_withClient(useClient());
2205
2393
  }
2394
+ function useNotificationSettings() {
2395
+ return useNotificationSettings_withClient(useClient());
2396
+ }
2397
+ function useNotificationSettingsSuspense() {
2398
+ return useNotificationSettingsSuspense_withClient(useClient());
2399
+ }
2400
+ function useUpdateNotificationSettings() {
2401
+ return useUpdateNotificationSettings_withClient(useClient());
2402
+ }
2206
2403
  function useUser(userId) {
2207
2404
  const client = useClient();
2208
2405
  return useUser_withClient(client, userId);
@@ -2280,7 +2477,7 @@ import {
2280
2477
  createThreadId,
2281
2478
  DefaultMap as DefaultMap2,
2282
2479
  errorIf,
2283
- HttpError,
2480
+ HttpError as HttpError2,
2284
2481
  kInternal as kInternal3,
2285
2482
  makePoller as makePoller2,
2286
2483
  ServerMsgCode
@@ -2397,7 +2594,7 @@ function makeRoomExtrasForClient(client) {
2397
2594
  const store = getUmbrellaStoreForClient(client);
2398
2595
  function onMutationFailure(optimisticId, context, innerError) {
2399
2596
  store.optimisticUpdates.remove(optimisticId);
2400
- if (innerError instanceof HttpError) {
2597
+ if (innerError instanceof HttpError2) {
2401
2598
  if (innerError.status === 403) {
2402
2599
  const detailedMessage = [
2403
2600
  innerError.message,
@@ -3850,6 +4047,9 @@ export {
3850
4047
  useDeleteInboxNotification,
3851
4048
  useUnreadInboxNotificationsCount,
3852
4049
  useUnreadInboxNotificationsCountSuspense,
4050
+ useNotificationSettings,
4051
+ useNotificationSettingsSuspense,
4052
+ useUpdateNotificationSettings,
3853
4053
  useRoomInfo,
3854
4054
  useRoomInfoSuspense,
3855
4055
  _useInboxNotificationThread,
@@ -3934,4 +4134,4 @@ export {
3934
4134
  _useStorageRoot,
3935
4135
  _useUpdateMyPresence
3936
4136
  };
3937
- //# sourceMappingURL=chunk-4KNGHD4I.mjs.map
4137
+ //# sourceMappingURL=chunk-OSTPNTQF.mjs.map