@liveblocks/react 2.7.0 → 2.7.1
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.
- package/dist/{chunk-KNPU4P3Y.js → chunk-TNEGW2UU.js} +486 -356
- package/dist/chunk-TNEGW2UU.js.map +1 -0
- package/dist/{chunk-OKR7ROQ5.mjs → chunk-XK5NTOJJ.mjs} +540 -410
- package/dist/chunk-XK5NTOJJ.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{suspense-pL0llH_6.d.mts → suspense-ZevLSpFZ.d.mts} +63 -23
- package/dist/{suspense-pL0llH_6.d.ts → suspense-ZevLSpFZ.d.ts} +63 -23
- package/dist/suspense.d.mts +1 -1
- package/dist/suspense.d.ts +1 -1
- package/dist/suspense.js +3 -3
- package/dist/suspense.mjs +1 -1
- package/package.json +6 -4
- package/dist/chunk-KNPU4P3Y.js.map +0 -1
- package/dist/chunk-OKR7ROQ5.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/version.ts","../src/ClientSideSuspense.tsx","../src/contexts.ts","../src/liveblocks.tsx","../src/lib/compare.ts","../src/lib/guards.ts","../src/lib/querying.ts","../src/lib/retry-error.ts","../src/lib/shallow2.ts","../src/lib/use-initial.ts","../src/lib/use-latest.ts","../src/lib/use-polyfill.ts","../src/umbrella-store.ts","../src/types/errors.ts","../src/room.tsx","../src/use-scroll-to-comment-on-load-effect.ts"],"names":["React","shallow","createContext","useCallback","useContext","useEffect","isPlainObject","console","existingComment","existingReaction","subscribers","useInboxNotificationThread","useMarkInboxNotificationAsRead","useMarkAllInboxNotificationsAsRead","useDeleteInboxNotification","useDeleteAllInboxNotifications","LiveblocksProvider","useClient","kInternal","makePoller","stringify","useSyncExternalStoreWithSelector","comment","noop","useSyncExternalStore","POLLING_INTERVAL","_extras","_bundles","getExtrasForClient","makeExtrasForClient","version","room","other","rootOrNull","state","err","metadata","inboxNotification","settings"],"mappings":"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","sourcesContent":["declare const __VERSION__: string;\ndeclare const TSUP_FORMAT: string;\n\nexport const PKG_NAME = \"@liveblocks/react\";\nexport const PKG_VERSION = typeof __VERSION__ === \"string\" && __VERSION__;\nexport const PKG_FORMAT = typeof TSUP_FORMAT === \"string\" && TSUP_FORMAT;\n","import type { ReactNode } from \"react\";\nimport * as React from \"react\";\n\ntype Props = {\n fallback: ReactNode;\n children: (() => ReactNode | undefined) | ReactNode | undefined;\n};\n\n/**\n * Almost like a normal <Suspense> component, except that for server-side\n * renders, the fallback will be used.\n *\n * The child props will have to be provided in a function, i.e. change:\n *\n * <Suspense fallback={<Loading />}>\n * <MyRealComponent a={1} />\n * </Suspense>\n *\n * To:\n *\n * <ClientSideSuspense fallback={<Loading />}>\n * <MyRealComponent a={1} />\n * </ClientSideSuspense>\n *\n */\nexport function ClientSideSuspense(props: Props) {\n const [mounted, setMounted] = React.useState(false);\n\n React.useEffect(() => {\n // Effects are never executed on the server side. The point of this is to\n // delay the flipping of this boolean until after hydration has happened.\n setMounted(true);\n }, []);\n\n return (\n <React.Suspense fallback={props.fallback}>\n {mounted\n ? typeof props.children === \"function\"\n ? props.children()\n : props.children\n : props.fallback}\n </React.Suspense>\n );\n}\n","import type {\n BaseMetadata,\n BaseUserMeta,\n Json,\n JsonObject,\n LsonObject,\n Room,\n} from \"@liveblocks/client\";\nimport type { OpaqueRoom } from \"@liveblocks/core\";\nimport * as React from \"react\";\n\n/**\n * Raw access to the React context where the RoomProvider stores the current\n * room. Exposed for advanced use cases only.\n *\n * @private This is a private/advanced API. Do not rely on it.\n */\nexport const RoomContext = React.createContext<OpaqueRoom | null>(null);\n\n/** @internal */\nexport function useRoomOrNull<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n>(): Room<P, S, U, E, M> | null {\n return React.useContext(RoomContext) as Room<P, S, U, E, M> | null;\n}\n\n/**\n * Returns whether the hook is called within a RoomProvider context.\n *\n * @example\n * const isInsideRoom = useIsInsideRoom();\n */\nexport function useIsInsideRoom(): boolean {\n const room = useRoomOrNull();\n return room !== null;\n}\n","import type {\n BaseMetadata,\n BaseUserMeta,\n Client,\n ClientOptions,\n ThreadData,\n} from \"@liveblocks/client\";\nimport type {\n AsyncResult,\n BaseRoomInfo,\n DM,\n DU,\n OpaqueClient,\n} from \"@liveblocks/core\";\nimport {\n assert,\n createClient,\n kInternal,\n makePoller,\n memoizeOnSuccess,\n raise,\n shallow,\n stringify,\n} from \"@liveblocks/core\";\nimport type { PropsWithChildren } from \"react\";\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n} from \"react\";\nimport { useSyncExternalStore } from \"use-sync-external-store/shim/index.js\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector.js\";\n\nimport { useIsInsideRoom } from \"./contexts\";\nimport { byFirstCreated, byMostRecentlyUpdated } from \"./lib/compare\";\nimport { makeThreadsFilter } from \"./lib/querying\";\nimport { autoRetry, retryError } from \"./lib/retry-error\";\nimport { shallow2 } from \"./lib/shallow2\";\nimport { useInitial, useInitialUnlessFunction } from \"./lib/use-initial\";\nimport { use } from \"./lib/use-polyfill\";\nimport type {\n InboxNotificationsState,\n LiveblocksContextBundle,\n RoomInfoAsyncResult,\n RoomInfoAsyncSuccess,\n SharedContextBundle,\n ThreadsQuery,\n ThreadsState,\n ThreadsStateSuccess,\n UnreadInboxNotificationsCountState,\n UserAsyncResult,\n UserAsyncSuccess,\n UseUserThreadsOptions,\n} from \"./types\";\nimport type { UmbrellaStoreState } from \"./umbrella-store\";\nimport { UmbrellaStore } from \"./umbrella-store\";\n\n// NOTE: These helper types are only temporarily needed while we're refactoring things\n// NOTE: The reason we cannot inline them into the selectors is that the react-hooks/exchaustive-deps lint rule will think\ntype GetInboxNotificationsType<M extends BaseMetadata = BaseMetadata> =\n ReturnType<UmbrellaStore<M>[\"getInboxNotifications\"]>;\nexport type GetThreadsType<M extends BaseMetadata = BaseMetadata> = ReturnType<\n UmbrellaStore<M>[\"getThreads\"]\n>;\nexport type GetNotificationSettingsType = ReturnType<\n UmbrellaStore<BaseMetadata>[\"getNotificationSettings\"]\n>;\n\n/**\n * Raw access to the React context where the LiveblocksProvider stores the\n * current client. Exposed for advanced use cases only.\n *\n * @private This is a private/advanced API. Do not rely on it.\n */\nexport const ClientContext = createContext<OpaqueClient | null>(null);\n\nfunction missingUserError(userId: string) {\n return new Error(`resolveUsers didn't return anything for user '${userId}'`);\n}\n\nfunction missingRoomInfoError(roomId: string) {\n return new Error(\n `resolveRoomsInfo didn't return anything for room '${roomId}'`\n );\n}\n\nconst _umbrellaStores = new WeakMap<\n OpaqueClient,\n UmbrellaStore<BaseMetadata>\n>();\nconst _extras = new WeakMap<\n OpaqueClient,\n ReturnType<typeof makeExtrasForClient>\n>();\nconst _bundles = new WeakMap<\n OpaqueClient,\n LiveblocksContextBundle<BaseUserMeta, BaseMetadata>\n>();\n\nexport const POLLING_INTERVAL = 60 * 1000; // 1 minute\nexport const INBOX_NOTIFICATIONS_QUERY = \"INBOX_NOTIFICATIONS\";\nexport const USER_THREADS_QUERY = \"USER_THREADS\";\n\nfunction selectorFor_useInboxNotifications(\n state: ReturnType<UmbrellaStore<BaseMetadata>[\"getInboxNotifications\"]>\n): InboxNotificationsState {\n // TODO Can we make this a static property, rather than a static key in a dynamic map?\n const query = state.queries[INBOX_NOTIFICATIONS_QUERY];\n\n if (query === undefined || query.isLoading) {\n return {\n isLoading: true,\n };\n }\n\n if (query.error !== undefined) {\n return {\n error: query.error,\n isLoading: false,\n };\n }\n\n return {\n inboxNotifications: state.inboxNotifications,\n isLoading: false,\n };\n}\n\nfunction selectUnreadInboxNotificationsCount(\n state: ReturnType<UmbrellaStore<BaseMetadata>[\"getInboxNotifications\"]>\n) {\n let count = 0;\n\n for (const notification of state.inboxNotifications) {\n if (\n notification.readAt === null ||\n notification.readAt < notification.notifiedAt\n ) {\n count++;\n }\n }\n\n return count;\n}\n\nfunction selectorFor_useUnreadInboxNotificationsCount(\n state: ReturnType<UmbrellaStore<BaseMetadata>[\"getInboxNotifications\"]>\n): UnreadInboxNotificationsCountState {\n const query = state.queries[INBOX_NOTIFICATIONS_QUERY];\n\n if (query === undefined || query.isLoading) {\n return {\n isLoading: true,\n };\n }\n\n if (query.error !== undefined) {\n return {\n error: query.error,\n isLoading: false,\n };\n }\n\n return {\n isLoading: false,\n count: selectUnreadInboxNotificationsCount(state),\n };\n}\n\nfunction selectorFor_useUser<U extends BaseUserMeta>(\n state: AsyncResult<U[\"info\"] | undefined> | undefined,\n userId: string\n): UserAsyncResult<U[\"info\"]> {\n if (state === undefined || state?.isLoading) {\n return state ?? { isLoading: true };\n }\n\n if (state.error) {\n return state;\n }\n\n // If this is a \"success\" state, but there still is no data, then it means\n // the \"resolving of this user\" returned undefined. In that case, still treat\n // this as an error state.\n if (!state.data) {\n return {\n isLoading: false,\n error: missingUserError(userId),\n };\n }\n\n return {\n isLoading: false,\n user: state.data,\n };\n}\n\nfunction selectorFor_useRoomInfo(\n state: AsyncResult<BaseRoomInfo | undefined> | undefined,\n roomId: string\n): RoomInfoAsyncResult {\n if (state === undefined || state?.isLoading) {\n return state ?? { isLoading: true };\n }\n\n if (state.error) {\n return state;\n }\n\n // If this is a \"success\" state, but there still is no data, then it means\n // the \"resolving of this user\" returned undefined. In that case, still treat\n // this as an error state.\n if (!state.data) {\n return {\n isLoading: false,\n error: missingRoomInfoError(roomId),\n };\n }\n\n return {\n isLoading: false,\n info: state.data,\n };\n}\n\n/**\n * @private Do not rely on this internal API.\n */\n// TODO This helper should ideally not have to be exposed at the package level!\n// TODO It's currently used by react-lexical though.\nexport function selectThreads<M extends BaseMetadata>(\n state: UmbrellaStoreState<M>,\n options: {\n roomId: string | null;\n query?: ThreadsQuery<M>;\n orderBy:\n | \"age\" // = default\n | \"last-update\";\n }\n): ThreadData<M>[] {\n let threads = state.threads;\n\n if (options.roomId !== null) {\n threads = threads.filter((thread) => thread.roomId === options.roomId);\n }\n\n // Third filter pass: select only threads matching query filter\n const query = options.query;\n if (query) {\n threads = threads.filter(makeThreadsFilter<M>(query));\n }\n\n // Sort threads by creation date (oldest first)\n return threads.sort(\n options.orderBy === \"last-update\" ? byMostRecentlyUpdated : byFirstCreated\n );\n}\n\nfunction getOrCreateContextBundle<\n U extends BaseUserMeta,\n M extends BaseMetadata,\n>(client: OpaqueClient): LiveblocksContextBundle<U, M> {\n let bundle = _bundles.get(client);\n if (!bundle) {\n bundle = makeLiveblocksContextBundle(client);\n _bundles.set(client, bundle);\n }\n return bundle as LiveblocksContextBundle<U, M>;\n}\n\n/**\n * Gets or creates a unique Umbrella store for each unique client instance.\n *\n * @private\n */\nexport function getUmbrellaStoreForClient<M extends BaseMetadata>(\n client: OpaqueClient\n): UmbrellaStore<M> {\n let store = _umbrellaStores.get(client);\n if (!store) {\n store = new UmbrellaStore();\n _umbrellaStores.set(client, store);\n }\n return store as unknown as UmbrellaStore<M>;\n}\n\n// TODO: Likely a better / more clear name for this helper will arise. I'll\n// rename this later. All of these are implementation details to support inbox\n// notifications on a per-client basis.\n/** @internal Only exported for unit tests. */\nexport function getExtrasForClient<M extends BaseMetadata>(\n client: OpaqueClient\n) {\n let extras = _extras.get(client);\n if (!extras) {\n extras = makeExtrasForClient(client);\n _extras.set(client, extras);\n }\n\n return extras as unknown as Omit<typeof extras, \"store\"> & {\n store: UmbrellaStore<M>;\n };\n}\n\nfunction makeExtrasForClient<M extends BaseMetadata>(client: OpaqueClient) {\n const store = getUmbrellaStoreForClient(client);\n // TODO ^ Bind to M type param here\n\n let lastRequestedAt: Date | undefined;\n\n /**\n * Performs one network fetch, and updates the store and last requested at\n * date if successful. If unsuccessful, will throw.\n */\n async function fetchInboxNotifications() {\n // If inbox notifications have not been fetched yet, we get all of them\n // Else, we fetch only what changed since the last request\n if (lastRequestedAt === undefined) {\n const result = await client.getInboxNotifications();\n\n store.updateThreadsAndNotifications(\n result.threads,\n result.inboxNotifications,\n [],\n [],\n INBOX_NOTIFICATIONS_QUERY\n );\n\n lastRequestedAt = result.requestedAt;\n } else {\n const result = await client.getInboxNotificationsSince({\n since: lastRequestedAt,\n });\n\n store.updateThreadsAndNotifications(\n result.threads.updated,\n result.inboxNotifications.updated,\n result.threads.deleted,\n result.inboxNotifications.deleted,\n INBOX_NOTIFICATIONS_QUERY\n );\n\n if (lastRequestedAt < result.requestedAt) {\n lastRequestedAt = result.requestedAt;\n }\n }\n }\n\n let pollerSubscribers = 0;\n const poller = makePoller(async () => {\n try {\n await waitUntilInboxNotificationsLoaded();\n await fetchInboxNotifications();\n } catch (err) {\n // When polling, we don't want to throw errors, ever\n console.warn(`Polling new inbox notifications failed: ${String(err)}`);\n }\n });\n\n /**\n * Will trigger an initial fetch of inbox notifications if this hasn't\n * already happened. Will resolve once there is initial data. Will retry\n * a few times automatically in case fetching fails, with incremental backoff\n * delays. Will throw eventually only if all retries fail.\n */\n const waitUntilInboxNotificationsLoaded = memoizeOnSuccess(async () => {\n store.setQueryLoading(INBOX_NOTIFICATIONS_QUERY);\n\n try {\n await autoRetry(\n () => fetchInboxNotifications(),\n 5,\n [5000, 5000, 10000, 15000]\n );\n } catch (err) {\n // Store the error in the cache as a side-effect, for non-Suspense\n store.setQueryError(INBOX_NOTIFICATIONS_QUERY, err as Error);\n\n // Rethrow it for Suspense, where this promise must fail\n throw err;\n }\n });\n\n /**\n * Triggers an initial fetch of inbox notifications if this hasn't\n * already happened.\n */\n function loadInboxNotifications(): void {\n void waitUntilInboxNotificationsLoaded().catch(() => {\n // Deliberately catch and ignore any errors here\n });\n }\n\n /**\n * Enables polling for inbox notifications when the component mounts. Stops\n * polling on unmount.\n *\n * Safe to be called multiple times from different components. The first\n * component to mount starts the polling. The last component to unmount stops\n * the polling.\n */\n function useEnableInboxNotificationsPolling() {\n useEffect(() => {\n // Increment\n pollerSubscribers++;\n poller.start(POLLING_INTERVAL);\n\n return () => {\n // Decrement\n if (pollerSubscribers <= 0) {\n console.warn(\n `Internal unexpected behavior. Cannot decrease subscriber count for query \"${INBOX_NOTIFICATIONS_QUERY}\"`\n );\n return;\n }\n\n pollerSubscribers--;\n if (pollerSubscribers <= 0) {\n poller.stop();\n }\n };\n }, []);\n }\n\n const userThreadsPoller = makePoller(refreshUserThreads);\n\n let isFetchingUserThreadsUpdates = false;\n\n async function refreshUserThreads() {\n const since = userThreadslastRequestedAt;\n\n if (since === undefined || isFetchingUserThreadsUpdates) {\n return;\n }\n try {\n isFetchingUserThreadsUpdates = true;\n const updates = await client[kInternal].getThreadsSince({\n since,\n });\n isFetchingUserThreadsUpdates = false;\n store.updateThreadsAndNotifications(\n updates.threads.updated,\n [],\n updates.threads.deleted,\n [],\n USER_THREADS_QUERY\n );\n\n userThreadslastRequestedAt = updates.requestedAt;\n } catch (err) {\n isFetchingUserThreadsUpdates = false;\n return;\n }\n }\n\n const userThreadsSubscribersByQuery = new Map<string, number>();\n const userThreadsRequestsByQuery = new Map<string, Promise<unknown>>();\n\n function incrementUserThreadsQuerySubscribers(queryKey: string) {\n const subscribers = userThreadsSubscribersByQuery.get(queryKey) ?? 0;\n userThreadsSubscribersByQuery.set(queryKey, subscribers + 1);\n\n userThreadsPoller.start(POLLING_INTERVAL);\n\n // Decrement in the unsub function\n return () => {\n const subscribers = userThreadsSubscribersByQuery.get(queryKey);\n\n if (subscribers === undefined || subscribers <= 0) {\n console.warn(\n `Internal unexpected behavior. Cannot decrease subscriber count for query \"${queryKey}\"`\n );\n return;\n }\n\n userThreadsSubscribersByQuery.set(queryKey, subscribers - 1);\n\n let totalSubscribers = 0;\n for (const subscribers of userThreadsSubscribersByQuery.values()) {\n totalSubscribers += subscribers;\n }\n\n if (totalSubscribers <= 0) {\n userThreadsPoller.stop();\n }\n };\n }\n\n let userThreadslastRequestedAt: Date | undefined;\n\n async function getUserThreads(\n queryKey: string,\n options: UseUserThreadsOptions<M>,\n { retryCount }: { retryCount: number } = { retryCount: 0 }\n ) {\n const existingRequest = userThreadsRequestsByQuery.get(queryKey);\n\n // If a request was already made for the query, we do not make another request and return the existing promise of the request\n if (existingRequest !== undefined) return existingRequest;\n\n const request = client[kInternal].getThreads(options);\n\n // Store the promise of the request for the query so that we do not make another request for the same query\n userThreadsRequestsByQuery.set(queryKey, request);\n\n store.setQueryLoading(queryKey);\n\n try {\n const result = await request;\n\n store.updateThreadsAndNotifications(\n result.threads,\n result.inboxNotifications,\n [],\n [],\n queryKey\n );\n\n /**\n * We set the `userThreadslastRequestedAt` value to the timestamp returned by the current request if:\n * 1. The `userThreadslastRequestedAt` value has not been set\n * OR\n * 2. The `userThreadslastRequestedAt` value is older than the timestamp returned by the current request\n */\n if (\n userThreadslastRequestedAt === undefined ||\n userThreadslastRequestedAt < result.requestedAt\n ) {\n userThreadslastRequestedAt = result.requestedAt;\n }\n\n userThreadsPoller.start(POLLING_INTERVAL);\n } catch (err) {\n userThreadsRequestsByQuery.delete(queryKey);\n\n // Retry the action using the exponential backoff algorithm\n retryError(() => {\n void getUserThreads(queryKey, options, {\n retryCount: retryCount + 1,\n });\n }, retryCount);\n\n // Set the query state to the error state\n store.setQueryError(queryKey, err as Error);\n }\n\n return;\n }\n\n return {\n store,\n useEnableInboxNotificationsPolling,\n waitUntilInboxNotificationsLoaded,\n loadInboxNotifications,\n incrementUserThreadsQuerySubscribers,\n getUserThreads,\n };\n}\n\nfunction makeLiveblocksContextBundle<\n U extends BaseUserMeta,\n M extends BaseMetadata,\n>(client: Client<U>): LiveblocksContextBundle<U, M> {\n // Bind all hooks to the current client instance\n const useInboxNotificationThread = (inboxNotificationId: string) =>\n useInboxNotificationThread_withClient<M>(client, inboxNotificationId);\n\n const useMarkInboxNotificationAsRead = () =>\n useMarkInboxNotificationAsRead_withClient(client);\n\n const useMarkAllInboxNotificationsAsRead = () =>\n useMarkAllInboxNotificationsAsRead_withClient(client);\n\n const useDeleteInboxNotification = () =>\n useDeleteInboxNotification_withClient(client);\n\n const useDeleteAllInboxNotifications = () =>\n useDeleteAllInboxNotifications_withClient(client);\n\n // NOTE: This version of the LiveblocksProvider does _not_ take any props.\n // This is because we already have a client bound to it.\n function LiveblocksProvider(props: PropsWithChildren) {\n useEnsureNoLiveblocksProvider();\n return (\n <ClientContext.Provider value={client}>\n {props.children}\n </ClientContext.Provider>\n );\n }\n\n const shared = createSharedContext<U>(client);\n\n const bundle: LiveblocksContextBundle<U, M> = {\n LiveblocksProvider,\n\n useInboxNotifications: () => useInboxNotifications_withClient(client),\n useUnreadInboxNotificationsCount: () =>\n useUnreadInboxNotificationsCount_withClient(client),\n\n useMarkInboxNotificationAsRead,\n useMarkAllInboxNotificationsAsRead,\n\n useDeleteInboxNotification,\n useDeleteAllInboxNotifications,\n\n useInboxNotificationThread,\n useUserThreads_experimental,\n\n ...shared.classic,\n\n suspense: {\n LiveblocksProvider,\n\n useInboxNotifications: () =>\n useInboxNotificationsSuspense_withClient(client),\n useUnreadInboxNotificationsCount: () =>\n useUnreadInboxNotificationsCountSuspense_withClient(client),\n\n useMarkInboxNotificationAsRead,\n useMarkAllInboxNotificationsAsRead,\n\n useDeleteInboxNotification,\n useDeleteAllInboxNotifications,\n\n useInboxNotificationThread,\n\n useUserThreads_experimental: useUserThreadsSuspense_experimental,\n\n ...shared.suspense,\n },\n };\n return bundle;\n}\n\nfunction useInboxNotifications_withClient(client: OpaqueClient) {\n const { loadInboxNotifications, store, useEnableInboxNotificationsPolling } =\n getExtrasForClient(client);\n\n // Trigger initial loading of inbox notifications if it hasn't started\n // already, but don't await its promise.\n useEffect(() => {\n loadInboxNotifications();\n }, [loadInboxNotifications]);\n\n useEnableInboxNotificationsPolling();\n return useSyncExternalStoreWithSelector(\n store.subscribeInboxNotifications,\n store.getInboxNotifications,\n store.getInboxNotifications,\n selectorFor_useInboxNotifications,\n shallow\n );\n}\n\nfunction useInboxNotificationsSuspense_withClient(client: OpaqueClient) {\n const { waitUntilInboxNotificationsLoaded } = getExtrasForClient(client);\n\n // Suspend until there are at least some inbox notifications\n use(waitUntilInboxNotificationsLoaded());\n\n // We're in a Suspense world here, and as such, the useInboxNotifications()\n // hook is expected to only return success results when we're here.\n const result = useInboxNotifications_withClient(client);\n assert(!result.error, \"Did not expect error\");\n assert(!result.isLoading, \"Did not expect loading\");\n return result;\n}\n\nfunction useUnreadInboxNotificationsCount_withClient(client: OpaqueClient) {\n const { store, loadInboxNotifications, useEnableInboxNotificationsPolling } =\n getExtrasForClient(client);\n\n // Trigger initial loading of inbox notifications if it hasn't started\n // already, but don't await its promise.\n useEffect(() => {\n loadInboxNotifications();\n }, [loadInboxNotifications]);\n\n useEnableInboxNotificationsPolling();\n return useSyncExternalStoreWithSelector(\n store.subscribeInboxNotifications,\n store.getInboxNotifications,\n store.getInboxNotifications,\n selectorFor_useUnreadInboxNotificationsCount,\n shallow\n );\n}\n\nfunction useUnreadInboxNotificationsCountSuspense_withClient(\n client: OpaqueClient\n) {\n const { waitUntilInboxNotificationsLoaded } = getExtrasForClient(client);\n\n // Suspend until there are at least some inbox notifications\n use(waitUntilInboxNotificationsLoaded());\n\n const result = useUnreadInboxNotificationsCount_withClient(client);\n assert(!result.isLoading, \"Did not expect loading\");\n assert(!result.error, \"Did not expect error\");\n return result;\n}\n\nfunction useMarkInboxNotificationAsRead_withClient(client: OpaqueClient) {\n return useCallback(\n (inboxNotificationId: string) => {\n const { store } = getExtrasForClient(client);\n\n const readAt = new Date();\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"mark-inbox-notification-as-read\",\n inboxNotificationId,\n readAt,\n });\n\n client.markInboxNotificationAsRead(inboxNotificationId).then(\n () => {\n // Replace the optimistic update by the real thing\n store.updateInboxNotification(\n inboxNotificationId,\n optimisticUpdateId,\n (inboxNotification) => ({ ...inboxNotification, readAt })\n );\n },\n () => {\n // TODO: Broadcast errors to client\n store.removeOptimisticUpdate(optimisticUpdateId);\n }\n );\n },\n [client]\n );\n}\n\nfunction useMarkAllInboxNotificationsAsRead_withClient(client: OpaqueClient) {\n return useCallback(() => {\n const { store } = getExtrasForClient(client);\n const readAt = new Date();\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"mark-all-inbox-notifications-as-read\",\n readAt,\n });\n\n client.markAllInboxNotificationsAsRead().then(\n () => {\n // Replace the optimistic update by the real thing\n store.updateAllInboxNotifications(\n optimisticUpdateId,\n (inboxNotification) => ({ ...inboxNotification, readAt })\n );\n },\n () => {\n // TODO: Broadcast errors to client\n store.removeOptimisticUpdate(optimisticUpdateId);\n }\n );\n }, [client]);\n}\n\nfunction useDeleteInboxNotification_withClient(client: OpaqueClient) {\n return useCallback(\n (inboxNotificationId: string) => {\n const { store } = getExtrasForClient(client);\n\n const deletedAt = new Date();\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"delete-inbox-notification\",\n inboxNotificationId,\n deletedAt,\n });\n\n client.deleteInboxNotification(inboxNotificationId).then(\n () => {\n // Replace the optimistic update by the real thing\n store.deleteInboxNotification(\n inboxNotificationId,\n optimisticUpdateId\n );\n },\n () => {\n // TODO: Broadcast errors to client\n store.removeOptimisticUpdate(optimisticUpdateId);\n }\n );\n },\n [client]\n );\n}\n\nfunction useDeleteAllInboxNotifications_withClient(client: OpaqueClient) {\n return useCallback(() => {\n const { store } = getExtrasForClient(client);\n const deletedAt = new Date();\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"delete-all-inbox-notifications\",\n deletedAt,\n });\n\n client.deleteAllInboxNotifications().then(\n () => {\n // Replace the optimistic update by the real thing\n store.deleteAllInboxNotifications(optimisticUpdateId);\n },\n () => {\n // TODO: Broadcast errors to client\n store.removeOptimisticUpdate(optimisticUpdateId);\n }\n );\n }, [client]);\n}\n\nfunction useInboxNotificationThread_withClient<M extends BaseMetadata>(\n client: OpaqueClient,\n inboxNotificationId: string\n): ThreadData<M> {\n const { store } = getExtrasForClient<M>(client);\n\n const selector = useCallback(\n (state: GetInboxNotificationsType<M>) => {\n const inboxNotification =\n state.inboxNotificationsById[inboxNotificationId] ??\n raise(`Inbox notification with ID \"${inboxNotificationId}\" not found`);\n\n if (inboxNotification.kind !== \"thread\") {\n raise(\n `Inbox notification with ID \"${inboxNotificationId}\" is not of kind \"thread\"`\n );\n }\n\n const thread =\n state.threadsById[inboxNotification.threadId] ??\n raise(\n `Thread with ID \"${inboxNotification.threadId}\" not found, this inbox notification might not be of kind \"thread\"`\n );\n\n return thread;\n },\n [inboxNotificationId]\n );\n\n return useSyncExternalStoreWithSelector(\n store.subscribeInboxNotifications,\n store.getInboxNotifications,\n store.getInboxNotifications,\n selector\n );\n}\n\nfunction useUser_withClient<U extends BaseUserMeta>(\n client: Client<U>,\n userId: string\n): UserAsyncResult<U[\"info\"]> {\n const usersStore = client[kInternal].usersStore;\n\n const getUserState = useCallback(\n () => usersStore.getState(userId),\n [usersStore, userId]\n );\n\n useEffect(() => {\n // NOTE: .get() will trigger any actual fetches, whereas .getState() will not\n void usersStore.get(userId);\n }, [usersStore, userId]);\n\n const selector = useCallback(\n (state: ReturnType<typeof getUserState>) =>\n selectorFor_useUser(state, userId),\n [userId]\n );\n\n return useSyncExternalStoreWithSelector(\n usersStore.subscribe,\n getUserState,\n getUserState,\n selector,\n shallow\n );\n}\n\nfunction useUserSuspense_withClient<U extends BaseUserMeta>(\n client: Client<U>,\n userId: string\n) {\n const usersStore = client[kInternal].usersStore;\n\n const getUserState = useCallback(\n () => usersStore.getState(userId),\n [usersStore, userId]\n );\n const userState = getUserState();\n\n if (!userState || userState.isLoading) {\n throw usersStore.get(userId);\n }\n\n if (userState.error) {\n throw userState.error;\n }\n\n // Throw an error if `undefined` was returned by `resolveUsers` for this user ID\n if (!userState.data) {\n throw missingUserError(userId);\n }\n\n const state = useSyncExternalStore(\n usersStore.subscribe,\n getUserState,\n getUserState\n );\n assert(state !== undefined, \"Unexpected missing state\");\n assert(!state.isLoading, \"Unexpected loading state\");\n assert(!state.error, \"Unexpected error state\");\n return {\n isLoading: false,\n user: state.data,\n error: undefined,\n } as const;\n}\n\nfunction useRoomInfo_withClient(\n client: OpaqueClient,\n roomId: string\n): RoomInfoAsyncResult {\n const roomsInfoStore = client[kInternal].roomsInfoStore;\n\n const getRoomInfoState = useCallback(\n () => roomsInfoStore.getState(roomId),\n [roomsInfoStore, roomId]\n );\n\n const selector = useCallback(\n (state: ReturnType<typeof getRoomInfoState>) =>\n selectorFor_useRoomInfo(state, roomId),\n [roomId]\n );\n\n useEffect(() => {\n void roomsInfoStore.get(roomId);\n }, [roomsInfoStore, roomId]);\n\n return useSyncExternalStoreWithSelector(\n roomsInfoStore.subscribe,\n getRoomInfoState,\n getRoomInfoState,\n selector,\n shallow\n );\n}\n\nfunction useRoomInfoSuspense_withClient(client: OpaqueClient, roomId: string) {\n const roomsInfoStore = client[kInternal].roomsInfoStore;\n\n const getRoomInfoState = useCallback(\n () => roomsInfoStore.getState(roomId),\n [roomsInfoStore, roomId]\n );\n const roomInfoState = getRoomInfoState();\n\n if (!roomInfoState || roomInfoState.isLoading) {\n throw roomsInfoStore.get(roomId);\n }\n\n if (roomInfoState.error) {\n throw roomInfoState.error;\n }\n\n // Throw an error if `undefined` was returned by `resolveRoomsInfo` for this room ID\n if (!roomInfoState.data) {\n throw missingRoomInfoError(roomId);\n }\n\n const state = useSyncExternalStore(\n roomsInfoStore.subscribe,\n getRoomInfoState,\n getRoomInfoState\n );\n assert(state !== undefined, \"Unexpected missing state\");\n assert(!state.isLoading, \"Unexpected loading state\");\n assert(!state.error, \"Unexpected error state\");\n assert(state.data !== undefined, \"Unexpected missing room info data\");\n return {\n isLoading: false,\n info: state.data,\n error: undefined,\n } as const;\n}\n\n/** @internal */\nexport function createSharedContext<U extends BaseUserMeta>(\n client: Client<U>\n): SharedContextBundle<U> {\n const useClient = () => client;\n return {\n classic: {\n useClient,\n useUser: (userId: string) => useUser_withClient(client, userId),\n useRoomInfo: (roomId: string) => useRoomInfo_withClient(client, roomId),\n useIsInsideRoom,\n },\n suspense: {\n useClient,\n useUser: (userId: string) => useUserSuspense_withClient(client, userId),\n useRoomInfo: (roomId: string) =>\n useRoomInfoSuspense_withClient(client, roomId),\n useIsInsideRoom,\n },\n };\n}\n\n/**\n * @private This is an internal API.\n */\nfunction useEnsureNoLiveblocksProvider(options?: { allowNesting?: boolean }) {\n const existing = useClientOrNull();\n if (!options?.allowNesting && existing !== null) {\n throw new Error(\n \"You cannot nest multiple LiveblocksProvider instances in the same React tree.\"\n );\n }\n}\n\n/**\n * @private This is an internal API.\n */\nexport function useClientOrNull<U extends BaseUserMeta>() {\n return useContext(ClientContext) as Client<U> | null;\n}\n\n/**\n * Obtains a reference to the current Liveblocks client.\n */\nexport function useClient<U extends BaseUserMeta>() {\n return (\n useClientOrNull<U>() ??\n raise(\"LiveblocksProvider is missing from the React tree.\")\n );\n}\n\n/**\n * @private This is a private API.\n */\nexport function LiveblocksProviderWithClient(\n props: PropsWithChildren<{\n client: OpaqueClient;\n\n // Private flag, used only to skip the nesting check if this is\n // a LiveblocksProvider created implicitly by a factory-bound RoomProvider.\n allowNesting?: boolean;\n }>\n) {\n useEnsureNoLiveblocksProvider(props);\n return (\n <ClientContext.Provider value={props.client}>\n {props.children}\n </ClientContext.Provider>\n );\n}\n\n/**\n * Sets up a client for connecting to Liveblocks, and is the recommended way to do\n * this for React apps. You must define either `authEndpoint` or `publicApiKey`.\n * Resolver functions should be placed inside here, and a number of other options\n * are available, which correspond with those passed to `createClient`.\n * Unlike `RoomProvider`, `LiveblocksProvider` doesn’t call Liveblocks servers when mounted,\n * and it should be placed higher in your app’s component tree.\n */\nexport function LiveblocksProvider<U extends BaseUserMeta = DU>(\n props: PropsWithChildren<ClientOptions<U>>\n) {\n const { children, ...o } = props;\n\n // It's important that the static options remain stable, otherwise we'd be\n // creating new client instances on every render.\n const options = {\n publicApiKey: useInitial(o.publicApiKey),\n throttle: useInitial(o.throttle),\n lostConnectionTimeout: useInitial(o.lostConnectionTimeout),\n backgroundKeepAliveTimeout: useInitial(o.backgroundKeepAliveTimeout),\n polyfills: useInitial(o.polyfills),\n unstable_fallbackToHTTP: useInitial(o.unstable_fallbackToHTTP),\n unstable_streamData: useInitial(o.unstable_streamData),\n\n authEndpoint: useInitialUnlessFunction(o.authEndpoint),\n resolveMentionSuggestions: useInitialUnlessFunction(\n o.resolveMentionSuggestions\n ),\n resolveUsers: useInitialUnlessFunction(o.resolveUsers),\n resolveRoomsInfo: useInitialUnlessFunction(o.resolveRoomsInfo),\n\n baseUrl: useInitial(\n // @ts-expect-error - Hidden config options\n o.baseUrl as string | undefined\n ),\n enableDebugLogging: useInitial(\n // @ts-expect-error - Hidden config options\n o.enableDebugLogging as boolean | undefined\n ),\n } as ClientOptions<U>;\n\n // NOTE: Deliberately not passing any deps here, because we'll _never_ want\n // to recreate a client instance after the first render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const client = useMemo(() => createClient<U>(options), []);\n return (\n <LiveblocksProviderWithClient client={client}>\n {children}\n </LiveblocksProviderWithClient>\n );\n}\n\n/**\n * Creates a LiveblocksProvider and a set of typed hooks. Note that any\n * LiveblocksProvider created in this way takes no props, because it uses\n * settings from the given client instead.\n */\nexport function createLiveblocksContext<\n U extends BaseUserMeta = DU,\n M extends BaseMetadata = DM,\n>(client: OpaqueClient): LiveblocksContextBundle<U, M> {\n return getOrCreateContextBundle<U, M>(client);\n}\n\n/**\n * @experimental\n *\n * This hook is experimental and could be removed or changed at any time!\n * Do not use unless explicitly recommended by the Liveblocks team.\n *\n * WARNING:\n * Please note that this hook currently returns all threads by most recently\n * updated threads first. This is inconsistent with the default sort order of\n * the useThreads() hook, which returns them in chronological order (by\n * creation date). In the final version, we will make these hooks behave\n * consistently, so expect that in the final version, you'll have to explicitly\n * specify the sort order to be by most recently updated first somehow.\n * The final API for that is still TBD.\n *\n */\nfunction useUserThreads_experimental<M extends BaseMetadata>(\n options: UseUserThreadsOptions<M> = {\n query: {\n metadata: {},\n },\n }\n): ThreadsState<M> {\n const queryKey = React.useMemo(\n () => makeUserThreadsQueryKey(options.query),\n [options]\n );\n\n const client = useClient<M>();\n\n const { store, incrementUserThreadsQuerySubscribers, getUserThreads } =\n getExtrasForClient<M>(client);\n\n useEffect(() => {\n void getUserThreads(queryKey, options);\n return incrementUserThreadsQuerySubscribers(queryKey);\n }, [queryKey, incrementUserThreadsQuerySubscribers, getUserThreads, options]);\n\n const selector = useCallback(\n (state: GetThreadsType<M>): ThreadsState<M> => {\n const query = state.queries[queryKey];\n\n if (query === undefined || query.isLoading) {\n return {\n isLoading: true,\n };\n }\n\n if (query.error !== undefined) {\n return {\n threads: [],\n error: query.error,\n isLoading: false,\n };\n }\n\n return {\n threads: selectThreads(state, {\n roomId: null, // Do _not_ filter by roomId\n query: options.query,\n orderBy: \"last-update\",\n }),\n isLoading: false,\n };\n },\n [queryKey, options]\n );\n\n return useSyncExternalStoreWithSelector(\n store.subscribeThreads,\n store.getThreads,\n store.getThreads,\n selector,\n shallow2 // NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!\n );\n}\n\n/**\n * @experimental\n *\n * This hook is experimental and could be removed or changed at any time!\n * Do not use unless explicitly recommended by the Liveblocks team.\n *\n * WARNING:\n * Please note that this hook currently returns all threads by most recently\n * updated threads first. This is inconsistent with the default sort order of\n * the useThreads() hook, which returns them in chronological order (by\n * creation date). In the final version, we will make these hooks behave\n * consistently, so expect that in the final version, you'll have to explicitly\n * specify the sort order to be by most recently updated first somehow.\n * The final API for that is still TBD.\n */\nfunction useUserThreadsSuspense_experimental<M extends BaseMetadata>(\n options: UseUserThreadsOptions<M> = {\n query: {\n metadata: {},\n },\n }\n): ThreadsStateSuccess<M> {\n const queryKey = React.useMemo(\n () => makeUserThreadsQueryKey(options.query),\n [options]\n );\n\n const client = useClient<M>();\n\n const { store, getUserThreads } = getExtrasForClient<M>(client);\n\n React.useEffect(() => {\n const { incrementUserThreadsQuerySubscribers } = getExtrasForClient(client);\n return incrementUserThreadsQuerySubscribers(queryKey);\n }, [client, queryKey]);\n\n const query = store.getThreads().queries[queryKey];\n\n if (query === undefined || query.isLoading) {\n throw getUserThreads(queryKey, options);\n }\n\n if (query.error) {\n throw query.error;\n }\n\n const selector = useCallback(\n (state: GetThreadsType<M>): ThreadsStateSuccess<M> => {\n return {\n threads: selectThreads(state, {\n roomId: null, // Do _not_ filter by roomId\n query: options.query,\n orderBy: \"last-update\",\n }),\n isLoading: false,\n };\n },\n [options]\n );\n\n return useSyncExternalStoreWithSelector(\n store.subscribeThreads,\n store.getThreads,\n store.getThreads,\n selector,\n shallow2 // NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!\n );\n}\n\n/**\n * Returns the inbox notifications for the current user.\n *\n * @example\n * const { inboxNotifications, error, isLoading } = useInboxNotifications();\n */\nfunction useInboxNotifications() {\n return useInboxNotifications_withClient(useClient());\n}\n\n/**\n * Returns the inbox notifications for the current user.\n *\n * @example\n * const { inboxNotifications } = useInboxNotifications();\n */\nfunction useInboxNotificationsSuspense() {\n return useInboxNotificationsSuspense_withClient(useClient());\n}\n\nfunction useInboxNotificationThread<M extends BaseMetadata>(\n inboxNotificationId: string\n) {\n return useInboxNotificationThread_withClient<M>(\n useClient(),\n inboxNotificationId\n );\n}\n\n/**\n * Returns a function that marks all of the current user's inbox notifications as read.\n *\n * @example\n * const markAllInboxNotificationsAsRead = useMarkAllInboxNotificationsAsRead();\n * markAllInboxNotificationsAsRead();\n */\nfunction useMarkAllInboxNotificationsAsRead() {\n return useMarkAllInboxNotificationsAsRead_withClient(useClient());\n}\n\n/**\n * Returns a function that marks an inbox notification as read for the current user.\n *\n * @example\n * const markInboxNotificationAsRead = useMarkInboxNotificationAsRead();\n * markInboxNotificationAsRead(\"in_xxx\");\n */\nfunction useMarkInboxNotificationAsRead() {\n return useMarkInboxNotificationAsRead_withClient(useClient());\n}\n\n/**\n * Returns a function that deletes all of the current user's inbox notifications.\n *\n * @example\n * const deleteAllInboxNotifications = useDeleteAllInboxNotifications();\n * deleteAllInboxNotifications();\n */\nfunction useDeleteAllInboxNotifications() {\n return useDeleteAllInboxNotifications_withClient(useClient());\n}\n\n/**\n * Returns a function that deletes an inbox notification for the current user.\n *\n * @example\n * const deleteInboxNotification = useDeleteInboxNotification();\n * deleteInboxNotification(\"in_xxx\");\n */\nfunction useDeleteInboxNotification() {\n return useDeleteInboxNotification_withClient(useClient());\n}\n\n/**\n * Returns the number of unread inbox notifications for the current user.\n *\n * @example\n * const { count, error, isLoading } = useUnreadInboxNotificationsCount();\n */\nfunction useUnreadInboxNotificationsCount() {\n return useUnreadInboxNotificationsCount_withClient(useClient());\n}\n\n/**\n * Returns the number of unread inbox notifications for the current user.\n *\n * @example\n * const { count } = useUnreadInboxNotificationsCount();\n */\nfunction useUnreadInboxNotificationsCountSuspense() {\n return useUnreadInboxNotificationsCountSuspense_withClient(useClient());\n}\n\nfunction useUser<U extends BaseUserMeta>(userId: string) {\n const client = useClient<U>();\n return useUser_withClient(client, userId);\n}\n\nfunction useUserSuspense<U extends BaseUserMeta>(\n userId: string\n): UserAsyncSuccess<U[\"info\"]> {\n const client = useClient<U>();\n return useUserSuspense_withClient(client, userId);\n}\n\n/**\n * Returns room info from a given room ID.\n *\n * @example\n * const { info, error, isLoading } = useRoomInfo(\"room-id\");\n */\nfunction useRoomInfo(roomId: string): RoomInfoAsyncResult {\n return useRoomInfo_withClient(useClient(), roomId);\n}\n\n/**\n * Returns room info from a given room ID.\n *\n * @example\n * const { info } = useRoomInfo(\"room-id\");\n */\nfunction useRoomInfoSuspense(roomId: string): RoomInfoAsyncSuccess {\n return useRoomInfoSuspense_withClient(useClient(), roomId);\n}\n\ntype TypedBundle = LiveblocksContextBundle<DU, DM>;\n\n/**\n * Returns the thread associated with a `\"thread\"` inbox notification.\n *\n * It can **only** be called with IDs of `\"thread\"` inbox notifications,\n * so we recommend only using it when customizing the rendering or in other\n * situations where you can guarantee the kind of the notification.\n *\n * When `useInboxNotifications` returns `\"thread\"` inbox notifications,\n * it also receives the associated threads and caches them behind the scenes.\n * When you call `useInboxNotificationThread`, it simply returns the cached thread\n * for the inbox notification ID you passed to it, without any fetching or waterfalls.\n *\n * @example\n * const thread = useInboxNotificationThread(\"in_xxx\");\n */\nconst _useInboxNotificationThread: TypedBundle[\"useInboxNotificationThread\"] =\n useInboxNotificationThread;\n\n/**\n * Returns user info from a given user ID.\n *\n * @example\n * const { user, error, isLoading } = useUser(\"user-id\");\n */\nconst _useUser: TypedBundle[\"useUser\"] = useUser;\n\n/**\n * Returns user info from a given user ID.\n *\n * @example\n * const { user } = useUser(\"user-id\");\n */\nconst _useUserSuspense: TypedBundle[\"suspense\"][\"useUser\"] = useUserSuspense;\n\n/**\n * @experimental\n *\n * This hook is experimental and could be removed or changed at any time!\n * Do not use unless explicitly recommended by the Liveblocks team.\n *\n * WARNING:\n * Please note that this hook currently returns all threads by most recently\n * updated threads first. This is inconsistent with the default sort order of\n * the useThreads() hook, which returns them in chronological order (by\n * creation date). In the final version, we will make these hooks behave\n * consistently, so expect that in the final version, you'll have to explicitly\n * specify the sort order to be by most recently updated first somehow.\n * The final API for that is still TBD.\n */\nconst _useUserThreads_experimental: TypedBundle[\"useUserThreads_experimental\"] =\n useUserThreads_experimental;\n\n/**\n * @experimental\n *\n * This hook is experimental and could be removed or changed at any time!\n * Do not use unless explicitly recommended by the Liveblocks team.\n *\n * WARNING:\n * Please note that this hook currently returns all threads by most recently\n * updated threads first. This is inconsistent with the default sort order of\n * the useThreads() hook, which returns them in chronological order (by\n * creation date). In the final version, we will make these hooks behave\n * consistently, so expect that in the final version, you'll have to explicitly\n * specify the sort order to be by most recently updated first somehow.\n * The final API for that is still TBD.\n */\nconst _useUserThreadsSuspense_experimental: TypedBundle[\"suspense\"][\"useUserThreads_experimental\"] =\n useUserThreadsSuspense_experimental;\n\n// eslint-disable-next-line simple-import-sort/exports\nexport {\n _useInboxNotificationThread as useInboxNotificationThread,\n _useUser as useUser,\n _useUserSuspense as useUserSuspense,\n useInboxNotifications,\n useInboxNotificationsSuspense,\n useMarkAllInboxNotificationsAsRead,\n useMarkInboxNotificationAsRead,\n useDeleteAllInboxNotifications,\n useDeleteInboxNotification,\n useRoomInfo,\n useRoomInfoSuspense,\n useUnreadInboxNotificationsCount,\n useUnreadInboxNotificationsCountSuspense,\n _useUserThreads_experimental as useUserThreads_experimental,\n _useUserThreadsSuspense_experimental as useUserThreadsSuspense_experimental,\n};\n\nconst makeUserThreadsQueryKey = (options: UseUserThreadsOptions<DM>[\"query\"]) =>\n `${USER_THREADS_QUERY}:${stringify(options)}`;\n","/**\n * Comparison function to be used in .sort() which will sort threads from\n * oldest to newest, based on their creation dates.\n * Orders by \"createdAt ASC\".\n */\nexport function byFirstCreated(\n a: { createdAt: Date },\n b: { createdAt: Date }\n): number {\n return a.createdAt.getTime() - b.createdAt.getTime();\n}\n\n/**\n * Defines if a thread is newer (i.e. created more recently).\n * Doesn't factor in when the thread was last updated.\n */\nexport function isNewer(\n a: { createdAt: Date },\n b: { createdAt: Date }\n): boolean {\n return byFirstCreated(a, b) > 0;\n}\n\n/**\n * Defines if a thread is more recently updated. Doesn't factor in the original\n * creation date for these threads.\n */\nexport function isMoreRecentlyUpdated(\n a: { createdAt: Date; updatedAt?: Date },\n b: { createdAt: Date; updatedAt?: Date }\n): boolean {\n return byMostRecentlyUpdated(a, b) < 0;\n}\n\n/**\n * Comparison function to be used in .sort() which will sort threads from\n * newest to oldest, based on their last-updated dates.\n * Orders by \"updatedAt DESC\".\n *\n * IMPORTANT!\n * This is *NOT* simply the inverse of compareThreads!\n */\nexport function byMostRecentlyUpdated(\n a: { createdAt: Date; updatedAt?: Date },\n b: { createdAt: Date; updatedAt?: Date }\n): number {\n return (\n (b.updatedAt ?? b.createdAt).getTime() -\n (a.updatedAt ?? a.createdAt).getTime()\n );\n}\n","import { isPlainObject } from \"@liveblocks/core\";\n\n/**\n * Check if value is of shape { startsWith: string }\n */\nexport function isStartsWith(blob: unknown): blob is { startsWith: string } {\n return isPlainObject(blob) && isString(blob.startsWith);\n}\n\nexport function isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n","import type { BaseMetadata, ThreadData } from \"@liveblocks/client\";\n\nimport type { ThreadsQuery } from \"../types\";\nimport { isStartsWith, isString } from \"./guards\";\n\n/**\n * Creates a predicate function that will filter all ThreadData instances that\n * match the given query.\n */\nexport function makeThreadsFilter<M extends BaseMetadata>(\n query: ThreadsQuery<M>\n): (thread: ThreadData<M>) => boolean {\n return (thread: ThreadData<M>) =>\n matchesQuery(thread, query) && matchesMetadata(thread, query);\n}\n\nfunction matchesQuery(\n thread: ThreadData<BaseMetadata>,\n q: ThreadsQuery<BaseMetadata>\n) {\n // Boolean logic: query.resolved? => q.resolved === t.resolved\n return q.resolved === undefined || thread.resolved === q.resolved;\n}\n\nfunction matchesMetadata(\n thread: ThreadData<BaseMetadata>,\n q: ThreadsQuery<BaseMetadata>\n) {\n // Boolean logic: query.metadata? => all metadata matches\n const metadata = thread.metadata;\n return (\n q.metadata === undefined ||\n Object.entries(q.metadata).every(\n ([key, op]) =>\n // Boolean logic: op? => value matches the operator\n op === undefined || matchesOperator(metadata[key], op)\n )\n );\n}\n\nfunction matchesOperator(\n value: BaseMetadata[string],\n op: BaseMetadata[string] | { startsWith: string }\n) {\n if (isStartsWith(op)) {\n return isString(value) && value.startsWith(op.startsWith);\n } else {\n return value === op;\n }\n}\n","import { wait } from \"@liveblocks/core\";\n\nconst MAX_ERROR_RETRY_COUNT = 5;\n\nconst ERROR_RETRY_INTERVAL = 5000; // 5 seconds\n\n/**\n * Retries an action using the exponential backoff algorithm\n * @param action The action to retry\n * @param retryCount The number of times the action has been retried\n */\nexport function retryError(action: () => void, retryCount: number) {\n if (retryCount >= MAX_ERROR_RETRY_COUNT) return;\n\n const timeout = Math.pow(2, retryCount) * ERROR_RETRY_INTERVAL;\n\n setTimeout(() => {\n void action();\n }, timeout);\n}\n\n/**\n * Wraps a promise factory. Will create promises until one succeeds. If\n * a promise rejects, it will retry calling the factory for at most `maxTries`\n * times. Between each attempt, it will inject a a backoff delay (in millis)\n * from the given array. If the array contains fewer items then `maxTries`,\n * then the last backoff number will be used indefinitely.\n *\n * If the last attempt is rejected too, the returned promise will fail too.\n *\n * @param promiseFn The promise factory to execute\n * @param maxTries The number of total tries (must be >=1)\n * @param backoff An array of timings to inject between each promise attempt\n */\nexport async function autoRetry<T>(\n promiseFn: () => Promise<T>,\n maxTries: number,\n backoff: number[]\n): Promise<T> {\n const fallbackBackoff = backoff.length > 0 ? backoff[backoff.length - 1] : 0;\n\n let attempt = 0;\n\n while (true) {\n attempt++;\n\n const promise = promiseFn();\n try {\n return await promise;\n } catch (err) {\n if (attempt >= maxTries) {\n // Fail the entire promise right now\n throw new Error(`Failed after ${maxTries} attempts: ${String(err)}`);\n }\n }\n\n // Do another retry\n const delay = backoff[attempt - 1] ?? fallbackBackoff;\n await wait(delay);\n }\n}\n","import { isPlainObject, shallow } from \"@liveblocks/core\";\n\n/**\n * Two-level deep shallow check.\n * Useful for checking equality of { isLoading: false, myData: [ ... ] } like\n * data structures, where you want to do a shallow comparison on the \"data\"\n * key.\n *\n * NOTE: Works on objects only, not on arrays!\n */\nexport function shallow2(a: unknown, b: unknown): boolean {\n if (!isPlainObject(a) || !isPlainObject(b)) {\n return shallow(a, b);\n }\n\n const keysA = Object.keys(a);\n if (keysA.length !== Object.keys(b).length) {\n return false;\n }\n\n return keysA.every(\n (key) =>\n Object.prototype.hasOwnProperty.call(b, key) && shallow(a[key], b[key])\n );\n}\n","import type { Reducer } from \"react\";\nimport { useCallback, useReducer } from \"react\";\n\nimport { useLatest } from \"./use-latest\";\n\nconst noop = <T>(state: T) => state;\n\n/**\n * \"Freezes\" a given value, so that it will return the same value/instance on\n * each subsequent render. This can be used to freeze \"initial\" values for\n * custom hooks, much like how `useState(initialState)` or\n * `useRef(initialValue)` works.\n */\nexport function useInitial<T>(value: T): T {\n // Equivalent to useState(() => value)[0], but slightly more low-level\n return useReducer<Reducer<T, unknown>>(noop, value)[0];\n}\n\n/**\n * Like `useInitial`, but if the provided value is a function instance, will\n * instead return a stable wrapper that _is_ a stable reference itself between\n * re-renders, but one which will always call the _latest_ provided callback\n * instance.\n */\nexport function useInitialUnlessFunction<T>(latestValue: T): T {\n const frozenValue = useInitial(latestValue);\n\n // Normally the Rules of Hooks™ dictate that you should not call hooks\n // conditionally. In this case, we're good here, because the same code path\n // will always be taken on every subsequent render here, because we've frozen\n // the value.\n /* eslint-disable react-hooks/rules-of-hooks */\n if (typeof frozenValue === \"function\") {\n type Fn = T & ((...args: unknown[]) => unknown);\n const ref = useLatest(latestValue as Fn);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useCallback(((...args: unknown[]) => ref.current(...args)) as Fn, [\n ref,\n ]);\n } else {\n return frozenValue;\n }\n /* eslint-enable react-hooks/rules-of-hooks */\n}\n","import { useEffect, useRef } from \"react\";\n\n/**\n * Keeps a ref in sync with a given value that may or may not change on\n * every render.\n *\n * The purpose of this hook is to return a stable ref that can be passed\n * to a callback function so the callback can be registered but still can\n * access the latest value at a later point in time.\n */\nexport function useLatest<T>(value: T): { readonly current: T } {\n const ref = useRef(value);\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref;\n}\n","// import React from \"react\";\n\n/**\n * Drop-in replacement for React 19's `use` hook.\n */\nexport const use =\n // React.use ||\n <T>(\n promise: Promise<T> & {\n status?: \"pending\" | \"fulfilled\" | \"rejected\";\n value?: T;\n reason?: unknown;\n }\n ): T => {\n if (promise.status === \"pending\") {\n throw promise;\n } else if (promise.status === \"fulfilled\") {\n return promise.value as T;\n } else if (promise.status === \"rejected\") {\n throw promise.reason;\n } else {\n promise.status = \"pending\";\n promise.then(\n (v) => {\n promise.status = \"fulfilled\";\n promise.value = v;\n },\n (e) => {\n promise.status = \"rejected\";\n promise.reason = e;\n }\n );\n throw promise;\n }\n };\n","import type {\n AsyncResult,\n BaseMetadata,\n CommentData,\n CommentReaction,\n CommentUserReaction,\n DistributiveOmit,\n HistoryVersion,\n InboxNotificationData,\n InboxNotificationDeleteInfo,\n Patchable,\n Resolve,\n RoomNotificationSettings,\n Store,\n ThreadData,\n ThreadDataWithDeleteInfo,\n ThreadDeleteInfo,\n} from \"@liveblocks/core\";\nimport {\n compactObject,\n console,\n createStore,\n mapValues,\n nanoid,\n} from \"@liveblocks/core\";\n\nimport { isMoreRecentlyUpdated } from \"./lib/compare\";\n\ntype OptimisticUpdate<M extends BaseMetadata> =\n | CreateThreadOptimisticUpdate<M>\n | DeleteThreadOptimisticUpdate\n | EditThreadMetadataOptimisticUpdate<M>\n | MarkThreadAsResolvedOptimisticUpdate\n | MarkThreadAsUnresolvedOptimisticUpdate\n | CreateCommentOptimisticUpdate\n | EditCommentOptimisticUpdate\n | DeleteCommentOptimisticUpdate\n | AddReactionOptimisticUpdate\n | RemoveReactionOptimisticUpdate\n | MarkInboxNotificationAsReadOptimisticUpdate\n | MarkAllInboxNotificationsAsReadOptimisticUpdate\n | DeleteInboxNotificationOptimisticUpdate\n | DeleteAllInboxNotificationsOptimisticUpdate\n | UpdateNotificationSettingsOptimisticUpdate;\n\ntype CreateThreadOptimisticUpdate<M extends BaseMetadata> = {\n type: \"create-thread\";\n id: string;\n roomId: string;\n thread: ThreadData<M>;\n};\n\ntype DeleteThreadOptimisticUpdate = {\n type: \"delete-thread\";\n id: string;\n roomId: string;\n threadId: string;\n deletedAt: Date;\n};\n\ntype EditThreadMetadataOptimisticUpdate<M extends BaseMetadata> = {\n type: \"edit-thread-metadata\";\n id: string;\n threadId: string;\n metadata: Resolve<Patchable<M>>;\n updatedAt: Date;\n};\n\ntype MarkThreadAsResolvedOptimisticUpdate = {\n type: \"mark-thread-as-resolved\";\n id: string;\n threadId: string;\n updatedAt: Date;\n};\n\ntype MarkThreadAsUnresolvedOptimisticUpdate = {\n type: \"mark-thread-as-unresolved\";\n id: string;\n threadId: string;\n updatedAt: Date;\n};\n\ntype CreateCommentOptimisticUpdate = {\n type: \"create-comment\";\n id: string;\n comment: CommentData;\n};\n\ntype EditCommentOptimisticUpdate = {\n type: \"edit-comment\";\n id: string;\n comment: CommentData;\n};\n\ntype DeleteCommentOptimisticUpdate = {\n type: \"delete-comment\";\n id: string;\n roomId: string;\n threadId: string;\n deletedAt: Date;\n commentId: string;\n};\n\ntype AddReactionOptimisticUpdate = {\n type: \"add-reaction\";\n id: string;\n threadId: string;\n commentId: string;\n reaction: CommentUserReaction;\n};\n\ntype RemoveReactionOptimisticUpdate = {\n type: \"remove-reaction\";\n id: string;\n threadId: string;\n commentId: string;\n emoji: string;\n userId: string;\n removedAt: Date;\n};\n\ntype MarkInboxNotificationAsReadOptimisticUpdate = {\n type: \"mark-inbox-notification-as-read\";\n id: string;\n inboxNotificationId: string;\n readAt: Date;\n};\n\ntype MarkAllInboxNotificationsAsReadOptimisticUpdate = {\n type: \"mark-all-inbox-notifications-as-read\";\n id: string;\n readAt: Date;\n};\n\ntype DeleteInboxNotificationOptimisticUpdate = {\n type: \"delete-inbox-notification\";\n id: string;\n inboxNotificationId: string;\n deletedAt: Date;\n};\n\ntype DeleteAllInboxNotificationsOptimisticUpdate = {\n type: \"delete-all-inbox-notifications\";\n id: string;\n deletedAt: Date;\n};\n\ntype UpdateNotificationSettingsOptimisticUpdate = {\n type: \"update-notification-settings\";\n id: string;\n roomId: string;\n settings: Partial<RoomNotificationSettings>;\n};\n\ntype QueryState = AsyncResult<undefined>;\n// ^^^^^^^^^ We don't store the actual query result in this status\n\ntype InternalState<M extends BaseMetadata> = Readonly<{\n queries: Record<string, QueryState>;\n optimisticUpdates: readonly OptimisticUpdate<M>[];\n\n rawThreadsById: Record<string, ThreadDataWithDeleteInfo<M>>;\n inboxNotificationsById: Record<string, InboxNotificationData>;\n notificationSettingsByRoomId: Record<string, RoomNotificationSettings>;\n versionsByRoomId: Record<string, HistoryVersion[]>;\n}>;\n\n/**\n * Externally observable state of the store, which will have:\n * - Optimistic updates applied\n * - All deleted threads removed from the threads list\n */\nexport type UmbrellaStoreState<M extends BaseMetadata> = {\n /**\n * Keep track of loading and error status of all the queries made by the client.\n * e.g. 'room-abc-{\"color\":\"red\"}' - ok\n * e.g. 'room-abc-{}' - loading\n */\n queries: Record<string, QueryState>;\n\n /**\n * All threads in a sorted array, optimistic updates applied, without deleted\n * threads.\n */\n threads: ThreadData<M>[];\n\n /**\n * All threads in a map, keyed by thread ID, with all optimistic updates\n * applied. Deleted threads are still in this mapping, and will have\n * a deletedAt field if so.\n */\n threadsById: Record<string, ThreadDataWithDeleteInfo<M>>;\n\n /**\n * All inbox notifications in a sorted array, optimistic updates applied.\n */\n inboxNotifications: InboxNotificationData[];\n\n /**\n * Inbox notifications by ID.\n * e.g. `in_${string}`\n */\n inboxNotificationsById: Record<string, InboxNotificationData>;\n\n /**\n * Notification settings by room ID.\n * e.g. { 'room-abc': { threads: \"all\" },\n * 'room-def': { threads: \"replies_and_mentions\" },\n * 'room-xyz': { threads: \"none\" },\n * }\n */\n notificationSettingsByRoomId: Record<string, RoomNotificationSettings>;\n /**\n * Versions by roomId\n * e.g. { 'room-abc': {versions: \"all versions\"}}\n */\n versionsByRoomId: Record<string, HistoryVersion[]>;\n};\n\nexport class UmbrellaStore<M extends BaseMetadata> {\n private _store: Store<InternalState<M>>;\n private _prevState: InternalState<M> | null = null;\n private _stateCached: UmbrellaStoreState<M> | null = null;\n\n constructor() {\n this._store = createStore<InternalState<M>>({\n rawThreadsById: {},\n queries: {},\n optimisticUpdates: [],\n inboxNotificationsById: {},\n notificationSettingsByRoomId: {},\n versionsByRoomId: {},\n });\n\n // Auto-bind all of this class methods once here, so we can use stable\n // references to them (most important for use in useSyncExternalStore)\n this.getThreads = this.getThreads.bind(this);\n this.getInboxNotifications = this.getInboxNotifications.bind(this);\n this.getNotificationSettings = this.getNotificationSettings.bind(this);\n this.getVersions = this.getVersions.bind(this);\n this.subscribeThreads = this.subscribeThreads.bind(this);\n this.subscribeInboxNotifications =\n this.subscribeInboxNotifications.bind(this);\n this.subscribeNotificationSettings =\n this.subscribeNotificationSettings.bind(this);\n this.subscribeVersions = this.subscribeVersions.bind(this);\n\n // APIs only used by the E2E tests at the moment\n this._hasOptimisticUpdates = this._hasOptimisticUpdates.bind(this);\n this._subscribeOptimisticUpdates =\n this._subscribeOptimisticUpdates.bind(this);\n }\n\n private get(): UmbrellaStoreState<M> {\n // Don't return the raw internal state immediately! Return a new computed\n // cached state (with optimistic updates applied) instead, and cache that\n // until the next .set() call invalidates it.\n const rawState = this._store.get();\n if (this._prevState !== rawState || this._stateCached === null) {\n this._prevState = rawState;\n this._stateCached = applyOptimisticUpdates(rawState);\n }\n return this._stateCached;\n }\n\n public getThreads(): UmbrellaStoreState<M> {\n return this.get();\n }\n\n public getInboxNotifications(): UmbrellaStoreState<M> {\n // TODO Return only the stable reference to the inboxNotifications property\n return this.get();\n }\n\n public getNotificationSettings(): UmbrellaStoreState<M> {\n // TODO Return only the stable reference to the notificationSettings property\n return this.get();\n }\n\n public getVersions(): UmbrellaStoreState<M> {\n return this.get();\n }\n\n /**\n * @private Only used by the E2E test suite.\n */\n public _hasOptimisticUpdates(): boolean {\n return this._store.get().optimisticUpdates.length > 0;\n }\n\n private subscribe(callback: () => void): () => void {\n return this._store.subscribe(callback);\n }\n\n /**\n * @private Only used by the E2E test suite.\n */\n public _subscribeOptimisticUpdates(callback: () => void): () => void {\n // TODO Make this actually only update when optimistic updates are changed\n return this.subscribe(callback);\n }\n\n public subscribeThreads(callback: () => void): () => void {\n // TODO Make this actually only update when threads are invalidated\n return this.subscribe(callback);\n }\n\n public subscribeInboxNotifications(callback: () => void): () => void {\n // TODO Make this actually only update when inbox notifications are invalidated\n return this.subscribe(callback);\n }\n\n public subscribeNotificationSettings(callback: () => void): () => void {\n // TODO Make this actually only update when notification settings are invalidated\n return this.subscribe(callback);\n }\n\n public subscribeVersions(callback: () => void): () => void {\n // TODO Make this actually only update when versions are invalidated\n return this.subscribe(callback);\n }\n\n // Direct low-level cache mutations ------------------------------------------------- {{{\n\n private updateThreadsCache(\n mapFn: (\n cache: Readonly<Record<string, ThreadDataWithDeleteInfo<M>>>\n ) => Readonly<Record<string, ThreadDataWithDeleteInfo<M>>>\n ): void {\n this._store.set((state) => {\n const threads = mapFn(state.rawThreadsById);\n return threads !== state.rawThreadsById\n ? { ...state, rawThreadsById: threads }\n : state;\n });\n }\n\n private updateInboxNotificationsCache(\n mapFn: (\n cache: Readonly<Record<string, InboxNotificationData>>\n ) => Readonly<Record<string, InboxNotificationData>>\n ): void {\n this._store.set((state) => {\n const inboxNotifications = mapFn(state.inboxNotificationsById);\n return inboxNotifications !== state.inboxNotificationsById\n ? { ...state, inboxNotificationsById: inboxNotifications }\n : state;\n });\n }\n\n private setNotificationSettings(\n roomId: string,\n settings: RoomNotificationSettings\n ): void {\n this._store.set((state) => ({\n ...state,\n notificationSettingsByRoomId: {\n ...state.notificationSettingsByRoomId,\n [roomId]: settings,\n },\n }));\n }\n\n private setVersions(roomId: string, versions: HistoryVersion[]): void {\n this._store.set((state) => ({\n ...state,\n versionsByRoomId: {\n ...state.versionsByRoomId,\n [roomId]: versions,\n },\n }));\n }\n\n private setQueryState(queryKey: string, queryState: QueryState): void {\n this._store.set((state) => ({\n ...state,\n queries: {\n ...state.queries,\n [queryKey]: queryState,\n },\n }));\n }\n\n private updateOptimisticUpdatesCache(\n mapFn: (\n cache: readonly OptimisticUpdate<M>[]\n ) => readonly OptimisticUpdate<M>[]\n ): void {\n this._store.set((state) => ({\n ...state,\n optimisticUpdates: mapFn(state.optimisticUpdates),\n }));\n }\n\n // ---------------------------------------------------------------------------------- }}}\n\n /** @internal - Only call this method from unit tests. */\n public force_set(\n callback: (currentState: InternalState<M>) => InternalState<M>\n ): void {\n return this._store.set(callback);\n }\n\n /**\n * Updates an existing inbox notification with a new value, replacing the\n * corresponding optimistic update.\n *\n * This will not update anything if the inbox notification ID isn't found in\n * the cache.\n */\n public updateInboxNotification(\n inboxNotificationId: string,\n optimisticUpdateId: string,\n callback: (\n notification: Readonly<InboxNotificationData>\n ) => Readonly<InboxNotificationData>\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n this.removeOptimisticUpdate(optimisticUpdateId); // 1️⃣\n\n // 2️⃣\n this.updateInboxNotificationsCache((cache) => {\n const existing = cache[inboxNotificationId];\n if (!existing) {\n // If the inbox notification doesn't exist in the cache, we do not\n // change anything\n return cache;\n }\n\n const inboxNotifications = {\n ...cache,\n [inboxNotificationId]: callback(existing),\n };\n return inboxNotifications;\n });\n });\n }\n\n /**\n * Updates *all* inbox notifications by running a mapper function over all of\n * them, replacing the corresponding optimistic update.\n */\n public updateAllInboxNotifications(\n optimisticUpdateId: string,\n mapFn: (\n notification: Readonly<InboxNotificationData>\n ) => Readonly<InboxNotificationData>\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n this.removeOptimisticUpdate(optimisticUpdateId); // 1️⃣\n this.updateInboxNotificationsCache((cache) => mapValues(cache, mapFn)); // 2️⃣\n });\n }\n\n /**\n * Deletes an existing inbox notification, replacing the corresponding\n * optimistic update.\n */\n public deleteInboxNotification(\n inboxNotificationId: string,\n optimisticUpdateId: string\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n this.removeOptimisticUpdate(optimisticUpdateId); // 1️⃣\n\n // 2️⃣\n this.updateInboxNotificationsCache((cache) => {\n // Delete it\n const { [inboxNotificationId]: removed, ...newCache } = cache;\n return removed === undefined ? cache : newCache;\n });\n });\n }\n\n /**\n * Deletes *all* inbox notifications, replacing the corresponding optimistic\n * update.\n */\n public deleteAllInboxNotifications(optimisticUpdateId: string): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n this.removeOptimisticUpdate(optimisticUpdateId); // 1️⃣\n this.updateInboxNotificationsCache(() => ({})); // 2️⃣ empty the cache\n });\n }\n\n /**\n * Creates an new thread, replacing the corresponding optimistic update.\n */\n public createThread(\n optimisticUpdateId: string,\n thread: Readonly<ThreadDataWithDeleteInfo<M>>\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n this.removeOptimisticUpdate(optimisticUpdateId); // 1️⃣j\n this.updateThreadsCache((cache) => ({ ...cache, [thread.id]: thread })); // 2️⃣\n });\n }\n\n /**\n * Updates an existing thread with a new value, replacing the corresponding\n * optimistic update.\n *\n * This will not update anything if:\n * - The thread ID isn't found in the cache; or\n * - The thread ID was already deleted from the cache; or\n * - The thread ID in the cache was updated more recently than the optimistic\n * update's timestamp (if given)\n */\n private updateThread(\n threadId: string,\n optimisticUpdateId: string | null,\n callback: (\n thread: Readonly<ThreadDataWithDeleteInfo<M>>\n ) => Readonly<ThreadDataWithDeleteInfo<M>>,\n updatedAt?: Date // TODO We could look this up from the optimisticUpdate instead?\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n if (optimisticUpdateId !== null) {\n this.removeOptimisticUpdate(optimisticUpdateId); // 1️⃣\n }\n\n // 2️⃣\n this.updateThreadsCache((cache) => {\n const existing = cache[threadId];\n\n // If the thread doesn't exist in the cache, we do not update the metadata\n if (!existing) {\n return cache;\n }\n\n // If the thread has been deleted, we do not update the metadata\n if (existing.deletedAt !== undefined) {\n return cache;\n }\n\n if (\n !!updatedAt &&\n !!existing.updatedAt &&\n existing.updatedAt > updatedAt\n ) {\n return cache;\n }\n\n return { ...cache, [threadId]: callback(existing) };\n });\n });\n }\n\n public patchThread(\n threadId: string,\n optimisticUpdateId: string | null,\n patch: {\n // Only these fields are currently supported to patch\n metadata?: M;\n resolved?: boolean;\n },\n updatedAt: Date // TODO We could look this up from the optimisticUpdate instead?\n ): void {\n return this.updateThread(\n threadId,\n optimisticUpdateId,\n (thread) => ({ ...thread, ...compactObject(patch) }),\n updatedAt\n );\n }\n\n public addReaction(\n threadId: string,\n optimisticUpdateId: string | null,\n commentId: string,\n reaction: CommentUserReaction,\n createdAt: Date // TODO We could look this up from the optimisticUpdate instead?\n ): void {\n this.updateThread(\n threadId,\n optimisticUpdateId,\n (thread) => applyAddReaction(thread, commentId, reaction),\n createdAt\n );\n }\n\n public removeReaction(\n threadId: string,\n optimisticUpdateId: string | null,\n commentId: string,\n emoji: string,\n userId: string,\n removedAt: Date\n ): void {\n this.updateThread(\n threadId,\n optimisticUpdateId,\n (thread) =>\n applyRemoveReaction(thread, commentId, emoji, userId, removedAt),\n removedAt\n );\n }\n\n /**\n * Soft-deletes an existing thread by setting its `deletedAt` value,\n * replacing the corresponding optimistic update.\n *\n * This will not update anything if:\n * - The thread ID isn't found in the cache; or\n * - The thread ID was already deleted from the cache\n */\n public deleteThread(\n threadId: string,\n optimisticUpdateId: string | null\n ): void {\n return this.updateThread(\n threadId,\n optimisticUpdateId,\n\n // A deletion is actually an update of the deletedAt property internally\n (thread) => ({ ...thread, updatedAt: new Date(), deletedAt: new Date() })\n );\n }\n\n /**\n * Creates an existing comment and ensures the associated notification is\n * updated correctly, replacing the corresponding optimistic update.\n */\n public createComment(\n newComment: CommentData,\n optimisticUpdateId: string\n ): void {\n // Batch 1️⃣ + 2️⃣ + 3️⃣\n this._store.batch(() => {\n // 1️⃣\n this.removeOptimisticUpdate(optimisticUpdateId);\n\n // If the associated thread is not found, we cannot create a comment under it\n const existingThread =\n this._store.get().rawThreadsById[newComment.threadId];\n if (!existingThread) {\n return;\n }\n\n // 2️⃣ Update the thread instance by adding a comment under it\n this.updateThreadsCache((cache) => ({\n ...cache,\n [newComment.threadId]: applyUpsertComment(existingThread, newComment),\n }));\n\n // 3️⃣ Update the associated inbox notification (if any)\n this.updateInboxNotificationsCache((cache) => {\n const existingNotification = Object.values(cache).find(\n (notification) =>\n notification.kind === \"thread\" &&\n notification.threadId === newComment.threadId\n );\n\n if (!existingNotification) {\n // Nothing to update here\n return cache;\n }\n\n // If the thread has an inbox notification associated with it, we update the notification's `notifiedAt` and `readAt` values\n return {\n ...cache,\n [existingNotification.id]: {\n ...existingNotification,\n notifiedAt: newComment.createdAt,\n readAt: newComment.createdAt,\n },\n };\n });\n });\n }\n\n public editComment(\n threadId: string,\n optimisticUpdateId: string,\n editedComment: CommentData\n ): void {\n return this.updateThread(threadId, optimisticUpdateId, (thread) =>\n applyUpsertComment(thread, editedComment)\n );\n }\n\n public deleteComment(\n threadId: string,\n optimisticUpdateId: string,\n commentId: string,\n deletedAt: Date\n ): void {\n return this.updateThread(\n threadId,\n optimisticUpdateId,\n (thread) => applyDeleteComment(thread, commentId, deletedAt),\n deletedAt\n );\n }\n\n public updateThreadAndNotification(\n thread: ThreadData<M>,\n inboxNotification?: InboxNotificationData\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n // 1️⃣\n this.updateThreadsCache((cache) => {\n const existingThread = cache[thread.id];\n return existingThread === undefined ||\n isMoreRecentlyUpdated(thread, existingThread)\n ? { ...cache, [thread.id]: thread }\n : cache;\n });\n\n // 2️⃣\n if (inboxNotification !== undefined) {\n this.updateInboxNotificationsCache((cache) => ({\n ...cache,\n [inboxNotification.id]: inboxNotification,\n }));\n }\n });\n }\n\n public updateThreadsAndNotifications(\n threads: ThreadData<M>[],\n inboxNotifications: InboxNotificationData[],\n deletedThreads: ThreadDeleteInfo[],\n deletedInboxNotifications: InboxNotificationDeleteInfo[],\n queryKey?: string\n ): void {\n // Batch 1️⃣ + 2️⃣ + 3️⃣\n this._store.batch(() => {\n // 1️⃣\n this.updateThreadsCache((cache) =>\n applyThreadUpdates(cache, {\n newThreads: threads,\n deletedThreads,\n })\n );\n\n // 2️⃣\n this.updateInboxNotificationsCache((cache) =>\n applyNotificationsUpdates(cache, {\n newInboxNotifications: inboxNotifications,\n deletedNotifications: deletedInboxNotifications,\n })\n );\n\n // 3️⃣\n if (queryKey !== undefined) {\n this.setQueryOK(queryKey);\n }\n });\n }\n\n /**\n * Updates existing notification setting for a room with a new value,\n * replacing the corresponding optimistic update.\n */\n public updateRoomInboxNotificationSettings2(\n roomId: string,\n optimisticUpdateId: string,\n settings: Readonly<RoomNotificationSettings>\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n this.removeOptimisticUpdate(optimisticUpdateId); // 1️⃣\n this.setNotificationSettings(roomId, settings); // 2️⃣\n });\n }\n\n public updateRoomInboxNotificationSettings(\n roomId: string,\n settings: RoomNotificationSettings,\n queryKey: string\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n this.setQueryOK(queryKey); // 1️⃣\n this.setNotificationSettings(roomId, settings); // 2️⃣\n });\n }\n\n public updateRoomVersions(\n roomId: string,\n versions: HistoryVersion[],\n queryKey?: string\n ): void {\n // Batch 1️⃣ + 2️⃣\n this._store.batch(() => {\n this.setVersions(roomId, versions); // 1️⃣\n\n // 2️⃣\n if (queryKey !== undefined) {\n this.setQueryOK(queryKey);\n }\n });\n }\n\n public addOptimisticUpdate(\n optimisticUpdate: DistributiveOmit<OptimisticUpdate<M>, \"id\">\n ): string {\n const id = nanoid();\n const newUpdate: OptimisticUpdate<M> = { ...optimisticUpdate, id };\n this.updateOptimisticUpdatesCache((cache) => [...cache, newUpdate]);\n return id;\n }\n\n public removeOptimisticUpdate(optimisticUpdateId: string): void {\n this.updateOptimisticUpdatesCache((cache) =>\n cache.filter((ou) => ou.id !== optimisticUpdateId)\n );\n }\n\n //\n // Query State APIs\n //\n\n public setQueryLoading(queryKey: string): void {\n this.setQueryState(queryKey, { isLoading: true });\n }\n\n private setQueryOK(queryKey: string): void {\n this.setQueryState(queryKey, { isLoading: false, data: undefined });\n }\n\n public setQueryError(queryKey: string, error: Error): void {\n this.setQueryState(queryKey, { isLoading: false, error });\n }\n}\n\nfunction applyOptimisticUpdates<M extends BaseMetadata>(\n state: InternalState<M>\n): UmbrellaStoreState<M> {\n const output = {\n threads: { ...state.rawThreadsById },\n inboxNotifications: { ...state.inboxNotificationsById },\n notificationSettings: { ...state.notificationSettingsByRoomId },\n };\n\n for (const optimisticUpdate of state.optimisticUpdates) {\n switch (optimisticUpdate.type) {\n case \"create-thread\": {\n output.threads[optimisticUpdate.thread.id] = optimisticUpdate.thread;\n break;\n }\n case \"edit-thread-metadata\": {\n const thread = output.threads[optimisticUpdate.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n // If the thread has been deleted, we do not apply the update\n if (thread.deletedAt !== undefined) {\n break;\n }\n\n // If the thread has been updated since the optimistic update, we do not apply the update\n if (\n thread.updatedAt !== undefined &&\n thread.updatedAt > optimisticUpdate.updatedAt\n ) {\n break;\n }\n\n output.threads[thread.id] = {\n ...thread,\n updatedAt: optimisticUpdate.updatedAt,\n metadata: {\n ...thread.metadata,\n ...optimisticUpdate.metadata,\n },\n };\n\n break;\n }\n case \"mark-thread-as-resolved\": {\n const thread = output.threads[optimisticUpdate.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n // If the thread has been deleted, we do not apply the update\n if (thread.deletedAt !== undefined) {\n break;\n }\n\n output.threads[thread.id] = {\n ...thread,\n resolved: true,\n };\n\n break;\n }\n case \"mark-thread-as-unresolved\": {\n const thread = output.threads[optimisticUpdate.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n // If the thread has been deleted, we do not apply the update\n if (thread.deletedAt !== undefined) {\n break;\n }\n\n output.threads[thread.id] = {\n ...thread,\n resolved: false,\n };\n\n break;\n }\n case \"create-comment\": {\n const thread = output.threads[optimisticUpdate.comment.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n output.threads[thread.id] = applyUpsertComment(\n thread,\n optimisticUpdate.comment\n );\n\n const inboxNotification = Object.values(output.inboxNotifications).find(\n (notification) =>\n notification.kind === \"thread\" &&\n notification.threadId === thread.id\n );\n\n if (inboxNotification === undefined) {\n break;\n }\n\n output.inboxNotifications[inboxNotification.id] = {\n ...inboxNotification,\n notifiedAt: optimisticUpdate.comment.createdAt,\n readAt: optimisticUpdate.comment.createdAt,\n };\n\n break;\n }\n case \"edit-comment\": {\n const thread = output.threads[optimisticUpdate.comment.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n output.threads[thread.id] = applyUpsertComment(\n thread,\n optimisticUpdate.comment\n );\n\n break;\n }\n case \"delete-comment\": {\n const thread = output.threads[optimisticUpdate.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n output.threads[thread.id] = applyDeleteComment(\n thread,\n optimisticUpdate.commentId,\n optimisticUpdate.deletedAt\n );\n\n break;\n }\n\n case \"delete-thread\": {\n const thread = output.threads[optimisticUpdate.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n output.threads[optimisticUpdate.threadId] = {\n ...output.threads[optimisticUpdate.threadId],\n deletedAt: optimisticUpdate.deletedAt,\n updatedAt: optimisticUpdate.deletedAt,\n comments: [],\n };\n break;\n }\n case \"add-reaction\": {\n const thread = output.threads[optimisticUpdate.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n output.threads[thread.id] = applyAddReaction(\n thread,\n optimisticUpdate.commentId,\n optimisticUpdate.reaction\n );\n\n break;\n }\n case \"remove-reaction\": {\n const thread = output.threads[optimisticUpdate.threadId];\n // If the thread doesn't exist in the cache, we do not apply the update\n if (thread === undefined) {\n break;\n }\n\n output.threads[thread.id] = applyRemoveReaction(\n thread,\n optimisticUpdate.commentId,\n optimisticUpdate.emoji,\n optimisticUpdate.userId,\n optimisticUpdate.removedAt\n );\n\n break;\n }\n case \"mark-inbox-notification-as-read\": {\n output.inboxNotifications[optimisticUpdate.inboxNotificationId] = {\n ...state.inboxNotificationsById[optimisticUpdate.inboxNotificationId],\n readAt: optimisticUpdate.readAt,\n };\n break;\n }\n case \"mark-all-inbox-notifications-as-read\": {\n for (const id in output.inboxNotifications) {\n output.inboxNotifications[id] = {\n ...output.inboxNotifications[id],\n readAt: optimisticUpdate.readAt,\n };\n }\n break;\n }\n case \"delete-inbox-notification\": {\n const {\n [optimisticUpdate.inboxNotificationId]: _,\n ...inboxNotifications\n } = output.inboxNotifications;\n output.inboxNotifications = inboxNotifications;\n break;\n }\n case \"delete-all-inbox-notifications\": {\n output.inboxNotifications = {};\n break;\n }\n case \"update-notification-settings\": {\n output.notificationSettings[optimisticUpdate.roomId] = {\n ...output.notificationSettings[optimisticUpdate.roomId],\n ...optimisticUpdate.settings,\n };\n }\n }\n }\n\n const cleanedThreads =\n // Don't expose any soft-deleted threads\n Object.values(output.threads).filter(\n (thread): thread is ThreadData<M> => !thread.deletedAt\n );\n\n const cleanedNotifications =\n // Sort so that the most recent notifications are first\n Object.values(output.inboxNotifications).sort(\n (a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime()\n );\n\n return {\n inboxNotifications: cleanedNotifications,\n inboxNotificationsById: output.inboxNotifications,\n notificationSettingsByRoomId: output.notificationSettings,\n queries: state.queries,\n threads: cleanedThreads,\n threadsById: output.threads,\n versionsByRoomId: state.versionsByRoomId,\n };\n}\n\nexport function applyThreadUpdates<M extends BaseMetadata>(\n existingThreads: Record<string, ThreadDataWithDeleteInfo<M>>,\n updates: {\n newThreads: ThreadData<M>[];\n deletedThreads: ThreadDeleteInfo[];\n }\n): Record<string, ThreadData<M>> {\n const updatedThreads = { ...existingThreads };\n\n // Add new threads or update existing threads if the existing thread is older than the new thread.\n updates.newThreads.forEach((thread) => {\n const existingThread = updatedThreads[thread.id];\n\n // If a thread already exists but it's been already more recent, don't update it\n if (existingThread) {\n if (isMoreRecentlyUpdated(existingThread, thread)) {\n return; // Do not update the existing thread\n }\n }\n\n updatedThreads[thread.id] = thread;\n });\n\n // Mark threads in the deletedThreads list as deleted\n updates.deletedThreads.forEach(({ id, deletedAt }) => {\n const existingThread = updatedThreads[id];\n if (existingThread === undefined) return;\n\n existingThread.deletedAt = deletedAt;\n existingThread.updatedAt = deletedAt;\n existingThread.comments = [];\n });\n\n return updatedThreads;\n}\n\nexport function applyNotificationsUpdates(\n existingInboxNotifications: Record<string, InboxNotificationData>,\n updates: {\n newInboxNotifications: InboxNotificationData[];\n deletedNotifications: InboxNotificationDeleteInfo[];\n }\n): Record<string, InboxNotificationData> {\n const updatedInboxNotifications = { ...existingInboxNotifications };\n\n // Add new notifications or update existing notifications if the existing notification is older than the new notification.\n updates.newInboxNotifications.forEach((notification) => {\n const existingNotification = updatedInboxNotifications[notification.id];\n // If the notification already exists, we need to compare the two notifications to determine which one is newer.\n if (existingNotification) {\n const result = compareInboxNotifications(\n existingNotification,\n notification\n );\n\n // If the existing notification is newer than the new notification, we do not update the existing notification.\n if (result === 1) return;\n }\n\n // If the new notification is newer than the existing notification, we update the existing notification.\n updatedInboxNotifications[notification.id] = notification;\n });\n\n updates.deletedNotifications.forEach(\n ({ id }) => delete updatedInboxNotifications[id]\n );\n\n return updatedInboxNotifications;\n}\n\n/**\n * Compares two inbox notifications to determine which one is newer.\n * @param inboxNotificationA The first inbox notification to compare.\n * @param inboxNotificationB The second inbox notification to compare.\n * @returns 1 if inboxNotificationA is newer, -1 if inboxNotificationB is newer, or 0 if they are the same age or can't be compared.\n */\nexport function compareInboxNotifications(\n inboxNotificationA: InboxNotificationData,\n inboxNotificationB: InboxNotificationData\n): number {\n if (inboxNotificationA.notifiedAt > inboxNotificationB.notifiedAt) {\n return 1;\n } else if (inboxNotificationA.notifiedAt < inboxNotificationB.notifiedAt) {\n return -1;\n }\n\n // notifiedAt times are the same, compare readAt times if both are not null\n if (inboxNotificationA.readAt && inboxNotificationB.readAt) {\n return inboxNotificationA.readAt > inboxNotificationB.readAt\n ? 1\n : inboxNotificationA.readAt < inboxNotificationB.readAt\n ? -1\n : 0;\n } else if (inboxNotificationA.readAt || inboxNotificationB.readAt) {\n return inboxNotificationA.readAt ? 1 : -1;\n }\n\n // If all dates are equal, return 0\n return 0;\n}\n\n/** @internal Exported for unit tests only. */\nexport function applyUpsertComment<M extends BaseMetadata>(\n thread: ThreadDataWithDeleteInfo<M>,\n comment: CommentData\n): ThreadDataWithDeleteInfo<M> {\n // If the thread has been deleted, we do not apply the update\n if (thread.deletedAt !== undefined) {\n return thread;\n }\n\n // Validate that the comment belongs to the thread\n if (comment.threadId !== thread.id) {\n console.warn(\n `Comment ${comment.id} does not belong to thread ${thread.id}`\n );\n return thread;\n }\n\n const existingComment = thread.comments.find(\n (existingComment) => existingComment.id === comment.id\n );\n\n // If the comment doesn't exist in the thread, add the comment\n if (existingComment === undefined) {\n const updatedAt = new Date(\n Math.max(thread.updatedAt?.getTime() || 0, comment.createdAt.getTime())\n );\n\n const updatedThread = {\n ...thread,\n updatedAt,\n comments: [...thread.comments, comment],\n };\n\n return updatedThread;\n }\n\n // If the comment exists in the thread and has been deleted, do not apply the update\n if (existingComment.deletedAt !== undefined) {\n return thread;\n }\n\n // Proceed to update the comment if:\n // 1. The existing comment has not been edited\n // 2. The incoming comment has not been edited (i.e. it's a new comment)\n // 3. The incoming comment has been edited more recently than the existing comment\n if (\n existingComment.editedAt === undefined ||\n comment.editedAt === undefined ||\n existingComment.editedAt <= comment.editedAt\n ) {\n const updatedComments = thread.comments.map((existingComment) =>\n existingComment.id === comment.id ? comment : existingComment\n );\n\n const updatedThread = {\n ...thread,\n updatedAt: new Date(\n Math.max(\n thread.updatedAt?.getTime() || 0,\n comment.editedAt?.getTime() || comment.createdAt.getTime()\n )\n ),\n comments: updatedComments,\n };\n return updatedThread;\n }\n\n return thread;\n}\n\n/** @internal Exported for unit tests only. */\nexport function applyDeleteComment<M extends BaseMetadata>(\n thread: ThreadDataWithDeleteInfo<M>,\n commentId: string,\n deletedAt: Date\n): ThreadDataWithDeleteInfo<M> {\n // If the thread has been deleted, we do not delete the comment\n if (thread.deletedAt !== undefined) {\n return thread;\n }\n\n const existingComment = thread.comments.find(\n (comment) => comment.id === commentId\n );\n\n // If the comment doesn't exist in the thread, we cannot perform the deletion\n if (existingComment === undefined) {\n return thread;\n }\n\n // If the comment has been deleted since the deletion request, we do not delete the comment\n if (existingComment.deletedAt !== undefined) {\n return thread;\n }\n\n const updatedComments = thread.comments.map((comment) =>\n comment.id === commentId\n ? {\n ...comment,\n deletedAt,\n body: undefined,\n }\n : comment\n );\n\n // If all comments have been deleted, we mark the thread as deleted\n if (!updatedComments.some((comment) => comment.deletedAt === undefined)) {\n return {\n ...thread,\n deletedAt,\n updatedAt: deletedAt,\n comments: [],\n };\n }\n\n return {\n ...thread,\n updatedAt: deletedAt,\n comments: updatedComments,\n };\n}\n\n/** @internal Exported for unit tests only. */\nexport function applyAddReaction<M extends BaseMetadata>(\n thread: ThreadDataWithDeleteInfo<M>,\n commentId: string,\n reaction: CommentUserReaction\n): ThreadDataWithDeleteInfo<M> {\n // If the thread has been deleted, we do not add the reaction\n if (thread.deletedAt !== undefined) {\n return thread;\n }\n\n const existingComment = thread.comments.find(\n (comment) => comment.id === commentId\n );\n\n // If the comment doesn't exist in the thread, we do not add the reaction\n if (existingComment === undefined) {\n return thread;\n }\n\n // If the comment has been deleted since the reaction addition request, we do not add the reaction\n if (existingComment.deletedAt !== undefined) {\n return thread;\n }\n\n const updatedComments = thread.comments.map((comment) =>\n comment.id === commentId\n ? {\n ...comment,\n reactions: upsertReaction(comment.reactions, reaction),\n }\n : comment\n );\n\n return {\n ...thread,\n updatedAt: new Date(\n Math.max(reaction.createdAt.getTime(), thread.updatedAt?.getTime() || 0)\n ),\n comments: updatedComments,\n };\n}\n\n/** @internal Exported for unit tests only. */\nexport function applyRemoveReaction<M extends BaseMetadata>(\n thread: ThreadDataWithDeleteInfo<M>,\n commentId: string,\n emoji: string,\n userId: string,\n removedAt: Date\n): ThreadDataWithDeleteInfo<M> {\n // If the thread has been deleted, we do not remove the reaction\n if (thread.deletedAt !== undefined) {\n return thread;\n }\n\n const existingComment = thread.comments.find(\n (comment) => comment.id === commentId\n );\n\n // If the comment doesn't exist in the thread, we do not remove the reaction\n if (existingComment === undefined) {\n return thread;\n }\n\n // If the comment has been deleted since the reaction removal request, we do not remove the reaction\n if (existingComment.deletedAt !== undefined) {\n return thread;\n }\n\n const updatedComments = thread.comments.map((comment) =>\n comment.id === commentId\n ? {\n ...comment,\n reactions: comment.reactions\n .map((reaction) =>\n reaction.emoji === emoji\n ? {\n ...reaction,\n users: reaction.users.filter((user) => user.id !== userId),\n }\n : reaction\n )\n .filter((reaction) => reaction.users.length > 0), // Remove reactions with no users left\n }\n : comment\n );\n\n return {\n ...thread,\n updatedAt: new Date(\n Math.max(removedAt.getTime(), thread.updatedAt?.getTime() || 0)\n ),\n comments: updatedComments,\n };\n}\n\nfunction upsertReaction(\n reactions: CommentReaction[],\n reaction: CommentUserReaction\n): CommentReaction[] {\n const existingReaction = reactions.find(\n (existingReaction) => existingReaction.emoji === reaction.emoji\n );\n\n // If the reaction doesn't exist in the comment, we add it\n if (existingReaction === undefined) {\n return [\n ...reactions,\n {\n emoji: reaction.emoji,\n createdAt: reaction.createdAt,\n users: [{ id: reaction.userId }],\n },\n ];\n }\n\n // If the reaction exists in the comment, we add the user to the reaction if they are not already in it\n if (\n existingReaction.users.some((user) => user.id === reaction.userId) === false\n ) {\n return reactions.map((existingReaction) =>\n existingReaction.emoji === reaction.emoji\n ? {\n ...existingReaction,\n users: [...existingReaction.users, { id: reaction.userId }],\n }\n : existingReaction\n );\n }\n\n return reactions;\n}\n","import type { BaseMetadata, CommentBody, Patchable } from \"@liveblocks/core\";\n\n/**\n * @private Internal API, do not rely on it.\n */\nexport class CreateThreadError<M extends BaseMetadata> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n metadata: M;\n }\n ) {\n super(\"Create thread failed.\");\n this.name = \"CreateThreadError\";\n }\n}\n\nexport class DeleteThreadError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n }\n ) {\n super(\"Delete thread failed.\");\n this.name = \"DeleteThreadError\";\n }\n}\n\nexport class EditThreadMetadataError<M extends BaseMetadata> extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n metadata: Patchable<M>;\n }\n ) {\n super(\"Edit thread metadata failed.\");\n this.name = \"EditThreadMetadataError\";\n }\n}\n\nexport class MarkThreadAsResolvedError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n }\n ) {\n super(\"Mark thread as resolved failed.\");\n this.name = \"MarkThreadAsResolvedError\";\n }\n}\n\nexport class MarkThreadAsUnresolvedError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n }\n ) {\n super(\"Mark thread as unresolved failed.\");\n this.name = \"MarkThreadAsUnresolvedError\";\n }\n}\n\nexport class CreateCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Create comment failed.\");\n this.name = \"CreateCommentError\";\n }\n}\n\nexport class EditCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n body: CommentBody;\n }\n ) {\n super(\"Edit comment failed.\");\n this.name = \"EditCommentError\";\n }\n}\n\nexport class DeleteCommentError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n }\n ) {\n super(\"Delete comment failed.\");\n this.name = \"DeleteCommentError\";\n }\n}\n\nexport class AddReactionError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n emoji: string;\n }\n ) {\n super(\"Add reaction failed.\");\n this.name = \"AddReactionError\";\n }\n}\n\nexport class RemoveReactionError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n threadId: string;\n commentId: string;\n emoji: string;\n }\n ) {\n super(\"Remove reaction failed.\");\n this.name = \"RemoveReactionError\";\n }\n}\n\nexport class MarkInboxNotificationAsReadError extends Error {\n constructor(\n public cause: Error,\n public context: {\n inboxNotificationId: string;\n }\n ) {\n super(\"Mark inbox notification as read failed.\");\n this.name = \"MarkInboxNotificationAsReadError\";\n }\n}\n\nexport class UpdateNotificationSettingsError extends Error {\n constructor(\n public cause: Error,\n public context: {\n roomId: string;\n }\n ) {\n super(\"Update notification settings failed.\");\n this.name = \"UpdateNotificationSettingsError\";\n }\n}\n\nexport type CommentsError<M extends BaseMetadata> =\n | CreateThreadError<M>\n | EditThreadMetadataError<M>\n | CreateCommentError\n | EditCommentError\n | DeleteCommentError\n | MarkInboxNotificationAsReadError\n | UpdateNotificationSettingsError;\n","import type {\n BaseMetadata,\n BaseUserMeta,\n BroadcastOptions,\n Client,\n CommentData,\n History,\n HistoryVersion,\n Json,\n JsonObject,\n LiveObject,\n LostConnectionEvent,\n LsonObject,\n OthersEvent,\n Room,\n RoomNotificationSettings,\n Status,\n StorageStatus,\n ThreadData,\n User,\n} from \"@liveblocks/client\";\nimport { shallow } from \"@liveblocks/client\";\nimport type {\n CommentsEventServerMsg,\n DE,\n DM,\n DP,\n DS,\n DU,\n EnterOptions,\n LiveblocksError,\n OpaqueClient,\n OpaqueRoom,\n RoomEventMessage,\n ToImmutable,\n} from \"@liveblocks/core\";\nimport {\n CommentsApiError,\n console,\n createCommentId,\n createThreadId,\n deprecateIf,\n errorIf,\n kInternal,\n makeEventSource,\n makePoller,\n nn,\n NotificationsApiError,\n ServerMsgCode,\n stringify,\n} from \"@liveblocks/core\";\nimport * as React from \"react\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector.js\";\n\nimport { RoomContext, useIsInsideRoom, useRoomOrNull } from \"./contexts\";\nimport { isString } from \"./lib/guards\";\nimport { retryError } from \"./lib/retry-error\";\nimport { useInitial } from \"./lib/use-initial\";\nimport { useLatest } from \"./lib/use-latest\";\nimport { use } from \"./lib/use-polyfill\";\nimport type { GetNotificationSettingsType, GetThreadsType } from \"./liveblocks\";\nimport {\n createSharedContext,\n getUmbrellaStoreForClient,\n LiveblocksProviderWithClient,\n selectThreads,\n useClient,\n useClientOrNull,\n} from \"./liveblocks\";\nimport type {\n CommentReactionOptions,\n CreateCommentOptions,\n CreateThreadOptions,\n DeleteCommentOptions,\n EditCommentOptions,\n EditThreadMetadataOptions,\n HistoryVersionDataState,\n HistoryVersionsState,\n HistoryVersionsStateResolved,\n MutationContext,\n OmitFirstArg,\n RoomContextBundle,\n RoomNotificationSettingsState,\n RoomNotificationSettingsStateSuccess,\n RoomProviderProps,\n StorageStatusSuccess,\n ThreadsState,\n ThreadsStateSuccess,\n ThreadSubscription,\n UseStorageStatusOptions,\n UseThreadsOptions,\n} from \"./types\";\nimport {\n AddReactionError,\n type CommentsError,\n CreateCommentError,\n CreateThreadError,\n DeleteCommentError,\n DeleteThreadError,\n EditCommentError,\n EditThreadMetadataError,\n MarkInboxNotificationAsReadError,\n MarkThreadAsResolvedError,\n MarkThreadAsUnresolvedError,\n RemoveReactionError,\n UpdateNotificationSettingsError,\n} from \"./types/errors\";\nimport type { UmbrellaStore, UmbrellaStoreState } from \"./umbrella-store\";\nimport { useScrollToCommentOnLoadEffect } from \"./use-scroll-to-comment-on-load-effect\";\n\nconst SMOOTH_DELAY = 1000;\n\nconst noop = () => {};\nconst identity: <T>(x: T) => T = (x) => x;\n\nconst missing_unstable_batchedUpdates = (\n reactVersion: number,\n roomId: string\n) =>\n `We noticed you’re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you’re ready to upgrade to React 18:\n\n import { unstable_batchedUpdates } from \"react-dom\"; // or \"react-native\"\n\n <RoomProvider id=${JSON.stringify(\n roomId\n )} ... unstable_batchedUpdates={unstable_batchedUpdates}>\n ...\n </RoomProvider>\n\nWhy? Please see https://liveblocks.io/docs/platform/troubleshooting#stale-props-zombie-child for more information`;\n\nconst superfluous_unstable_batchedUpdates =\n \"You don’t need to pass unstable_batchedUpdates to RoomProvider anymore, since you’re on React 18+ already.\";\n\nfunction useSyncExternalStore<Snapshot>(\n s: (onStoreChange: () => void) => () => void,\n gs: () => Snapshot,\n gss: undefined | null | (() => Snapshot)\n): Snapshot {\n return useSyncExternalStoreWithSelector(s, gs, gss, identity);\n}\n\nconst STABLE_EMPTY_LIST = Object.freeze([]);\n\nexport const POLLING_INTERVAL = 5 * 60 * 1000; // 5 minutes\n\nfunction makeNotificationSettingsQueryKey(roomId: string) {\n return `${roomId}:NOTIFICATION_SETTINGS`;\n}\n\n// Don't try to inline this. This function is intended to be a stable\n// reference, to avoid a React.useCallback() wrapper.\nfunction alwaysEmptyList() {\n return STABLE_EMPTY_LIST;\n}\n\n// Don't try to inline this. This function is intended to be a stable\n// reference, to avoid a React.useCallback() wrapper.\nfunction alwaysNull() {\n return null;\n}\n\nfunction selectorFor_useOthersConnectionIds(\n others: readonly User<JsonObject, BaseUserMeta>[]\n): number[] {\n return others.map((user) => user.connectionId);\n}\n\nfunction selectNotificationSettings<M extends BaseMetadata>(\n roomId: string,\n state: UmbrellaStoreState<M>\n): RoomNotificationSettings {\n const notificationSettings = state.notificationSettingsByRoomId;\n return nn(notificationSettings[roomId]);\n}\n\nfunction makeMutationContext<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n>(room: Room<P, S, U, E, M>): MutationContext<P, S, U> {\n const cannotUseUntil = \"This mutation cannot be used until\";\n const needsPresence = `${cannotUseUntil} connected to the Liveblocks room`;\n const needsStorage = `${cannotUseUntil} storage has been loaded`;\n\n return {\n get storage() {\n const mutableRoot = room.getStorageSnapshot();\n if (mutableRoot === null) {\n throw new Error(needsStorage);\n }\n return mutableRoot;\n },\n\n get self() {\n const self = room.getSelf();\n if (self === null) {\n throw new Error(needsPresence);\n }\n return self;\n },\n\n get others() {\n const others = room.getOthers();\n if (room.getSelf() === null) {\n throw new Error(needsPresence);\n }\n return others;\n },\n\n setMyPresence: room.updatePresence,\n };\n}\n\nfunction getCurrentUserId(room: OpaqueRoom): string {\n const self = room.getSelf();\n if (self === null || self.id === undefined) {\n return \"anonymous\";\n } else {\n return self.id;\n }\n}\n\nfunction handleApiError(err: CommentsApiError | NotificationsApiError): Error {\n const message = `Request failed with status ${err.status}: ${err.message}`;\n\n // Log details about FORBIDDEN errors\n if (err.details?.error === \"FORBIDDEN\") {\n const detailedMessage = [message, err.details.suggestion, err.details.docs]\n .filter(Boolean)\n .join(\"\\n\");\n\n console.error(detailedMessage);\n }\n\n return new Error(message);\n}\n\nconst _extras = new WeakMap<\n OpaqueClient,\n ReturnType<typeof makeExtrasForClient>\n>();\nconst _bundles = new WeakMap<\n OpaqueClient,\n RoomContextBundle<JsonObject, LsonObject, BaseUserMeta, Json, BaseMetadata>\n>();\n\nfunction getOrCreateRoomContextBundle<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n>(client: OpaqueClient): RoomContextBundle<P, S, U, E, M> {\n let bundle = _bundles.get(client);\n if (!bundle) {\n bundle = makeRoomContextBundle(client);\n _bundles.set(client, bundle);\n }\n return bundle as unknown as RoomContextBundle<P, S, U, E, M>;\n}\n\n// TODO: Likely a better / more clear name for this helper will arise. I'll\n// rename this later. All of these are implementation details to support inbox\n// notifications on a per-client basis.\nfunction getExtrasForClient<M extends BaseMetadata>(client: OpaqueClient) {\n let extras = _extras.get(client);\n if (!extras) {\n extras = makeExtrasForClient(client);\n _extras.set(client, extras);\n }\n\n return extras as unknown as Omit<typeof extras, \"store\"> & {\n store: UmbrellaStore<M>;\n };\n}\n\nfunction makeExtrasForClient<M extends BaseMetadata>(client: OpaqueClient) {\n const store = getUmbrellaStoreForClient(client);\n\n const DEFAULT_DEDUPING_INTERVAL = 2000; // 2 seconds\n\n const lastRequestedAtByRoom = new Map<string, Date>(); // A map of room ids to the timestamp when the last request for threads updates was made\n const requestsByQuery = new Map<string, Promise<unknown>>(); // A map of query keys to the promise of the request for that query\n const requestStatusByRoom = new Map<string, boolean>(); // A map of room ids to a boolean indicating whether a request to retrieve threads updates is in progress\n const subscribersByQuery = new Map<string, number>(); // A map of query keys to the number of subscribers for that query\n\n const poller = makePoller(refreshThreadsAndNotifications);\n\n async function refreshThreadsAndNotifications() {\n const requests: Promise<unknown>[] = [];\n\n client[kInternal].getRoomIds().map((roomId) => {\n const room = client.getRoom(roomId);\n if (room === null) return;\n\n // Retrieve threads that have been updated/deleted since the last requestedAt value\n requests.push(getThreadsUpdates(room.id));\n });\n\n await Promise.allSettled(requests);\n }\n\n function incrementQuerySubscribers(queryKey: string) {\n const subscribers = subscribersByQuery.get(queryKey) ?? 0;\n subscribersByQuery.set(queryKey, subscribers + 1);\n\n poller.start(POLLING_INTERVAL);\n\n // Decrement in the unsub function\n return () => {\n const subscribers = subscribersByQuery.get(queryKey);\n\n if (subscribers === undefined || subscribers <= 0) {\n console.warn(\n `Internal unexpected behavior. Cannot decrease subscriber count for query \"${queryKey}\"`\n );\n return;\n }\n\n subscribersByQuery.set(queryKey, subscribers - 1);\n\n let totalSubscribers = 0;\n for (const subscribers of subscribersByQuery.values()) {\n totalSubscribers += subscribers;\n }\n\n if (totalSubscribers <= 0) {\n poller.stop();\n }\n };\n }\n\n /**\n * Retrieve threads that have been updated/deleted since the last time the room requested threads updates and update the local cache with the new data\n * @param roomId The id of the room for which to retrieve threads updates\n */\n async function getThreadsUpdates(roomId: string) {\n const room = client.getRoom(roomId) as Room<\n never,\n never,\n never,\n never,\n M\n > | null; // TODO: Figure out how to remove this casting\n if (room === null) return;\n\n const since = lastRequestedAtByRoom.get(room.id);\n if (since === undefined) return;\n\n const isFetchingThreadsUpdates = requestStatusByRoom.get(room.id) ?? false;\n // If another request to retrieve threads updates for the room is in progress, we do not start a new one\n if (isFetchingThreadsUpdates === true) return;\n\n try {\n // Set the isFetchingThreadsUpdates flag to true to prevent multiple requests to fetch threads updates for the room from being made at the same time\n requestStatusByRoom.set(room.id, true);\n\n const updates = await room.getThreadsSince({ since });\n\n // Set the isFetchingThreadsUpdates flag to false after a certain interval to prevent multiple requests from being made at the same time\n setTimeout(() => {\n requestStatusByRoom.set(room.id, false);\n }, DEFAULT_DEDUPING_INTERVAL);\n\n store.updateThreadsAndNotifications(\n updates.threads.updated,\n updates.inboxNotifications.updated,\n updates.threads.deleted,\n updates.inboxNotifications.deleted\n );\n\n // Update the `lastRequestedAt` value for the room to the timestamp returned by the current request\n lastRequestedAtByRoom.set(room.id, updates.requestedAt);\n } catch (err) {\n requestStatusByRoom.set(room.id, false);\n // TODO: Implement error handling\n return;\n }\n }\n\n async function getRoomVersions(\n room: OpaqueRoom,\n { retryCount }: { retryCount: number } = { retryCount: 0 }\n ) {\n const queryKey = getVersionsQueryKey(room.id);\n const existingRequest = requestsByQuery.get(queryKey);\n if (existingRequest !== undefined) return existingRequest;\n const request = room[kInternal].listTextVersions();\n requestsByQuery.set(queryKey, request);\n store.setQueryLoading(queryKey);\n try {\n const result = await request;\n const data = (await result.json()) as {\n versions: HistoryVersion[];\n };\n const versions = data.versions.map(({ createdAt, ...version }) => {\n return {\n createdAt: new Date(createdAt),\n ...version,\n };\n });\n store.updateRoomVersions(room.id, versions, queryKey);\n requestsByQuery.delete(queryKey);\n } catch (err) {\n requestsByQuery.delete(queryKey);\n // Retry the action using the exponential backoff algorithm\n retryError(() => {\n void getRoomVersions(room, {\n retryCount: retryCount + 1,\n });\n }, retryCount);\n store.setQueryError(queryKey, err as Error);\n }\n return;\n }\n\n async function getThreadsAndInboxNotifications(\n room: OpaqueRoom,\n queryKey: string,\n options: UseThreadsOptions<M>,\n { retryCount }: { retryCount: number } = { retryCount: 0 }\n ) {\n const existingRequest = requestsByQuery.get(queryKey);\n\n // If a request was already made for the query, we do not make another request and return the existing promise of the request\n if (existingRequest !== undefined) return existingRequest;\n\n const request = room.getThreads(options);\n\n // Store the promise of the request for the query so that we do not make another request for the same query\n requestsByQuery.set(queryKey, request);\n\n store.setQueryLoading(queryKey);\n try {\n const result = await request;\n\n store.updateThreadsAndNotifications(\n result.threads as ThreadData<M>[], // TODO: Figure out how to remove this casting\n result.inboxNotifications,\n [],\n [],\n queryKey\n );\n\n const lastRequestedAt = lastRequestedAtByRoom.get(room.id);\n\n /**\n * We set the `lastRequestedAt` value for the room to the timestamp returned by the current request if:\n * 1. The `lastRequestedAt` value for the room has not been set\n * OR\n * 2. The `lastRequestedAt` value for the room is older than the timestamp returned by the current request\n */\n if (\n lastRequestedAt === undefined ||\n lastRequestedAt > result.requestedAt\n ) {\n lastRequestedAtByRoom.set(room.id, result.requestedAt);\n }\n\n poller.start(POLLING_INTERVAL);\n } catch (err) {\n requestsByQuery.delete(queryKey);\n\n // Retry the action using the exponential backoff algorithm\n retryError(() => {\n void getThreadsAndInboxNotifications(room, queryKey, options, {\n retryCount: retryCount + 1,\n });\n }, retryCount);\n\n // Set the query state to the error state\n store.setQueryError(queryKey, err as Error);\n }\n return;\n }\n\n async function getInboxNotificationSettings(\n room: OpaqueRoom,\n queryKey: string,\n { retryCount }: { retryCount: number } = { retryCount: 0 }\n ) {\n const existingRequest = requestsByQuery.get(queryKey);\n\n // If a request was already made for the notifications query, we do not make another request and return the existing promise\n if (existingRequest !== undefined) return existingRequest;\n\n try {\n const request = room.getNotificationSettings();\n\n requestsByQuery.set(queryKey, request);\n\n store.setQueryLoading(queryKey);\n\n const settings = await request;\n\n store.updateRoomInboxNotificationSettings(room.id, settings, queryKey);\n } catch (err) {\n requestsByQuery.delete(queryKey);\n\n retryError(() => {\n void getInboxNotificationSettings(room, queryKey, {\n retryCount: retryCount + 1,\n });\n }, retryCount);\n\n store.setQueryError(queryKey, err as Error);\n }\n return;\n }\n\n const commentsErrorEventSource = makeEventSource<CommentsError<M>>();\n\n function onMutationFailure(\n innerError: Error,\n optimisticUpdateId: string,\n createPublicError: (error: Error) => CommentsError<M>\n ) {\n store.removeOptimisticUpdate(optimisticUpdateId);\n\n if (innerError instanceof CommentsApiError) {\n const error = handleApiError(innerError);\n commentsErrorEventSource.notify(createPublicError(error));\n return;\n }\n\n if (innerError instanceof NotificationsApiError) {\n handleApiError(innerError);\n // TODO: Create public error and notify via notificationsErrorEventSource?\n return;\n }\n\n throw innerError;\n }\n\n return {\n store,\n incrementQuerySubscribers,\n commentsErrorEventSource,\n getThreadsUpdates,\n getThreadsAndInboxNotifications,\n getInboxNotificationSettings,\n getRoomVersions,\n onMutationFailure,\n };\n}\n\ntype RoomLeavePair<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n> = {\n room: Room<P, S, U, E, M>;\n leave: () => void;\n};\n\nfunction makeRoomContextBundle<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n>(client: Client<U>): RoomContextBundle<P, S, U, E, M> {\n type TRoom = Room<P, S, U, E, M>;\n\n function RoomProvider_withImplicitLiveblocksProvider(\n props: RoomProviderProps<P, S>\n ) {\n // NOTE: Normally, nesting LiveblocksProvider is not allowed. This\n // factory-bound version of the RoomProvider will create an implicit\n // LiveblocksProvider. This means that if an end user nests this\n // RoomProvider under a LiveblocksProvider context, that would be an error.\n // However, we'll allow that nesting only in this specific situation, and\n // only because this wrapper will keep the Liveblocks context and the Room\n // context consistent internally.\n return (\n <LiveblocksProviderWithClient client={client} allowNesting>\n <RoomProvider {...props} />\n </LiveblocksProviderWithClient>\n );\n }\n\n const shared = createSharedContext<U>(client);\n\n const bundle: RoomContextBundle<P, S, U, E, M> = {\n RoomContext: RoomContext as React.Context<TRoom | null>,\n RoomProvider: RoomProvider_withImplicitLiveblocksProvider,\n\n useRoom,\n useStatus,\n useStorageStatus,\n\n useBatch,\n useBroadcastEvent,\n useOthersListener,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n useStorageRoot,\n useStorage,\n\n useSelf,\n useMyPresence,\n useUpdateMyPresence,\n useOthers,\n useOthersMapped,\n useOthersConnectionIds,\n useOther,\n\n useMutation: useMutation as RoomContextBundle<P, S, U, E, M>[\"useMutation\"],\n\n useThreads,\n\n useCreateThread,\n useDeleteThread,\n useEditThreadMetadata,\n useMarkThreadAsResolved,\n useMarkThreadAsUnresolved,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n useAddReaction,\n useRemoveReaction,\n useMarkThreadAsRead,\n useThreadSubscription,\n\n useHistoryVersions,\n useHistoryVersionData,\n\n useRoomNotificationSettings,\n useUpdateRoomNotificationSettings,\n\n ...shared.classic,\n\n suspense: {\n RoomContext: RoomContext as React.Context<TRoom | null>,\n RoomProvider: RoomProvider_withImplicitLiveblocksProvider,\n\n useRoom,\n useStatus,\n useStorageStatus: useStorageStatusSuspense,\n\n useBatch,\n useBroadcastEvent,\n useOthersListener,\n useLostConnectionListener,\n useErrorListener,\n useEventListener,\n\n useHistory,\n useUndo,\n useRedo,\n useCanRedo,\n useCanUndo,\n\n useStorageRoot,\n useStorage: useStorageSuspense,\n\n useSelf: useSelfSuspense,\n useMyPresence,\n useUpdateMyPresence,\n useOthers: useOthersSuspense,\n useOthersMapped: useOthersMappedSuspense,\n useOthersConnectionIds: useOthersConnectionIdsSuspense,\n useOther: useOtherSuspense,\n\n useMutation: useMutation as RoomContextBundle<\n P,\n S,\n U,\n E,\n M\n >[\"suspense\"][\"useMutation\"],\n\n useThreads: useThreadsSuspense,\n\n useCreateThread,\n useDeleteThread,\n useEditThreadMetadata,\n useMarkThreadAsResolved,\n useMarkThreadAsUnresolved,\n useCreateComment,\n useEditComment,\n useDeleteComment,\n useAddReaction,\n useRemoveReaction,\n useMarkThreadAsRead,\n useThreadSubscription,\n\n // TODO: useHistoryVersionData: useHistoryVersionDataSuspense,\n useHistoryVersions: useHistoryVersionsSuspense,\n\n useRoomNotificationSettings: useRoomNotificationSettingsSuspense,\n useUpdateRoomNotificationSettings,\n\n ...shared.suspense,\n },\n\n useCommentsErrorListener,\n };\n\n return Object.defineProperty(bundle, kInternal, {\n enumerable: false,\n });\n}\n\nfunction RoomProvider<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n>(props: RoomProviderProps<P, S>) {\n const client = useClient<U>();\n const [cache] = React.useState(\n () => new Map<string, RoomLeavePair<P, S, U, E, M>>()\n );\n\n // Produce a version of client.enterRoom() that when called for the same\n // room ID multiple times, will not keep producing multiple leave\n // functions, but instead return the cached one.\n const stableEnterRoom: typeof client.enterRoom<P, S, E, M> =\n React.useCallback(\n (\n roomId: string,\n options: EnterOptions<P, S>\n ): RoomLeavePair<P, S, U, E, M> => {\n const cached = cache.get(roomId);\n if (cached) return cached;\n\n const rv = client.enterRoom<P, S, E, M>(roomId, options);\n\n // Wrap the leave function to also delete the cached value\n const origLeave = rv.leave;\n rv.leave = () => {\n origLeave();\n cache.delete(roomId);\n };\n\n cache.set(roomId, rv);\n return rv;\n },\n [client, cache]\n );\n\n //\n // RATIONALE:\n // At the \"Outer\" RoomProvider level, we keep a cache and produce\n // a stableEnterRoom function, which we pass down to the real \"Inner\"\n // RoomProvider level.\n //\n // The purpose is to ensure that if `stableEnterRoom(\"my-room\")` is called\n // multiple times for the same room ID, it will always return the exact same\n // (cached) value, so that in total only a single \"leave\" function gets\n // produced and registered in the client.\n //\n // If we didn't use this cache, then in React StrictMode\n // stableEnterRoom(\"my-room\") might get called multiple (at least 4) times,\n // causing more leave functions to be produced in the client, some of which\n // we cannot get a hold on (because StrictMode would discard those results by\n // design). This would make it appear to the Client that the Room is still in\n // use by some party that hasn't called `leave()` on it yet, thus causing the\n // Room to not be freed and destroyed when the component unmounts later.\n //\n return (\n <RoomProviderInner<P, S, U, E, M>\n {...(props as any)}\n stableEnterRoom={stableEnterRoom}\n />\n );\n}\n\ntype EnterRoomType<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n> = (\n roomId: string,\n options: EnterOptions<P, S>\n) => RoomLeavePair<P, S, U, E, M>;\n\n/** @internal */\nfunction RoomProviderInner<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n>(\n props: RoomProviderProps<P, S> & {\n stableEnterRoom: EnterRoomType<P, S, U, E, M>;\n }\n) {\n const client = useClient<U>();\n const { id: roomId, stableEnterRoom } = props;\n\n if (process.env.NODE_ENV !== \"production\") {\n if (!roomId) {\n throw new Error(\n \"RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required\"\n );\n }\n\n if (!isString(roomId)) {\n throw new Error(\"RoomProvider id property should be a string.\");\n }\n\n const majorReactVersion = parseInt(React.version) || 1;\n const oldReactVersion = majorReactVersion < 18;\n errorIf(\n oldReactVersion && props.unstable_batchedUpdates === undefined,\n missing_unstable_batchedUpdates(majorReactVersion, roomId)\n );\n deprecateIf(\n !oldReactVersion && props.unstable_batchedUpdates !== undefined,\n superfluous_unstable_batchedUpdates\n );\n }\n\n // Note: We'll hold on to the initial value given here, and ignore any\n // changes to this argument in subsequent renders\n const frozenProps = useInitial({\n initialPresence: props.initialPresence,\n initialStorage: props.initialStorage,\n unstable_batchedUpdates: props.unstable_batchedUpdates,\n autoConnect: props.autoConnect ?? typeof window !== \"undefined\",\n }) as EnterOptions<P, S>;\n\n const [{ room }, setRoomLeavePair] = React.useState(() =>\n stableEnterRoom(roomId, {\n ...frozenProps,\n autoConnect: false, // Deliberately using false here on the first render, see below\n })\n );\n\n React.useEffect(() => {\n const { store } = getExtrasForClient(client);\n\n async function handleCommentEvent(message: CommentsEventServerMsg) {\n // If thread deleted event is received, we remove the thread from the local cache\n // no need for more processing\n if (message.type === ServerMsgCode.THREAD_DELETED) {\n store.deleteThread(message.threadId, null);\n return;\n }\n\n // TODO: Error handling\n const info = await room.getThread(message.threadId);\n\n // If no thread info was returned (i.e., 404), we remove the thread and relevant inbox notifications from local cache.\n if (!info.thread) {\n store.deleteThread(message.threadId, null);\n return;\n }\n const { thread, inboxNotification } = info;\n\n const existingThread = store.getThreads().threadsById[message.threadId];\n\n switch (message.type) {\n case ServerMsgCode.COMMENT_EDITED:\n case ServerMsgCode.THREAD_METADATA_UPDATED:\n case ServerMsgCode.THREAD_UPDATED:\n case ServerMsgCode.COMMENT_REACTION_ADDED:\n case ServerMsgCode.COMMENT_REACTION_REMOVED:\n case ServerMsgCode.COMMENT_DELETED:\n // If the thread doesn't exist in the local cache, we do not update it with the server data as an optimistic update could have deleted the thread locally.\n if (!existingThread) break;\n\n store.updateThreadAndNotification(thread, inboxNotification);\n break;\n case ServerMsgCode.COMMENT_CREATED:\n store.updateThreadAndNotification(thread, inboxNotification);\n break;\n default:\n break;\n }\n }\n\n return room.events.comments.subscribe(\n (message) => void handleCommentEvent(message)\n );\n }, [client, room]);\n\n React.useEffect(() => {\n const { getThreadsUpdates } = getExtrasForClient(client);\n // Retrieve threads that have been updated/deleted since the last time the room requested threads updates\n void getThreadsUpdates(room.id);\n }, [client, room.id]);\n\n /**\n * Subscribe to the 'online' event to fetch threads/notifications updates when the browser goes back online.\n */\n React.useEffect(() => {\n function handleIsOnline() {\n const { getThreadsUpdates } = getExtrasForClient(client);\n void getThreadsUpdates(room.id);\n }\n\n window.addEventListener(\"online\", handleIsOnline);\n return () => {\n window.removeEventListener(\"online\", handleIsOnline);\n };\n }, [client, room.id]);\n\n React.useEffect(() => {\n const pair = stableEnterRoom(roomId, frozenProps);\n\n setRoomLeavePair(pair);\n const { room, leave } = pair;\n\n // In React, it's important to start connecting to the room as an effect,\n // rather than doing this during the initial render. This means that\n // during the initial render (both on the server-side, and on the first\n // hydration on the client-side), the value of the `useStatus()` hook\n // will correctly be \"initial\", and transition to \"connecting\" as an\n // effect.\n if (frozenProps.autoConnect) {\n room.connect();\n }\n\n return () => {\n leave();\n };\n }, [roomId, frozenProps, stableEnterRoom]);\n\n return (\n <RoomContext.Provider value={room}>{props.children}</RoomContext.Provider>\n );\n}\n\nfunction useRoom<\n P extends JsonObject = DP,\n S extends LsonObject = DS,\n U extends BaseUserMeta = DU,\n E extends Json = DE,\n M extends BaseMetadata = DM,\n>(): Room<P, S, U, E, M> {\n const room = useRoomOrNull<P, S, U, E, M>();\n if (room === null) {\n throw new Error(\"RoomProvider is missing from the React tree.\");\n }\n return room;\n}\n\n/**\n * Returns the current connection status for the Room, and triggers\n * a re-render whenever it changes. Can be used to render a status badge.\n */\nfunction useStatus(): Status {\n const room = useRoom();\n const subscribe = room.events.status.subscribe;\n const getSnapshot = room.getStatus;\n const getServerSnapshot = room.getStatus;\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\n/**\n * Returns the current storage status for the Room, and triggers\n * a re-render whenever it changes. Can be used to render a \"Saving...\"\n * indicator.\n */\nfunction useStorageStatus(options?: UseStorageStatusOptions): StorageStatus {\n // Normally the Rules of Hooks™ dictate that you should not call hooks\n // conditionally. In this case, we're good here, because the same code path\n // will always be taken on every subsequent render here, because we've frozen\n // the value.\n /* eslint-disable react-hooks/rules-of-hooks */\n const smooth = useInitial(options?.smooth ?? false);\n if (smooth) {\n return useStorageStatusSmooth();\n } else {\n return useStorageStatusImmediate();\n }\n /* eslint-enable react-hooks/rules-of-hooks */\n}\n\nfunction useStorageStatusImmediate(): StorageStatus {\n const room = useRoom();\n const subscribe = room.events.storageStatus.subscribe;\n const getSnapshot = room.getStorageStatus;\n const getServerSnapshot = room.getStorageStatus;\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\nfunction useStorageStatusSmooth(): StorageStatus {\n const room = useRoom();\n const [status, setStatus] = React.useState(room.getStorageStatus);\n const oldStatus = useLatest(room.getStorageStatus());\n\n React.useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout>;\n const unsub = room.events.storageStatus.subscribe((newStatus) => {\n if (\n oldStatus.current === \"synchronizing\" &&\n newStatus === \"synchronized\"\n ) {\n // Delay delivery of the \"synchronized\" event\n timeoutId = setTimeout(() => setStatus(newStatus), SMOOTH_DELAY);\n } else {\n clearTimeout(timeoutId);\n setStatus(newStatus);\n }\n });\n\n // Clean up\n return () => {\n clearTimeout(timeoutId);\n unsub();\n };\n }, [room, oldStatus]);\n\n return status;\n}\n\n/**\n * @deprecated It's recommended to use `useMutation` for writing to Storage,\n * which will automatically batch all mutations.\n *\n * Returns a function that batches modifications made during the given function.\n * All the modifications are sent to other clients in a single message.\n * All the modifications are merged in a single history item (undo/redo).\n * All the subscribers are called only after the batch is over.\n */\nfunction useBatch<T>(): (callback: () => T) => T {\n return useRoom().batch;\n}\n\nfunction useBroadcastEvent<E extends Json>(): (\n event: E,\n options?: BroadcastOptions\n) => void {\n const room = useRoom<never, never, never, E, never>();\n return React.useCallback(\n (\n event: E,\n options: BroadcastOptions = { shouldQueueEventIfNotReady: false }\n ) => {\n room.broadcastEvent(event, options);\n },\n [room]\n );\n}\n\nfunction useOthersListener<P extends JsonObject, U extends BaseUserMeta>(\n callback: (event: OthersEvent<P, U>) => void\n) {\n const room = useRoom<P, never, U, never, never>();\n const savedCallback = useLatest(callback);\n React.useEffect(\n () => room.events.others.subscribe((event) => savedCallback.current(event)),\n [room, savedCallback]\n );\n}\n\n/**\n * Get informed when reconnecting to the Liveblocks servers is taking\n * longer than usual. This typically is a sign of a client that has lost\n * internet connectivity.\n *\n * This isn't problematic (because the Liveblocks client is still trying to\n * reconnect), but it's typically a good idea to inform users about it if\n * the connection takes too long to recover.\n *\n * @example\n * useLostConnectionListener(event => {\n * if (event === 'lost') {\n * toast.warn('Reconnecting to the Liveblocks servers is taking longer than usual...')\n * } else if (event === 'failed') {\n * toast.warn('Reconnecting to the Liveblocks servers failed.')\n * } else if (event === 'restored') {\n * toast.clear();\n * }\n * })\n */\nfunction useLostConnectionListener(\n callback: (event: LostConnectionEvent) => void\n): void {\n const room = useRoom();\n const savedCallback = useLatest(callback);\n React.useEffect(\n () =>\n room.events.lostConnection.subscribe((event) =>\n savedCallback.current(event)\n ),\n [room, savedCallback]\n );\n}\n\n/**\n * useErrorListener is a React hook that allows you to respond to potential room\n * connection errors.\n *\n * @example\n * useErrorListener(er => {\n * console.error(er);\n * })\n */\nfunction useErrorListener(callback: (err: LiveblocksError) => void): void {\n const room = useRoom();\n const savedCallback = useLatest(callback);\n React.useEffect(\n () => room.events.error.subscribe((e) => savedCallback.current(e)),\n [room, savedCallback]\n );\n}\n\nfunction useEventListener<\n P extends JsonObject,\n U extends BaseUserMeta,\n E extends Json,\n>(callback: (data: RoomEventMessage<P, U, E>) => void): void {\n const room = useRoom<P, never, U, E, never>();\n const savedCallback = useLatest(callback);\n React.useEffect(() => {\n const listener = (eventData: RoomEventMessage<P, U, E>) => {\n savedCallback.current(eventData);\n };\n\n return room.events.customEvent.subscribe(listener);\n }, [room, savedCallback]);\n}\n\n/**\n * Returns the room.history\n */\nfunction useHistory(): History {\n return useRoom().history;\n}\n\n/**\n * Returns a function that undoes the last operation executed by the current\n * client. It does not impact operations made by other clients.\n */\nfunction useUndo(): () => void {\n return useHistory().undo;\n}\n\n/**\n * Returns a function that redoes the last operation executed by the current\n * client. It does not impact operations made by other clients.\n */\nfunction useRedo(): () => void {\n return useHistory().redo;\n}\n\n/**\n * Returns whether there are any operations to undo.\n */\nfunction useCanUndo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canUndo = room.history.canUndo;\n return useSyncExternalStore(subscribe, canUndo, canUndo);\n}\n\n/**\n * Returns whether there are any operations to redo.\n */\nfunction useCanRedo(): boolean {\n const room = useRoom();\n const subscribe = room.events.history.subscribe;\n const canRedo = room.history.canRedo;\n return useSyncExternalStore(subscribe, canRedo, canRedo);\n}\n\nfunction useSelf<P extends JsonObject, U extends BaseUserMeta>(): User<\n P,\n U\n> | null;\nfunction useSelf<P extends JsonObject, U extends BaseUserMeta, T>(\n selector: (me: User<P, U>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n): T | null;\nfunction useSelf<P extends JsonObject, U extends BaseUserMeta, T>(\n maybeSelector?: (me: User<P, U>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n): T | User<P, U> | null {\n type Snapshot = User<P, U> | null;\n type Selection = T | null;\n\n const room = useRoom<P, never, U, never, never>();\n const subscribe = room.events.self.subscribe;\n const getSnapshot: () => Snapshot = room.getSelf;\n\n const selector = maybeSelector ?? (identity as (me: User<P, U>) => T);\n const wrappedSelector = React.useCallback(\n (me: Snapshot): Selection => (me !== null ? selector(me) : null),\n [selector]\n );\n\n const getServerSnapshot = alwaysNull;\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n}\n\nfunction useMyPresence<P extends JsonObject>(): [\n P,\n (patch: Partial<P>, options?: { addToHistory: boolean }) => void,\n] {\n const room = useRoom<P, never, never, never, never>();\n const subscribe = room.events.myPresence.subscribe;\n const getSnapshot = room.getPresence;\n const presence = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n const setPresence = room.updatePresence;\n return [presence, setPresence];\n}\n\nfunction useUpdateMyPresence<P extends JsonObject>(): (\n patch: Partial<P>,\n options?: { addToHistory: boolean }\n) => void {\n return useRoom<P, never, never, never, never>().updatePresence;\n}\n\nfunction useOthers<\n P extends JsonObject,\n U extends BaseUserMeta,\n>(): readonly User<P, U>[];\nfunction useOthers<P extends JsonObject, U extends BaseUserMeta, T>(\n selector: (others: readonly User<P, U>[]) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T;\nfunction useOthers<P extends JsonObject, U extends BaseUserMeta, T>(\n selector?: (others: readonly User<P, U>[]) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T | readonly User<P, U>[] {\n const room = useRoom<P, never, U, never, never>();\n const subscribe = room.events.others.subscribe;\n const getSnapshot = room.getOthers;\n const getServerSnapshot = alwaysEmptyList;\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n selector ?? (identity as (others: readonly User<P, U>[]) => T),\n isEqual\n );\n}\n\nfunction useOthersMapped<P extends JsonObject, U extends BaseUserMeta, T>(\n itemSelector: (other: User<P, U>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n): ReadonlyArray<readonly [connectionId: number, data: T]> {\n const wrappedSelector = React.useCallback(\n (others: readonly User<P, U>[]) =>\n others.map((other) => [other.connectionId, itemSelector(other)] as const),\n [itemSelector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (\n a: ReadonlyArray<readonly [connectionId: number, data: T]>,\n b: ReadonlyArray<readonly [connectionId: number, data: T]>\n ): boolean => {\n const eq = itemIsEqual ?? Object.is;\n return (\n a.length === b.length &&\n a.every((atuple, index) => {\n // We know btuple always exist because we checked the array length on the previous line\n const btuple = b[index];\n return atuple[0] === btuple[0] && eq(atuple[1], btuple[1]);\n })\n );\n },\n [itemIsEqual]\n );\n\n return useOthers(wrappedSelector, wrappedIsEqual);\n}\n\n/**\n * Returns an array of connection IDs. This matches the values you'll get by\n * using the `useOthers()` hook.\n *\n * Roughly equivalent to:\n * useOthers((others) => others.map(other => other.connectionId), shallow)\n *\n * This is useful in particular to implement efficiently rendering components\n * for each user in the room, e.g. cursors.\n *\n * @example\n * const ids = useOthersConnectionIds();\n * // [2, 4, 7]\n */\nfunction useOthersConnectionIds(): readonly number[] {\n return useOthers(selectorFor_useOthersConnectionIds, shallow);\n}\n\nconst NOT_FOUND = Symbol();\n\ntype NotFound = typeof NOT_FOUND;\n\nfunction useOther<P extends JsonObject, U extends BaseUserMeta, T>(\n connectionId: number,\n selector: (other: User<P, U>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T {\n const wrappedSelector = React.useCallback(\n (others: readonly User<P, U>[]) => {\n // TODO: Make this O(1) instead of O(n)?\n const other = others.find((other) => other.connectionId === connectionId);\n return other !== undefined ? selector(other) : NOT_FOUND;\n },\n [connectionId, selector]\n );\n\n const wrappedIsEqual = React.useCallback(\n (prev: T | NotFound, curr: T | NotFound): boolean => {\n if (prev === NOT_FOUND || curr === NOT_FOUND) {\n return prev === curr;\n }\n\n const eq = isEqual ?? Object.is;\n return eq(prev, curr);\n },\n [isEqual]\n );\n\n const other = useOthers(wrappedSelector, wrappedIsEqual);\n if (other === NOT_FOUND) {\n throw new Error(\n `No such other user with connection id ${connectionId} exists`\n );\n }\n\n return other;\n}\n\n/** @internal */\nfunction useMutableStorageRoot<S extends LsonObject>(): LiveObject<S> | null {\n const room = useRoom<never, S, never, never, never>();\n const subscribe = room.events.storageDidLoad.subscribeOnce;\n const getSnapshot = room.getStorageSnapshot;\n const getServerSnapshot = alwaysNull;\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n\n// NOTE: This API exists for backward compatible reasons\nfunction useStorageRoot<S extends LsonObject>(): [root: LiveObject<S> | null] {\n return [useMutableStorageRoot<S>()];\n}\n\nfunction useStorage<S extends LsonObject, T>(\n selector: (root: ToImmutable<S>) => T,\n isEqual?: (prev: T | null, curr: T | null) => boolean\n): T | null {\n type Snapshot = ToImmutable<S> | null;\n type Selection = T | null;\n\n const room = useRoom<never, S, never, never, never>();\n const rootOrNull = useMutableStorageRoot<S>();\n\n const wrappedSelector = React.useCallback(\n (rootOrNull: Snapshot): Selection =>\n rootOrNull !== null ? selector(rootOrNull) : null,\n [selector]\n );\n\n const subscribe = React.useCallback(\n (onStoreChange: () => void) =>\n rootOrNull !== null\n ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true })\n : noop,\n [room, rootOrNull]\n );\n\n const getSnapshot = React.useCallback((): Snapshot => {\n if (rootOrNull === null) {\n return null;\n } else {\n const root = rootOrNull;\n const imm = root.toImmutable();\n return imm;\n }\n }, [rootOrNull]);\n\n const getServerSnapshot = alwaysNull;\n\n return useSyncExternalStoreWithSelector(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n wrappedSelector,\n isEqual\n );\n}\n\nfunction useMutation<\n P extends JsonObject,\n S extends LsonObject,\n U extends BaseUserMeta,\n E extends Json,\n M extends BaseMetadata,\n F extends (context: MutationContext<P, S, U>, ...args: any[]) => any,\n>(callback: F, deps: readonly unknown[]): OmitFirstArg<F> {\n const room = useRoom<P, S, U, E, M>();\n return React.useMemo(\n () => {\n return ((...args) =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n room.batch(() =>\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n callback(\n makeMutationContext<P, S, U, E, M>(room),\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n ...args\n )\n )) as OmitFirstArg<F>;\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [room, ...deps]\n );\n}\n\nfunction useThreads<M extends BaseMetadata>(\n options: UseThreadsOptions<M> = {\n query: { metadata: {} },\n }\n): ThreadsState<M> {\n const { scrollOnLoad = true } = options;\n const client = useClient();\n const room = useRoom();\n\n // e.g. 'room-abc-{\"color\":\"red\",\"xyz\":123}'\n const queryKey = React.useMemo(\n () => generateQueryKey(room.id, options.query),\n [room, options]\n );\n\n const { store, getThreadsAndInboxNotifications, incrementQuerySubscribers } =\n getExtrasForClient<M>(client);\n\n React.useEffect(() => {\n void getThreadsAndInboxNotifications(room, queryKey, options);\n return incrementQuerySubscribers(queryKey);\n }, [room, queryKey]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const selector = React.useCallback(\n (state: UmbrellaStoreState<M>): ThreadsState<M> => {\n const query = state.queries[queryKey];\n if (query === undefined || query.isLoading) {\n return {\n isLoading: true,\n };\n }\n\n return {\n threads: selectThreads(state, {\n roomId: room.id,\n query: options.query,\n orderBy: \"age\",\n }),\n isLoading: false,\n error: query.error,\n };\n },\n [room, queryKey] // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const state = useSyncExternalStoreWithSelector(\n store.subscribeThreads,\n store.getThreads,\n store.getThreads,\n selector\n );\n\n useScrollToCommentOnLoadEffect(scrollOnLoad, state);\n\n return state;\n}\n\n/**\n * @private Internal API, do not rely on it.\n */\nfunction useCommentsErrorListener<M extends BaseMetadata>(\n callback: (error: CommentsError<M>) => void\n) {\n const client = useClient();\n const savedCallback = useLatest(callback);\n const { commentsErrorEventSource } = getExtrasForClient<M>(client);\n\n React.useEffect(() => {\n return commentsErrorEventSource.subscribe(savedCallback.current);\n }, [savedCallback, commentsErrorEventSource]);\n}\n\nfunction useCreateThread<M extends BaseMetadata>(): (\n options: CreateThreadOptions<M>\n) => ThreadData<M> {\n const client = useClient();\n const room = useRoom();\n\n return React.useCallback(\n (options: CreateThreadOptions<M>): ThreadData<M> => {\n const body = options.body;\n const metadata = options.metadata ?? ({} as M);\n\n const threadId = createThreadId();\n const commentId = createCommentId();\n const createdAt = new Date();\n\n const newComment: CommentData = {\n id: commentId,\n threadId,\n roomId: room.id,\n createdAt,\n type: \"comment\",\n userId: getCurrentUserId(room),\n body,\n reactions: [],\n };\n const newThread: ThreadData<M> = {\n id: threadId,\n type: \"thread\",\n createdAt,\n updatedAt: createdAt,\n roomId: room.id,\n metadata,\n comments: [newComment],\n resolved: false,\n };\n\n const { store, onMutationFailure } = getExtrasForClient(client);\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"create-thread\",\n thread: newThread,\n roomId: room.id,\n });\n\n room.createThread({ threadId, commentId, body, metadata }).then(\n (thread) => {\n // Replace the optimistic update by the real thing\n store.createThread(optimisticUpdateId, thread);\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (err) =>\n new CreateThreadError(err, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n metadata,\n })\n )\n );\n\n return newThread;\n },\n [client, room]\n );\n}\n\nfunction useDeleteThread(): (threadId: string) => void {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n (threadId: string): void => {\n const { store, onMutationFailure } = getExtrasForClient(client);\n\n const thread = store.getThreads().threadsById[threadId];\n\n const userId = getCurrentUserId(room);\n\n if (thread?.comments?.[0]?.userId !== userId) {\n throw new Error(\"Only the thread creator can delete the thread\");\n }\n\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"delete-thread\",\n roomId: room.id,\n threadId,\n deletedAt: new Date(),\n });\n\n room.deleteThread(threadId).then(\n () => {\n // Replace the optimistic update by the real thing\n store.deleteThread(threadId, optimisticUpdateId);\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (err) => new DeleteThreadError(err, { roomId: room.id, threadId })\n )\n );\n },\n [client, room]\n );\n}\n\nfunction useEditThreadMetadata<M extends BaseMetadata>() {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n (options: EditThreadMetadataOptions<M>): void => {\n if (!options.metadata) {\n return;\n }\n\n const threadId = options.threadId;\n const metadata = options.metadata;\n const updatedAt = new Date();\n\n const { store, onMutationFailure } = getExtrasForClient(client);\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"edit-thread-metadata\",\n metadata,\n threadId,\n updatedAt,\n });\n\n room.editThreadMetadata({ threadId, metadata }).then(\n (metadata) =>\n // Replace the optimistic update by the real thing\n store.patchThread(\n threadId,\n optimisticUpdateId,\n { metadata },\n updatedAt\n ),\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new EditThreadMetadataError(error, {\n roomId: room.id,\n threadId,\n metadata,\n })\n )\n );\n },\n [client, room]\n );\n}\n\n/**\n * Returns a function that adds a comment to a thread.\n *\n * @example\n * const createComment = useCreateComment();\n * createComment({ threadId: \"th_xxx\", body: {} });\n */\nfunction useCreateComment(): (options: CreateCommentOptions) => CommentData {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n ({ threadId, body }: CreateCommentOptions): CommentData => {\n const commentId = createCommentId();\n const createdAt = new Date();\n\n const comment: CommentData = {\n id: commentId,\n threadId,\n roomId: room.id,\n type: \"comment\",\n createdAt,\n userId: getCurrentUserId(room),\n body,\n reactions: [],\n };\n\n const { store, onMutationFailure } = getExtrasForClient(client);\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"create-comment\",\n comment,\n });\n\n room.createComment({ threadId, commentId, body }).then(\n (newComment) => {\n // Replace the optimistic update by the real thing\n store.createComment(newComment, optimisticUpdateId);\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (err) =>\n new CreateCommentError(err, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n );\n\n return comment;\n },\n [client, room]\n );\n}\n\n/**\n * Returns a function that edits a comment's body.\n *\n * @example\n * const editComment = useEditComment()\n * editComment({ threadId: \"th_xxx\", commentId: \"cm_xxx\", body: {} })\n */\nfunction useEditComment(): (options: EditCommentOptions) => void {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n ({ threadId, commentId, body }: EditCommentOptions): void => {\n const editedAt = new Date();\n\n const { store, onMutationFailure } = getExtrasForClient(client);\n const thread = store.getThreads().threadsById[threadId];\n if (thread === undefined) {\n console.warn(\n `Internal unexpected behavior. Cannot edit comment in thread \"${threadId}\" because the thread does not exist in the cache.`\n );\n return;\n }\n\n const comment = thread.comments.find(\n (comment) => comment.id === commentId\n );\n\n if (comment === undefined || comment.deletedAt !== undefined) {\n console.warn(\n `Internal unexpected behavior. Cannot edit comment \"${commentId}\" in thread \"${threadId}\" because the comment does not exist in the cache.`\n );\n return;\n }\n\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"edit-comment\",\n comment: {\n ...comment,\n editedAt,\n body,\n },\n });\n\n room.editComment({ threadId, commentId, body }).then(\n (editedComment) => {\n // Replace the optimistic update by the real thing\n store.editComment(threadId, optimisticUpdateId, editedComment);\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new EditCommentError(error, {\n roomId: room.id,\n threadId,\n commentId,\n body,\n })\n )\n );\n },\n [client, room]\n );\n}\n\n/**\n * Returns a function that deletes a comment.\n * If it is the last non-deleted comment, the thread also gets deleted.\n *\n * @example\n * const deleteComment = useDeleteComment();\n * deleteComment({ threadId: \"th_xxx\", commentId: \"cm_xxx\" })\n */\nfunction useDeleteComment() {\n const client = useClient();\n const room = useRoom();\n\n return React.useCallback(\n ({ threadId, commentId }: DeleteCommentOptions): void => {\n const deletedAt = new Date();\n\n const { store, onMutationFailure } = getExtrasForClient(client);\n\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"delete-comment\",\n threadId,\n commentId,\n deletedAt,\n roomId: room.id,\n });\n\n room.deleteComment({ threadId, commentId }).then(\n () => {\n // Replace the optimistic update by the real thing\n store.deleteComment(\n threadId,\n optimisticUpdateId,\n commentId,\n deletedAt\n );\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new DeleteCommentError(error, {\n roomId: room.id,\n threadId,\n commentId,\n })\n )\n );\n },\n [client, room]\n );\n}\n\nfunction useAddReaction<M extends BaseMetadata>() {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n ({ threadId, commentId, emoji }: CommentReactionOptions): void => {\n const createdAt = new Date();\n const userId = getCurrentUserId(room);\n\n const { store, onMutationFailure } = getExtrasForClient<M>(client);\n\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"add-reaction\",\n threadId,\n commentId,\n reaction: {\n emoji,\n userId,\n createdAt,\n },\n });\n\n room.addReaction({ threadId, commentId, emoji }).then(\n (addedReaction) => {\n // Replace the optimistic update by the real thing\n store.addReaction(\n threadId,\n optimisticUpdateId,\n commentId,\n addedReaction,\n createdAt\n );\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new AddReactionError(error, {\n roomId: room.id,\n threadId,\n commentId,\n emoji,\n })\n )\n );\n },\n [client, room]\n );\n}\n\n/**\n * Returns a function that removes a reaction on a comment.\n *\n * @example\n * const removeReaction = useRemoveReaction();\n * removeReaction({ threadId: \"th_xxx\", commentId: \"cm_xxx\", emoji: \"👍\" })\n */\nfunction useRemoveReaction() {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n ({ threadId, commentId, emoji }: CommentReactionOptions): void => {\n const userId = getCurrentUserId(room);\n\n const removedAt = new Date();\n\n const { store, onMutationFailure } = getExtrasForClient(client);\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"remove-reaction\",\n threadId,\n commentId,\n emoji,\n userId,\n removedAt,\n });\n\n room.removeReaction({ threadId, commentId, emoji }).then(\n () => {\n // Replace the optimistic update by the real thing\n store.removeReaction(\n threadId,\n optimisticUpdateId,\n commentId,\n emoji,\n userId,\n removedAt\n );\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new RemoveReactionError(error, {\n roomId: room.id,\n threadId,\n commentId,\n emoji,\n })\n )\n );\n },\n [client, room]\n );\n}\n\n/**\n * Returns a function that marks a thread as read.\n *\n * @example\n * const markThreadAsRead = useMarkThreadAsRead();\n * markThreadAsRead(\"th_xxx\");\n */\nfunction useMarkThreadAsRead() {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n (threadId: string) => {\n const { store, onMutationFailure } = getExtrasForClient(client);\n const inboxNotification = Object.values(\n store.getInboxNotifications().inboxNotificationsById\n ).find(\n (inboxNotification) =>\n inboxNotification.kind === \"thread\" &&\n inboxNotification.threadId === threadId\n );\n\n if (!inboxNotification) return;\n\n const now = new Date();\n\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"mark-inbox-notification-as-read\",\n inboxNotificationId: inboxNotification.id,\n readAt: now,\n });\n\n room.markInboxNotificationAsRead(inboxNotification.id).then(\n () => {\n // Replace the optimistic update by the real thing\n store.updateInboxNotification(\n inboxNotification.id,\n optimisticUpdateId,\n (inboxNotification) => ({ ...inboxNotification, readAt: now })\n );\n },\n (err: Error) => {\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new MarkInboxNotificationAsReadError(error, {\n inboxNotificationId: inboxNotification.id,\n })\n );\n return;\n }\n );\n },\n [client, room]\n );\n}\n\n/**\n * Returns a function that marks a thread as resolved.\n *\n * @example\n * const markThreadAsResolved = useMarkThreadAsResolved();\n * markThreadAsResolved(\"th_xxx\");\n */\nfunction useMarkThreadAsResolved() {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n (threadId: string) => {\n const updatedAt = new Date();\n\n const { store, onMutationFailure } = getExtrasForClient(client);\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"mark-thread-as-resolved\",\n threadId,\n updatedAt,\n });\n\n room.markThreadAsResolved(threadId).then(\n () => {\n // Replace the optimistic update by the real thing\n store.patchThread(\n threadId,\n optimisticUpdateId,\n { resolved: true },\n updatedAt\n );\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new MarkThreadAsResolvedError(error, {\n roomId: room.id,\n threadId,\n })\n )\n );\n },\n [client, room]\n );\n}\n\n/**\n * Returns a function that marks a thread as unresolved.\n *\n * @example\n * const markThreadAsUnresolved = useMarkThreadAsUnresolved();\n * markThreadAsUnresolved(\"th_xxx\");\n */\nfunction useMarkThreadAsUnresolved() {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n (threadId: string) => {\n const updatedAt = new Date();\n\n const { store, onMutationFailure } = getExtrasForClient(client);\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"mark-thread-as-unresolved\",\n threadId,\n updatedAt,\n });\n\n room.markThreadAsUnresolved(threadId).then(\n () => {\n // Replace the optimistic update by the real thing\n store.patchThread(\n threadId,\n optimisticUpdateId,\n { resolved: false },\n updatedAt\n );\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new MarkThreadAsUnresolvedError(error, {\n roomId: room.id,\n threadId,\n })\n )\n );\n },\n [client, room]\n );\n}\n\n/**\n * Returns the subscription status of a thread.\n *\n * @example\n * const { status, unreadSince } = useThreadSubscription(\"th_xxx\");\n */\nfunction useThreadSubscription(threadId: string): ThreadSubscription {\n const client = useClient();\n const { store } = getExtrasForClient(client);\n\n const selector = React.useCallback(\n (state: UmbrellaStoreState<BaseMetadata>): ThreadSubscription => {\n const inboxNotification = state.inboxNotifications.find(\n (inboxNotification) =>\n inboxNotification.kind === \"thread\" &&\n inboxNotification.threadId === threadId\n );\n\n const thread = state.threadsById[threadId];\n\n if (inboxNotification === undefined || thread === undefined) {\n return {\n status: \"not-subscribed\",\n };\n }\n\n return {\n status: \"subscribed\",\n unreadSince: inboxNotification.readAt,\n };\n },\n [threadId]\n );\n\n return useSyncExternalStoreWithSelector(\n store.subscribeThreads,\n store.getThreads,\n store.getThreads,\n selector\n );\n}\n\n/**\n * Returns the user's notification settings for the current room\n * and a function to update them.\n *\n * @example\n * const [{ settings }, updateSettings] = useRoomNotificationSettings();\n */\nfunction useRoomNotificationSettings(): [\n RoomNotificationSettingsState,\n (settings: Partial<RoomNotificationSettings>) => void,\n] {\n const client = useClient();\n const room = useRoom();\n const { store } = getExtrasForClient(client);\n\n React.useEffect(() => {\n const { getInboxNotificationSettings } = getExtrasForClient(client);\n const queryKey = makeNotificationSettingsQueryKey(room.id);\n void getInboxNotificationSettings(room, queryKey);\n }, [client, room]);\n\n const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();\n\n const selector = React.useCallback(\n (state: GetThreadsType): RoomNotificationSettingsState => {\n const query = state.queries[makeNotificationSettingsQueryKey(room.id)];\n\n if (query === undefined || query.isLoading) {\n return { isLoading: true };\n }\n\n if (query.error !== undefined) {\n return { isLoading: false, error: query.error };\n }\n\n return {\n isLoading: false,\n settings: selectNotificationSettings(room.id, state),\n };\n },\n [room]\n );\n\n const settings = useSyncExternalStoreWithSelector(\n store.subscribeNotificationSettings,\n store.getThreads,\n store.getThreads,\n selector\n );\n\n return React.useMemo(() => {\n return [settings, updateRoomNotificationSettings];\n }, [settings, updateRoomNotificationSettings]);\n}\n\n/**\n * Returns the version data bianry for a given version\n *\n * @example\n * const {data} = useHistoryVersionData(versionId);\n */\nfunction useHistoryVersionData(versionId: string): HistoryVersionDataState {\n const [state, setState] = React.useState<HistoryVersionDataState>({\n isLoading: true,\n });\n const room = useRoom();\n React.useEffect(() => {\n setState({ isLoading: true });\n const load = async () => {\n try {\n const response = await room[kInternal].getTextVersion(versionId);\n const buffer = await response.arrayBuffer();\n const data = new Uint8Array(buffer);\n setState({\n isLoading: false,\n data,\n });\n } catch (error) {\n setState({\n isLoading: false,\n error:\n error instanceof Error\n ? error\n : new Error(\n \"An unknown error occurred while loading this version\"\n ),\n });\n }\n };\n void load();\n }, [room, versionId]);\n return state;\n}\n\n/**\n * (Private beta) Returns a history of versions of the current room.\n *\n * @example\n * const { versions, error, isLoading } = useHistoryVersions();\n */\nfunction useHistoryVersions(): HistoryVersionsState {\n const client = useClient();\n const room = useRoom();\n const queryKey = getVersionsQueryKey(room.id);\n\n const { store, getRoomVersions } = getExtrasForClient(client);\n\n React.useEffect(() => {\n void getRoomVersions(room);\n }, [room]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const selector = React.useCallback(\n (state: ReturnType<typeof store.getVersions>): HistoryVersionsState => {\n const query = state.queries[queryKey];\n if (query === undefined || query.isLoading) {\n return {\n isLoading: true,\n };\n }\n\n return {\n versions: state.versionsByRoomId[room.id],\n isLoading: false,\n error: query.error,\n };\n },\n [room, queryKey] // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const state = useSyncExternalStoreWithSelector(\n store.subscribeVersions,\n store.getVersions,\n store.getVersions,\n selector\n );\n\n return state;\n}\n\n/**\n * Returns a function that updates the user's notification settings\n * for the current room.\n *\n * @example\n * const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();\n * updateRoomNotificationSettings({ threads: \"all\" });\n */\nfunction useUpdateRoomNotificationSettings() {\n const client = useClient();\n const room = useRoom();\n return React.useCallback(\n (settings: Partial<RoomNotificationSettings>) => {\n const { store, onMutationFailure } = getExtrasForClient(client);\n const optimisticUpdateId = store.addOptimisticUpdate({\n type: \"update-notification-settings\",\n roomId: room.id,\n settings,\n });\n\n room.updateNotificationSettings(settings).then(\n (settings) => {\n // Replace the optimistic update by the real thing\n store.updateRoomInboxNotificationSettings2(\n room.id,\n optimisticUpdateId,\n settings\n );\n },\n (err: Error) =>\n onMutationFailure(\n err,\n optimisticUpdateId,\n (error) =>\n new UpdateNotificationSettingsError(error, {\n roomId: room.id,\n })\n )\n );\n },\n [client, room]\n );\n}\n\nfunction ensureNotServerSide(): void {\n // Error early if suspense is used in a server-side context\n if (typeof window === \"undefined\") {\n throw new Error(\n \"You cannot use the Suspense version of this hook on the server side. Make sure to only call them on the client side.\\nFor tips, see https://liveblocks.io/docs/api-reference/liveblocks-react#suspense-avoid-ssr\"\n );\n }\n}\n\nfunction useSuspendUntilPresenceReady(): void {\n // Throw an error if we're calling this on the server side\n ensureNotServerSide();\n\n const room = useRoom();\n use(room.waitUntilPresenceReady());\n}\n\nfunction useSelfSuspense<P extends JsonObject, U extends BaseUserMeta>(): User<\n P,\n U\n>;\nfunction useSelfSuspense<P extends JsonObject, U extends BaseUserMeta, T>(\n selector: (me: User<P, U>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T;\nfunction useSelfSuspense<P extends JsonObject, U extends BaseUserMeta, T>(\n selector?: (me: User<P, U>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T | User<P, U> {\n useSuspendUntilPresenceReady();\n return useSelf(\n selector as (me: User<P, U>) => T,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T | User<P, U>;\n}\n\nfunction useOthersSuspense<\n P extends JsonObject,\n U extends BaseUserMeta,\n>(): readonly User<P, U>[];\nfunction useOthersSuspense<P extends JsonObject, U extends BaseUserMeta, T>(\n selector: (others: readonly User<P, U>[]) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T;\nfunction useOthersSuspense<P extends JsonObject, U extends BaseUserMeta, T>(\n selector?: (others: readonly User<P, U>[]) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T | readonly User<P, U>[] {\n useSuspendUntilPresenceReady();\n return useOthers(\n selector as (others: readonly User<P, U>[]) => T,\n isEqual as (prev: T, curr: T) => boolean\n ) as T | readonly User<P, U>[];\n}\n\n/**\n * Returns an array of connection IDs. This matches the values you'll get by\n * using the `useOthers()` hook.\n *\n * Roughly equivalent to:\n * useOthers((others) => others.map(other => other.connectionId), shallow)\n *\n * This is useful in particular to implement efficiently rendering components\n * for each user in the room, e.g. cursors.\n *\n * @example\n * const ids = useOthersConnectionIds();\n * // [2, 4, 7]\n */\nfunction useOthersConnectionIdsSuspense(): readonly number[] {\n useSuspendUntilPresenceReady();\n return useOthersConnectionIds();\n}\n\nfunction useOthersMappedSuspense<\n P extends JsonObject,\n U extends BaseUserMeta,\n T,\n>(\n itemSelector: (other: User<P, U>) => T,\n itemIsEqual?: (prev: T, curr: T) => boolean\n): ReadonlyArray<readonly [connectionId: number, data: T]> {\n useSuspendUntilPresenceReady();\n return useOthersMapped(itemSelector, itemIsEqual);\n}\n\nfunction useOtherSuspense<P extends JsonObject, U extends BaseUserMeta, T>(\n connectionId: number,\n selector: (other: User<P, U>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T {\n useSuspendUntilPresenceReady();\n return useOther(connectionId, selector, isEqual);\n}\n\nfunction useSuspendUntilStorageReady(): void {\n // Throw an error if we're calling this on the server side\n ensureNotServerSide();\n\n const room = useRoom();\n use(room.waitUntilStorageReady());\n}\n\nfunction useStorageSuspense<S extends LsonObject, T>(\n selector: (root: ToImmutable<S>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T {\n useSuspendUntilStorageReady();\n return useStorage(\n selector,\n isEqual as (prev: T | null, curr: T | null) => boolean\n ) as T;\n}\n\n/**\n * Returns the current storage status for the Room, and triggers\n * a re-render whenever it changes. Can be used to render a \"Saving...\"\n * indicator.\n */\nfunction useStorageStatusSuspense(\n options?: UseStorageStatusOptions\n): StorageStatusSuccess {\n useSuspendUntilStorageReady();\n return useStorageStatus(options) as StorageStatusSuccess;\n}\n\nfunction useThreadsSuspense<M extends BaseMetadata>(\n options: UseThreadsOptions<M> = {\n query: { metadata: {} },\n }\n): ThreadsStateSuccess<M> {\n const { scrollOnLoad = true } = options;\n\n const client = useClient();\n const room = useRoom();\n const queryKey = React.useMemo(\n () => generateQueryKey(room.id, options.query),\n [room, options]\n );\n\n const { store, getThreadsAndInboxNotifications } =\n getExtrasForClient<M>(client);\n\n const query = store.getThreads().queries[queryKey];\n\n if (query === undefined || query.isLoading) {\n throw getThreadsAndInboxNotifications(room, queryKey, options);\n }\n\n if (query.error) {\n throw query.error;\n }\n\n const selector = React.useCallback(\n (state: ReturnType<typeof store.getThreads>): ThreadsStateSuccess<M> => {\n return {\n threads: selectThreads(state, {\n roomId: room.id,\n query: options.query,\n orderBy: \"age\",\n }),\n isLoading: false,\n };\n },\n [room, queryKey] // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n React.useEffect(() => {\n const { incrementQuerySubscribers } = getExtrasForClient(client);\n return incrementQuerySubscribers(queryKey);\n }, [client, queryKey]);\n\n const state = useSyncExternalStoreWithSelector(\n store.subscribeThreads,\n store.getThreads,\n store.getThreads,\n selector\n );\n\n useScrollToCommentOnLoadEffect(scrollOnLoad, state);\n\n return state;\n}\n\n/**\n * (Private beta) Returns a history of versions of the current room.\n *\n * @example\n * const { versions } = useHistoryVersions();\n */\nfunction useHistoryVersionsSuspense(): HistoryVersionsStateResolved {\n const client = useClient();\n const room = useRoom();\n const queryKey = getVersionsQueryKey(room.id);\n\n const { store, getRoomVersions } = getExtrasForClient(client);\n\n const query = store.getVersions().queries[queryKey];\n\n if (query === undefined || query.isLoading) {\n throw getRoomVersions(room);\n }\n\n if (query.error) {\n throw query.error;\n }\n\n const selector = React.useCallback(\n (state: UmbrellaStoreState<BaseMetadata>): HistoryVersionsStateResolved => {\n return {\n versions: state.versionsByRoomId[room.id],\n isLoading: false,\n };\n },\n [room, queryKey] // eslint-disable-line react-hooks/exhaustive-deps\n );\n\n const state = useSyncExternalStoreWithSelector(\n store.subscribeVersions,\n store.getVersions,\n store.getVersions,\n selector\n );\n\n return state;\n}\n\n/**\n * Returns the user's notification settings for the current room\n * and a function to update them.\n *\n * @example\n * const [{ settings }, updateSettings] = useRoomNotificationSettings();\n */\nfunction useRoomNotificationSettingsSuspense(): [\n RoomNotificationSettingsStateSuccess,\n (settings: Partial<RoomNotificationSettings>) => void,\n] {\n const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();\n const client = useClient();\n const room = useRoom();\n const queryKey = makeNotificationSettingsQueryKey(room.id);\n\n const { store, getInboxNotificationSettings } = getExtrasForClient(client);\n const query = store.getNotificationSettings().queries[queryKey];\n\n if (query === undefined || query.isLoading) {\n throw getInboxNotificationSettings(room, queryKey);\n }\n\n if (query.error) {\n throw query.error;\n }\n\n const selector = React.useCallback(\n (\n state: GetNotificationSettingsType\n ): RoomNotificationSettingsStateSuccess => {\n return {\n isLoading: false,\n settings: selectNotificationSettings(room.id, state),\n };\n },\n [room]\n );\n\n const settings = useSyncExternalStoreWithSelector(\n store.subscribeNotificationSettings,\n store.getNotificationSettings,\n store.getNotificationSettings,\n selector\n );\n\n return React.useMemo(() => {\n return [settings, updateRoomNotificationSettings];\n }, [settings, updateRoomNotificationSettings]);\n}\n\n/**\n * @private\n *\n * This is an internal API, use `createRoomContext` instead.\n */\nexport function useRoomContextBundleOrNull() {\n const client = useClientOrNull();\n const room = useRoomOrNull<never, never, never, never, never>();\n return client && room ? getOrCreateRoomContextBundle(client) : null;\n}\n\n/**\n * @private\n *\n * This is an internal API, use `createRoomContext` instead.\n */\nexport function useRoomContextBundle() {\n const client = useClient();\n return getOrCreateRoomContextBundle(client);\n}\n\n/**\n * Creates a RoomProvider and a set of typed hooks to use in your app. Note\n * that any RoomProvider created in this way does not need to be nested in\n * LiveblocksProvider, as it already has access to the client.\n */\nexport function createRoomContext<\n P extends JsonObject = DP,\n S extends LsonObject = DS,\n U extends BaseUserMeta = DU,\n E extends Json = DE,\n M extends BaseMetadata = DM,\n>(client: OpaqueClient): RoomContextBundle<P, S, U, E, M> {\n return getOrCreateRoomContextBundle<P, S, U, E, M>(client);\n}\n\n/**\n * Example:\n * generateQueryKey('room-abc', { xyz: 123, abc: \"red\" })\n * → 'room-abc-{\"color\":\"red\",\"xyz\":123}'\n */\nexport function generateQueryKey(\n roomId: string,\n options: UseThreadsOptions<BaseMetadata>[\"query\"]\n) {\n return `${roomId}-${stringify(options ?? {})}`;\n}\n\nexport function getVersionsQueryKey(roomId: string) {\n return `${roomId}-VERSIONS`;\n}\n\ntype TypedBundle = RoomContextBundle<DP, DS, DU, DE, DM>;\n\n/**\n * Makes a Room available in the component hierarchy below.\n * Joins the room when the component is mounted, and automatically leaves\n * the room when the component is unmounted.\n */\nconst _RoomProvider: TypedBundle[\"RoomProvider\"] = RoomProvider;\n\n/**\n * Returns a callback that lets you broadcast custom events to other users in the room\n *\n * @example\n * const broadcast = useBroadcastEvent();\n *\n * broadcast({ type: \"CUSTOM_EVENT\", data: { x: 0, y: 0 } });\n */\nconst _useBroadcastEvent: TypedBundle[\"useBroadcastEvent\"] = useBroadcastEvent;\n\n/**\n * Get informed when users enter or leave the room, as an event.\n *\n * @example\n * useOthersListener({ type, user, others }) => {\n * if (type === 'enter') {\n * // `user` has joined the room\n * } else if (type === 'leave') {\n * // `user` has left the room\n * }\n * })\n */\nconst _useOthersListener: TypedBundle[\"useOthersListener\"] = useOthersListener;\n\n/**\n * Returns the Room of the nearest RoomProvider above in the React component\n * tree.\n */\nconst _useRoom: TypedBundle[\"useRoom\"] = useRoom;\n\n/**\n * Returns whether the hook is called within a RoomProvider context.\n *\n * @example\n * const isInsideRoom = useIsInsideRoom();\n */\nconst _useIsInsideRoom: TypedBundle[\"useIsInsideRoom\"] = useIsInsideRoom;\n\n/**\n * Returns a function that adds a reaction from a comment.\n *\n * @example\n * const addReaction = useAddReaction();\n * addReaction({ threadId: \"th_xxx\", commentId: \"cm_xxx\", emoji: \"👍\" })\n */\nconst _useAddReaction: TypedBundle[\"useAddReaction\"] = useAddReaction;\n\n/**\n * Create a callback function that lets you mutate Liveblocks state.\n *\n * The first argument that gets passed into your callback will be\n * a \"mutation context\", which exposes the following:\n *\n * - `storage` - The mutable Storage root.\n * You can mutate any Live structures with this, for example:\n * `storage.get('layers').get('layer1').set('fill', 'red')`\n *\n * - `setMyPresence` - Call this with a new (partial) Presence value.\n *\n * - `self` - A read-only version of the latest self, if you need it to\n * compute the next state.\n *\n * - `others` - A read-only version of the latest others list, if you\n * need it to compute the next state.\n *\n * useMutation is like React's useCallback, except that the first argument\n * that gets passed into your callback will be a \"mutation context\".\n *\n * If you want get access to the immutable root somewhere in your mutation,\n * you can use `storage.ToImmutable()`.\n *\n * @example\n * const fillLayers = useMutation(\n * ({ storage }, color: Color) => {\n * ...\n * },\n * [],\n * );\n *\n * fillLayers('red');\n *\n * const deleteLayers = useMutation(\n * ({ storage }) => {\n * ...\n * },\n * [],\n * );\n *\n * deleteLayers();\n */\nconst _useMutation: TypedBundle[\"useMutation\"] = useMutation;\n\n/**\n * Returns a function that creates a thread with an initial comment, and optionally some metadata.\n *\n * @example\n * const createThread = useCreateThread();\n * createThread({ body: {}, metadata: {} });\n */\nconst _useCreateThread: TypedBundle[\"useCreateThread\"] = useCreateThread;\n\n/**\n * Returns a function that deletes a thread and its associated comments.\n * Only the thread creator can delete a thread, it will throw otherwise.\n *\n * @example\n * const deleteThread = useDeleteThread();\n * deleteThread(\"th_xxx\");\n */\nconst _useDeleteThread: TypedBundle[\"useDeleteThread\"] = useDeleteThread;\n\n/**\n * Returns a function that edits a thread's metadata.\n * To delete an existing metadata property, set its value to `null`.\n *\n * @example\n * const editThreadMetadata = useEditThreadMetadata();\n * editThreadMetadata({ threadId: \"th_xxx\", metadata: {} })\n */\nconst _useEditThreadMetadata: TypedBundle[\"useEditThreadMetadata\"] =\n useEditThreadMetadata;\n\n/**\n * useEventListener is a React hook that allows you to respond to events broadcast\n * by other users in the room.\n *\n * The `user` argument will indicate which `User` instance sent the message.\n * This will be equal to one of the others in the room, but it can be `null`\n * in case this event was broadcasted from the server.\n *\n * @example\n * useEventListener(({ event, user, connectionId }) => {\n * // ^^^^ Will be Client A\n * if (event.type === \"CUSTOM_EVENT\") {\n * // Do something\n * }\n * });\n */\nconst _useEventListener: TypedBundle[\"useEventListener\"] = useEventListener;\n\n/**\n * Returns the presence of the current user of the current room, and a function to update it.\n * It is different from the setState function returned by the useState hook from React.\n * You don't need to pass the full presence object to update it.\n *\n * @example\n * const [myPresence, updateMyPresence] = useMyPresence();\n * updateMyPresence({ x: 0 });\n * updateMyPresence({ y: 0 });\n *\n * // At the next render, \"myPresence\" will be equal to \"{ x: 0, y: 0 }\"\n */\nconst _useMyPresence: TypedBundle[\"useMyPresence\"] = useMyPresence;\n\n/**\n * Related to useOthers(), but optimized for selecting only \"subsets\" of\n * others. This is useful for performance reasons in particular, because\n * selecting only a subset of users also means limiting the number of\n * re-renders that will be triggered.\n *\n * @example\n * const avatars = useOthersMapped(user => user.info.avatar);\n * // ^^^^^^^\n * // { connectionId: number; data: string }[]\n *\n * The selector function you pass to useOthersMapped() is called an \"item\n * selector\", and operates on a single user at a time. If you provide an\n * (optional) \"item comparison\" function, it will be used to compare each\n * item pairwise.\n *\n * For example, to select multiple properties:\n *\n * @example\n * const avatarsAndCursors = useOthersMapped(\n * user => [u.info.avatar, u.presence.cursor],\n * shallow, // 👈\n * );\n */\nconst _useOthersMapped: TypedBundle[\"useOthersMapped\"] = useOthersMapped;\n\n/**\n * Related to useOthers(), but optimized for selecting only \"subsets\" of\n * others. This is useful for performance reasons in particular, because\n * selecting only a subset of users also means limiting the number of\n * re-renders that will be triggered.\n *\n * @example\n * const avatars = useOthersMapped(user => user.info.avatar);\n * // ^^^^^^^\n * // { connectionId: number; data: string }[]\n *\n * The selector function you pass to useOthersMapped() is called an \"item\n * selector\", and operates on a single user at a time. If you provide an\n * (optional) \"item comparison\" function, it will be used to compare each\n * item pairwise.\n *\n * For example, to select multiple properties:\n *\n * @example\n * const avatarsAndCursors = useOthersMapped(\n * user => [u.info.avatar, u.presence.cursor],\n * shallow, // 👈\n * );\n */\nconst _useOthersMappedSuspense: TypedBundle[\"suspense\"][\"useOthersMapped\"] =\n useOthersMappedSuspense;\n\n/**\n * Returns the threads within the current room.\n *\n * @example\n * const { threads, error, isLoading } = useThreads();\n */\nconst _useThreads: TypedBundle[\"useThreads\"] = useThreads;\n\n/**\n * Returns the threads within the current room.\n *\n * @example\n * const { threads } = useThreads();\n */\nconst _useThreadsSuspense: TypedBundle[\"suspense\"][\"useThreads\"] =\n useThreadsSuspense;\n\n/**\n * (Private beta) Returns a history of versions of the current room.\n *\n * @example\n * const { versions, error, isLoading } = useHistoryVersions();\n */\nconst _useHistoryVersions: TypedBundle[\"useHistoryVersions\"] =\n useHistoryVersions;\n\n/**\n * (Private beta) Returns a history of versions of the current room.\n *\n * @example\n * const { versions } = useHistoryVersions();\n */\nconst _useHistoryVersionsSuspense: TypedBundle[\"suspense\"][\"useHistoryVersions\"] =\n useHistoryVersionsSuspense;\n\n/**\n * Given a connection ID (as obtained by using `useOthersConnectionIds`), you\n * can call this selector deep down in your component stack to only have the\n * component re-render if properties for this particular user change.\n *\n * @example\n * // Returns only the selected values re-renders whenever that selection changes)\n * const { x, y } = useOther(2, user => user.presence.cursor);\n */\nconst _useOther: TypedBundle[\"useOther\"] = useOther;\n\n/**\n * Returns an array with information about all the users currently connected in\n * the room (except yourself).\n *\n * @example\n * const others = useOthers();\n *\n * // Example to map all cursors in JSX\n * return (\n * <>\n * {others.map((user) => {\n * if (user.presence.cursor == null) {\n * return null;\n * }\n * return <Cursor key={user.connectionId} cursor={user.presence.cursor} />\n * })}\n * </>\n * )\n */\nfunction _useOthers(): readonly User<DP, DU>[];\n/**\n * Extract arbitrary data based on all the users currently connected in the\n * room (except yourself).\n *\n * The selector function will get re-evaluated any time a user enters or\n * leaves the room, as well as whenever their presence data changes.\n *\n * The component that uses this hook will automatically re-render if your\n * selector function returns a different value from its previous run.\n *\n * By default `useOthers()` uses strict `===` to check for equality. Take\n * extra care when returning a computed object or list, for example when you\n * return the result of a .map() or .filter() call from the selector. In\n * those cases, you'll probably want to use a `shallow` comparison check.\n *\n * @example\n * const avatars = useOthers(users => users.map(u => u.info.avatar), shallow);\n * const cursors = useOthers(users => users.map(u => u.presence.cursor), shallow);\n * const someoneIsTyping = useOthers(users => users.some(u => u.presence.isTyping));\n *\n */\nfunction _useOthers<T>(\n selector: (others: readonly User<DP, DU>[]) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T;\nfunction _useOthers(...args: any[]) {\n return useOthers(...(args as []));\n}\n\n/**\n * Given a connection ID (as obtained by using `useOthersConnectionIds`), you\n * can call this selector deep down in your component stack to only have the\n * component re-render if properties for this particular user change.\n *\n * @example\n * // Returns only the selected values re-renders whenever that selection changes)\n * const { x, y } = useOther(2, user => user.presence.cursor);\n */\nconst _useOtherSuspense: TypedBundle[\"suspense\"][\"useOther\"] = useOtherSuspense;\n\n/**\n * Returns an array with information about all the users currently connected in\n * the room (except yourself).\n *\n * @example\n * const others = useOthers();\n *\n * // Example to map all cursors in JSX\n * return (\n * <>\n * {others.map((user) => {\n * if (user.presence.cursor == null) {\n * return null;\n * }\n * return <Cursor key={user.connectionId} cursor={user.presence.cursor} />\n * })}\n * </>\n * )\n */\nfunction _useOthersSuspense(): readonly User<DP, DU>[];\n/**\n * Extract arbitrary data based on all the users currently connected in the\n * room (except yourself).\n *\n * The selector function will get re-evaluated any time a user enters or\n * leaves the room, as well as whenever their presence data changes.\n *\n * The component that uses this hook will automatically re-render if your\n * selector function returns a different value from its previous run.\n *\n * By default `useOthers()` uses strict `===` to check for equality. Take\n * extra care when returning a computed object or list, for example when you\n * return the result of a .map() or .filter() call from the selector. In\n * those cases, you'll probably want to use a `shallow` comparison check.\n *\n * @example\n * const avatars = useOthers(users => users.map(u => u.info.avatar), shallow);\n * const cursors = useOthers(users => users.map(u => u.presence.cursor), shallow);\n * const someoneIsTyping = useOthers(users => users.some(u => u.presence.isTyping));\n *\n */\nfunction _useOthersSuspense<T>(\n selector: (others: readonly User<DP, DU>[]) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T;\nfunction _useOthersSuspense(...args: any[]) {\n return useOthersSuspense(...(args as []));\n}\n\n/**\n * Extract arbitrary data from the Liveblocks Storage state, using an\n * arbitrary selector function.\n *\n * The selector function will get re-evaluated any time something changes in\n * Storage. The value returned by your selector function will also be the\n * value returned by the hook.\n *\n * The `root` value that gets passed to your selector function is\n * a immutable/readonly version of your Liveblocks storage root.\n *\n * The component that uses this hook will automatically re-render if the\n * returned value changes.\n *\n * By default `useStorage()` uses strict `===` to check for equality. Take\n * extra care when returning a computed object or list, for example when you\n * return the result of a .map() or .filter() call from the selector. In\n * those cases, you'll probably want to use a `shallow` comparison check.\n */\nconst _useStorage: TypedBundle[\"useStorage\"] = useStorage;\n\n/**\n * Extract arbitrary data from the Liveblocks Storage state, using an\n * arbitrary selector function.\n *\n * The selector function will get re-evaluated any time something changes in\n * Storage. The value returned by your selector function will also be the\n * value returned by the hook.\n *\n * The `root` value that gets passed to your selector function is\n * a immutable/readonly version of your Liveblocks storage root.\n *\n * The component that uses this hook will automatically re-render if the\n * returned value changes.\n *\n * By default `useStorage()` uses strict `===` to check for equality. Take\n * extra care when returning a computed object or list, for example when you\n * return the result of a .map() or .filter() call from the selector. In\n * those cases, you'll probably want to use a `shallow` comparison check.\n */\nconst _useStorageSuspense: TypedBundle[\"suspense\"][\"useStorage\"] =\n useStorageSuspense;\n\n/**\n * Gets the current user once it is connected to the room.\n *\n * @example\n * const me = useSelf();\n * if (me !== null) {\n * const { x, y } = me.presence.cursor;\n * }\n */\nfunction _useSelf(): User<DP, DU> | null;\n/**\n * Extract arbitrary data based on the current user.\n *\n * The selector function will get re-evaluated any time your presence data\n * changes.\n *\n * The component that uses this hook will automatically re-render if your\n * selector function returns a different value from its previous run.\n *\n * By default `useSelf()` uses strict `===` to check for equality. Take extra\n * care when returning a computed object or list, for example when you return\n * the result of a .map() or .filter() call from the selector. In those\n * cases, you'll probably want to use a `shallow` comparison check.\n *\n * Will return `null` while Liveblocks isn't connected to a room yet.\n *\n * @example\n * const cursor = useSelf(me => me.presence.cursor);\n * if (cursor !== null) {\n * const { x, y } = cursor;\n * }\n *\n */\nfunction _useSelf<T>(\n selector: (me: User<DP, DU>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T | null;\nfunction _useSelf(...args: any[]) {\n return useSelf(...(args as []));\n}\n\n/**\n * Gets the current user once it is connected to the room.\n *\n * @example\n * const me = useSelf();\n * const { x, y } = me.presence.cursor;\n */\nfunction _useSelfSuspense(): User<DP, DU>;\n/**\n * Extract arbitrary data based on the current user.\n *\n * The selector function will get re-evaluated any time your presence data\n * changes.\n *\n * The component that uses this hook will automatically re-render if your\n * selector function returns a different value from its previous run.\n *\n * By default `useSelf()` uses strict `===` to check for equality. Take extra\n * care when returning a computed object or list, for example when you return\n * the result of a .map() or .filter() call from the selector. In those\n * cases, you'll probably want to use a `shallow` comparison check.\n *\n * @example\n * const cursor = useSelf(me => me.presence.cursor);\n * const { x, y } = cursor;\n *\n */\nfunction _useSelfSuspense<T>(\n selector: (me: User<DP, DU>) => T,\n isEqual?: (prev: T, curr: T) => boolean\n): T;\nfunction _useSelfSuspense(...args: any[]) {\n return useSelfSuspense(...(args as []));\n}\n\n/**\n * Returns the mutable (!) Storage root. This hook exists for\n * backward-compatible reasons.\n *\n * @example\n * const [root] = useStorageRoot();\n */\nconst _useStorageRoot: TypedBundle[\"useStorageRoot\"] = useStorageRoot;\n\n/**\n * useUpdateMyPresence is similar to useMyPresence but it only returns the function to update the current user presence.\n * If you don't use the current user presence in your component, but you need to update it (e.g. live cursor), it's better to use useUpdateMyPresence to avoid unnecessary renders.\n *\n * @example\n * const updateMyPresence = useUpdateMyPresence();\n * updateMyPresence({ x: 0 });\n * updateMyPresence({ y: 0 });\n *\n * // At the next render, the presence of the current user will be equal to \"{ x: 0, y: 0 }\"\n */\nconst _useUpdateMyPresence: TypedBundle[\"useUpdateMyPresence\"] =\n useUpdateMyPresence;\n\nexport {\n CreateThreadError,\n RoomContext,\n _RoomProvider as RoomProvider,\n _useAddReaction as useAddReaction,\n useBatch,\n _useBroadcastEvent as useBroadcastEvent,\n useCanRedo,\n useCanUndo,\n // TODO: Move to `liveblocks-react-lexical`\n useCommentsErrorListener,\n useCreateComment,\n _useCreateThread as useCreateThread,\n useDeleteComment,\n _useDeleteThread as useDeleteThread,\n useEditComment,\n _useEditThreadMetadata as useEditThreadMetadata,\n useErrorListener,\n _useEventListener as useEventListener,\n useHistory,\n useHistoryVersionData,\n _useHistoryVersions as useHistoryVersions,\n _useHistoryVersionsSuspense as useHistoryVersionsSuspense,\n _useIsInsideRoom as useIsInsideRoom,\n useLostConnectionListener,\n useMarkThreadAsRead,\n useMarkThreadAsResolved,\n useMarkThreadAsUnresolved,\n _useMutation as useMutation,\n _useMyPresence as useMyPresence,\n _useOther as useOther,\n _useOthers as useOthers,\n useOthersConnectionIds,\n useOthersConnectionIdsSuspense,\n _useOthersListener as useOthersListener,\n _useOthersMapped as useOthersMapped,\n _useOthersMappedSuspense as useOthersMappedSuspense,\n _useOthersSuspense as useOthersSuspense,\n _useOtherSuspense as useOtherSuspense,\n useRedo,\n useRemoveReaction,\n _useRoom as useRoom,\n useRoomNotificationSettings,\n _useSelf as useSelf,\n _useSelfSuspense as useSelfSuspense,\n useStatus,\n _useStorage as useStorage,\n _useStorageRoot as useStorageRoot,\n useStorageStatus,\n useStorageStatusSuspense,\n _useStorageSuspense as useStorageSuspense,\n _useThreads as useThreads,\n _useThreadsSuspense as useThreadsSuspense,\n useThreadSubscription,\n useUndo,\n _useUpdateMyPresence as useUpdateMyPresence,\n useUpdateRoomNotificationSettings,\n};\n","import type { BaseMetadata } from \"@liveblocks/client\";\nimport * as React from \"react\";\n\nimport type { ThreadsState } from \"./types\";\n\nfunction handleScrollToCommentOnLoad(\n shouldScrollOnLoad: boolean,\n state: ThreadsState<BaseMetadata>\n) {\n if (shouldScrollOnLoad === false) return;\n\n if (state.isLoading) return;\n\n const isWindowDefined = typeof window !== \"undefined\";\n if (!isWindowDefined) return;\n\n const hash = window.location.hash;\n const commentId = hash.slice(1);\n\n // If the hash is not a comment ID, we do not scroll to it\n if (!commentId.startsWith(\"cm_\")) return;\n\n // If a comment with the ID does not exist in the DOM, we do not scroll to it\n const comment = document.getElementById(commentId);\n if (comment === null) return;\n\n const comments = state.threads.flatMap((thread) => thread.comments);\n const isCommentInThreads = comments.some(\n (comment) => comment.id === commentId\n );\n\n // If the comment is not in the threads for this hook, we do not scroll to it\n if (!isCommentInThreads) return;\n\n comment.scrollIntoView();\n}\n\n/**\n * Scroll to the comment with the ID in the hash of the URL based on whether\n * the query is loading and whether the hook should scroll to the comment on load.\n */\nexport function useScrollToCommentOnLoadEffect(\n shouldScrollOnLoad: boolean,\n state: ThreadsState<BaseMetadata>\n) {\n React.useEffect(\n () => {\n handleScrollToCommentOnLoad(shouldScrollOnLoad, state);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps -- We only want to run this effect once\n [state.isLoading]\n );\n}\n"]}
|