@liveblocks/react 3.8.1 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/_private.cjs CHANGED
@@ -25,7 +25,7 @@
25
25
 
26
26
 
27
27
 
28
- var _chunk2YWY7TUQcjs = require('./chunk-2YWY7TUQ.cjs');
28
+ var _chunkNGMOQDHXcjs = require('./chunk-NGMOQDHX.cjs');
29
29
 
30
30
  // src/lib/use-layout-effect.ts
31
31
  var _react = require('react');
@@ -50,7 +50,7 @@ function selectorFor_useGroup(state) {
50
50
  };
51
51
  }
52
52
  function useGroup(groupId) {
53
- const client = _chunk2YWY7TUQcjs.useClient.call(void 0, );
53
+ const client = _chunkNGMOQDHXcjs.useClient.call(void 0, );
54
54
  const store = client[_core.kInternal].httpClient.groupsStore;
55
55
  const getGroupState = _react.useCallback.call(void 0,
56
56
  () => store.getItemState(groupId),
@@ -59,7 +59,7 @@ function useGroup(groupId) {
59
59
  _react.useEffect.call(void 0, () => {
60
60
  void store.enqueue(groupId);
61
61
  }, [store, groupId]);
62
- return _chunk2YWY7TUQcjs.useSyncExternalStoreWithSelector.call(void 0,
62
+ return _chunkNGMOQDHXcjs.useSyncExternalStoreWithSelector.call(void 0,
63
63
  store.subscribe,
64
64
  getGroupState,
65
65
  getGroupState,
@@ -80,8 +80,8 @@ function normalizeMentionSuggestions(suggestions) {
80
80
  function useMentionSuggestions(roomId, search) {
81
81
  const [mentionSuggestions, setMentionSuggestions] = _react.useState.call(void 0, );
82
82
  const lastInvokedAt = _react.useRef.call(void 0, );
83
- const resolveMentionSuggestions = _chunk2YWY7TUQcjs.useResolveMentionSuggestions.call(void 0, );
84
- const mentionSuggestionsCache = _chunk2YWY7TUQcjs.useMentionSuggestionsCache.call(void 0, );
83
+ const resolveMentionSuggestions = _chunkNGMOQDHXcjs.useResolveMentionSuggestions.call(void 0, );
84
+ const mentionSuggestionsCache = _chunkNGMOQDHXcjs.useMentionSuggestionsCache.call(void 0, );
85
85
  _react.useEffect.call(void 0, () => {
86
86
  if (search === void 0 || !resolveMentionSuggestions) {
87
87
  return;
@@ -136,7 +136,7 @@ function useMentionSuggestions(roomId, search) {
136
136
 
137
137
 
138
138
  function useSyncSource() {
139
- const client = _chunk2YWY7TUQcjs.useClient.call(void 0, );
139
+ const client = _chunkNGMOQDHXcjs.useClient.call(void 0, );
140
140
  const createSyncSource = client[_core.kInternal].createSyncSource;
141
141
  const [syncSource, setSyncSource] = _react.useState.call(void 0, );
142
142
  _react.useEffect.call(void 0, () => {
@@ -176,5 +176,5 @@ function useSyncSource() {
176
176
 
177
177
 
178
178
 
179
- exports.getUmbrellaStoreForClient = _chunk2YWY7TUQcjs.getUmbrellaStoreForClient; exports.useAddRoomCommentReaction = _chunk2YWY7TUQcjs.useAddRoomCommentReaction; exports.useClientOrNull = _chunk2YWY7TUQcjs.useClientOrNull; exports.useCreateRoomComment = _chunk2YWY7TUQcjs.useCreateRoomComment; exports.useCreateRoomThread = _chunk2YWY7TUQcjs.useCreateRoomThread; exports.useCreateTextMention = _chunk2YWY7TUQcjs.useCreateTextMention; exports.useDeleteRoomComment = _chunk2YWY7TUQcjs.useDeleteRoomComment; exports.useDeleteRoomThread = _chunk2YWY7TUQcjs.useDeleteRoomThread; exports.useDeleteTextMention = _chunk2YWY7TUQcjs.useDeleteTextMention; exports.useEditRoomComment = _chunk2YWY7TUQcjs.useEditRoomComment; exports.useEditRoomThreadMetadata = _chunk2YWY7TUQcjs.useEditRoomThreadMetadata; exports.useGroup = useGroup; exports.useLatest = _chunk2YWY7TUQcjs.useLatest; exports.useLayoutEffect = useLayoutEffect; exports.useMarkRoomThreadAsRead = _chunk2YWY7TUQcjs.useMarkRoomThreadAsRead; exports.useMarkRoomThreadAsResolved = _chunk2YWY7TUQcjs.useMarkRoomThreadAsResolved; exports.useMarkRoomThreadAsUnresolved = _chunk2YWY7TUQcjs.useMarkRoomThreadAsUnresolved; exports.useMentionSuggestions = useMentionSuggestions; exports.useMentionSuggestionsCache = _chunk2YWY7TUQcjs.useMentionSuggestionsCache; exports.useRemoveRoomCommentReaction = _chunk2YWY7TUQcjs.useRemoveRoomCommentReaction; exports.useReportTextEditor = _chunk2YWY7TUQcjs.useReportTextEditor; exports.useResolveMentionSuggestions = _chunk2YWY7TUQcjs.useResolveMentionSuggestions; exports.useRoomAttachmentUrl = _chunk2YWY7TUQcjs.useRoomAttachmentUrl; exports.useRoomPermissions = _chunk2YWY7TUQcjs.useRoomPermissions; exports.useRoomThreadSubscription = _chunk2YWY7TUQcjs.useRoomThreadSubscription; exports.useSignal = _chunk2YWY7TUQcjs.useSignal; exports.useSyncExternalStoreWithSelector = _chunk2YWY7TUQcjs.useSyncExternalStoreWithSelector; exports.useSyncSource = useSyncSource; exports.useYjsProvider = _chunk2YWY7TUQcjs.useYjsProvider;
179
+ exports.getUmbrellaStoreForClient = _chunkNGMOQDHXcjs.getUmbrellaStoreForClient; exports.useAddRoomCommentReaction = _chunkNGMOQDHXcjs.useAddRoomCommentReaction; exports.useClientOrNull = _chunkNGMOQDHXcjs.useClientOrNull; exports.useCreateRoomComment = _chunkNGMOQDHXcjs.useCreateRoomComment; exports.useCreateRoomThread = _chunkNGMOQDHXcjs.useCreateRoomThread; exports.useCreateTextMention = _chunkNGMOQDHXcjs.useCreateTextMention; exports.useDeleteRoomComment = _chunkNGMOQDHXcjs.useDeleteRoomComment; exports.useDeleteRoomThread = _chunkNGMOQDHXcjs.useDeleteRoomThread; exports.useDeleteTextMention = _chunkNGMOQDHXcjs.useDeleteTextMention; exports.useEditRoomComment = _chunkNGMOQDHXcjs.useEditRoomComment; exports.useEditRoomThreadMetadata = _chunkNGMOQDHXcjs.useEditRoomThreadMetadata; exports.useGroup = useGroup; exports.useLatest = _chunkNGMOQDHXcjs.useLatest; exports.useLayoutEffect = useLayoutEffect; exports.useMarkRoomThreadAsRead = _chunkNGMOQDHXcjs.useMarkRoomThreadAsRead; exports.useMarkRoomThreadAsResolved = _chunkNGMOQDHXcjs.useMarkRoomThreadAsResolved; exports.useMarkRoomThreadAsUnresolved = _chunkNGMOQDHXcjs.useMarkRoomThreadAsUnresolved; exports.useMentionSuggestions = useMentionSuggestions; exports.useMentionSuggestionsCache = _chunkNGMOQDHXcjs.useMentionSuggestionsCache; exports.useRemoveRoomCommentReaction = _chunkNGMOQDHXcjs.useRemoveRoomCommentReaction; exports.useReportTextEditor = _chunkNGMOQDHXcjs.useReportTextEditor; exports.useResolveMentionSuggestions = _chunkNGMOQDHXcjs.useResolveMentionSuggestions; exports.useRoomAttachmentUrl = _chunkNGMOQDHXcjs.useRoomAttachmentUrl; exports.useRoomPermissions = _chunkNGMOQDHXcjs.useRoomPermissions; exports.useRoomThreadSubscription = _chunkNGMOQDHXcjs.useRoomThreadSubscription; exports.useSignal = _chunkNGMOQDHXcjs.useSignal; exports.useSyncExternalStoreWithSelector = _chunkNGMOQDHXcjs.useSyncExternalStoreWithSelector; exports.useSyncSource = useSyncSource; exports.useYjsProvider = _chunkNGMOQDHXcjs.useYjsProvider;
180
180
  //# sourceMappingURL=_private.cjs.map
@@ -1,5 +1,5 @@
1
- import { G as GroupAsyncResult } from './room-DkyB1sbB.cjs';
2
- export { g as getUmbrellaStoreForClient, a as useAddRoomCommentReaction, u as useClientOrNull, b as useCreateRoomComment, c as useCreateRoomThread, d as useCreateTextMention, e as useDeleteRoomComment, f as useDeleteRoomThread, h as useDeleteTextMention, i as useEditRoomComment, j as useEditRoomThreadMetadata, k as useMarkRoomThreadAsRead, l as useMarkRoomThreadAsResolved, m as useMarkRoomThreadAsUnresolved, n as useMentionSuggestionsCache, o as useRemoveRoomCommentReaction, p as useReportTextEditor, q as useResolveMentionSuggestions, r as useRoomAttachmentUrl, s as useRoomPermissions, t as useRoomThreadSubscription, v as useYjsProvider } from './room-DkyB1sbB.cjs';
1
+ import { G as GroupAsyncResult } from './room-BZvk8RRP.cjs';
2
+ export { g as getUmbrellaStoreForClient, a as useAddRoomCommentReaction, u as useClientOrNull, b as useCreateRoomComment, c as useCreateRoomThread, d as useCreateTextMention, e as useDeleteRoomComment, f as useDeleteRoomThread, h as useDeleteTextMention, i as useEditRoomComment, j as useEditRoomThreadMetadata, k as useMarkRoomThreadAsRead, l as useMarkRoomThreadAsResolved, m as useMarkRoomThreadAsUnresolved, n as useMentionSuggestionsCache, o as useRemoveRoomCommentReaction, p as useReportTextEditor, q as useResolveMentionSuggestions, r as useRoomAttachmentUrl, s as useRoomPermissions, t as useRoomThreadSubscription, v as useYjsProvider } from './room-BZvk8RRP.cjs';
3
3
  import { MutableRefObject, useEffect } from 'react';
4
4
  import { MentionData, ISignal, SyncSource } from '@liveblocks/core';
5
5
  import '@liveblocks/client';
@@ -1,5 +1,5 @@
1
- import { G as GroupAsyncResult } from './room-DkyB1sbB.js';
2
- export { g as getUmbrellaStoreForClient, a as useAddRoomCommentReaction, u as useClientOrNull, b as useCreateRoomComment, c as useCreateRoomThread, d as useCreateTextMention, e as useDeleteRoomComment, f as useDeleteRoomThread, h as useDeleteTextMention, i as useEditRoomComment, j as useEditRoomThreadMetadata, k as useMarkRoomThreadAsRead, l as useMarkRoomThreadAsResolved, m as useMarkRoomThreadAsUnresolved, n as useMentionSuggestionsCache, o as useRemoveRoomCommentReaction, p as useReportTextEditor, q as useResolveMentionSuggestions, r as useRoomAttachmentUrl, s as useRoomPermissions, t as useRoomThreadSubscription, v as useYjsProvider } from './room-DkyB1sbB.js';
1
+ import { G as GroupAsyncResult } from './room-BZvk8RRP.js';
2
+ export { g as getUmbrellaStoreForClient, a as useAddRoomCommentReaction, u as useClientOrNull, b as useCreateRoomComment, c as useCreateRoomThread, d as useCreateTextMention, e as useDeleteRoomComment, f as useDeleteRoomThread, h as useDeleteTextMention, i as useEditRoomComment, j as useEditRoomThreadMetadata, k as useMarkRoomThreadAsRead, l as useMarkRoomThreadAsResolved, m as useMarkRoomThreadAsUnresolved, n as useMentionSuggestionsCache, o as useRemoveRoomCommentReaction, p as useReportTextEditor, q as useResolveMentionSuggestions, r as useRoomAttachmentUrl, s as useRoomPermissions, t as useRoomThreadSubscription, v as useYjsProvider } from './room-BZvk8RRP.js';
3
3
  import { MutableRefObject, useEffect } from 'react';
4
4
  import { MentionData, ISignal, SyncSource } from '@liveblocks/core';
5
5
  import '@liveblocks/client';
package/dist/_private.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  useSignal,
26
26
  useSyncExternalStoreWithSelector,
27
27
  useYjsProvider
28
- } from "./chunk-QY4EJ7GZ.js";
28
+ } from "./chunk-J2LMX3A6.js";
29
29
 
30
30
  // src/lib/use-layout-effect.ts
31
31
  import { useEffect, useLayoutEffect as useOriginalLayoutEffect } from "react";
@@ -286,7 +286,7 @@ import {
286
286
  createNotificationSettings,
287
287
  DefaultMap,
288
288
  DerivedSignal,
289
- getSubscriptionKey,
289
+ getSubscriptionKey as getSubscriptionKey2,
290
290
  kInternal as kInternal2,
291
291
  MutableSignal as MutableSignal3,
292
292
  nanoid as nanoid2,
@@ -324,12 +324,20 @@ function find(it, predicate) {
324
324
  }
325
325
 
326
326
  // src/lib/querying.ts
327
- import { isNumberOperator, isStartsWithOperator } from "@liveblocks/core";
328
- function makeThreadsFilter(query) {
329
- return (thread) => matchesThreadsQuery(thread, query) && matchesMetadata(thread, query);
327
+ import {
328
+ getSubscriptionKey,
329
+ isNumberOperator,
330
+ isStartsWithOperator
331
+ } from "@liveblocks/core";
332
+ function makeThreadsFilter(query, subscriptions) {
333
+ return (thread) => matchesThreadsQuery(thread, query, subscriptions) && matchesMetadata(thread, query);
330
334
  }
331
- function matchesThreadsQuery(thread, q) {
332
- return q.resolved === void 0 || thread.resolved === q.resolved;
335
+ function matchesThreadsQuery(thread, q, subscriptions) {
336
+ let subscription = void 0;
337
+ if (subscriptions) {
338
+ subscription = subscriptions?.[getSubscriptionKey("thread", thread.id)];
339
+ }
340
+ return (q.resolved === void 0 || thread.resolved === q.resolved) && (q.subscribed === void 0 || q.subscribed === true && subscription !== void 0 || q.subscribed === false && subscription === void 0);
333
341
  }
334
342
  function matchesMetadata(thread, q) {
335
343
  const metadata = thread.metadata;
@@ -475,15 +483,17 @@ var ThreadDB = class _ThreadDB {
475
483
  * 'desc' means by updatedAt DESC
476
484
  *
477
485
  * Will never return deleted threads in the result.
486
+ *
487
+ * Subscriptions are needed to filter threads based on the user's subscriptions.
478
488
  */
479
- findMany(roomId, query, direction) {
489
+ findMany(roomId, query, direction, subscriptions) {
480
490
  const index = direction === "desc" ? this.#desc : this.#asc;
481
491
  const crit = [];
482
492
  if (roomId !== void 0) {
483
493
  crit.push((t) => t.roomId === roomId);
484
494
  }
485
495
  if (query !== void 0) {
486
- crit.push(makeThreadsFilter(query));
496
+ crit.push(makeThreadsFilter(query, subscriptions));
487
497
  }
488
498
  return Array.from(index.filter((t) => crit.every((pred) => pred(t))));
489
499
  }
@@ -614,10 +624,12 @@ var SinglePageResource = class {
614
624
  #signal;
615
625
  signal;
616
626
  #fetchPage;
617
- constructor(fetchPage) {
627
+ #autoRetry = true;
628
+ constructor(fetchPage, autoRetry2 = true) {
618
629
  this.#signal = new Signal(ASYNC_LOADING);
619
630
  this.signal = this.#signal.asReadonly();
620
631
  this.#fetchPage = fetchPage;
632
+ this.#autoRetry = autoRetry2;
621
633
  autobind(this);
622
634
  }
623
635
  get() {
@@ -628,11 +640,7 @@ var SinglePageResource = class {
628
640
  if (this.#cachedPromise) {
629
641
  return this.#cachedPromise;
630
642
  }
631
- const initialFetcher$ = autoRetry(
632
- () => this.#fetchPage(),
633
- 5,
634
- [5e3, 5e3, 1e4, 15e3]
635
- );
643
+ const initialFetcher$ = this.#autoRetry ? autoRetry(() => this.#fetchPage(), 5, [5e3, 5e3, 1e4, 15e3]) : this.#fetchPage();
636
644
  const promise = usify(initialFetcher$);
637
645
  promise.then(
638
646
  () => {
@@ -640,10 +648,12 @@ var SinglePageResource = class {
640
648
  },
641
649
  (err) => {
642
650
  this.#signal.set(ASYNC_ERR(err));
643
- setTimeout(() => {
644
- this.#cachedPromise = null;
645
- this.#signal.set(ASYNC_LOADING);
646
- }, 5e3);
651
+ if (this.#autoRetry) {
652
+ setTimeout(() => {
653
+ this.#cachedPromise = null;
654
+ this.#signal.set(ASYNC_LOADING);
655
+ }, 5e3);
656
+ }
647
657
  }
648
658
  );
649
659
  this.#cachedPromise = promise;
@@ -747,11 +757,11 @@ function createStore_forSubscriptions(updates, threads) {
747
757
  baseSignal.mutate((lut) => {
748
758
  let mutated = false;
749
759
  for (const s of newSubscriptions) {
750
- lut.set(getSubscriptionKey(s), s);
760
+ lut.set(getSubscriptionKey2(s), s);
751
761
  mutated = true;
752
762
  }
753
763
  for (const s of deletedSubscriptions) {
754
- lut.delete(getSubscriptionKey(s));
764
+ lut.delete(getSubscriptionKey2(s));
755
765
  mutated = true;
756
766
  }
757
767
  return mutated;
@@ -759,7 +769,7 @@ function createStore_forSubscriptions(updates, threads) {
759
769
  }
760
770
  function create(subscription) {
761
771
  baseSignal.mutate((lut) => {
762
- lut.set(getSubscriptionKey(subscription), subscription);
772
+ lut.set(getSubscriptionKey2(subscription), subscription);
763
773
  });
764
774
  }
765
775
  function deleteOne(subscriptionKey) {
@@ -822,6 +832,19 @@ function createStore_forHistoryVersions() {
822
832
  update
823
833
  };
824
834
  }
835
+ function createStore_forUrlsMetadata() {
836
+ const baseSignal = new MutableSignal3(/* @__PURE__ */ new Map());
837
+ function update(url, metadata) {
838
+ baseSignal.mutate((lut) => {
839
+ lut.set(url, metadata);
840
+ });
841
+ }
842
+ return {
843
+ signal: DerivedSignal.from(baseSignal, (m) => Object.fromEntries(m)),
844
+ // Mutations
845
+ update
846
+ };
847
+ }
825
848
  function createStore_forPermissionHints() {
826
849
  const permissionsByRoomId = new DefaultMap(
827
850
  () => new Signal(/* @__PURE__ */ new Set())
@@ -931,6 +954,7 @@ var UmbrellaStore = class {
931
954
  // prettier-ignore
932
955
  historyVersions;
933
956
  unreadNotificationsCount;
957
+ urlsMetadata;
934
958
  permissionHints;
935
959
  notificationSettings;
936
960
  optimisticUpdates;
@@ -979,6 +1003,7 @@ var UmbrellaStore = class {
979
1003
  );
980
1004
  this.historyVersions = createStore_forHistoryVersions();
981
1005
  this.unreadNotificationsCount = createStore_forUnreadNotificationsCount();
1006
+ this.urlsMetadata = createStore_forUrlsMetadata();
982
1007
  const threadifications = DerivedSignal.from(
983
1008
  this.threads.signal,
984
1009
  this.notifications.signal,
@@ -1026,11 +1051,13 @@ var UmbrellaStore = class {
1026
1051
  if (result.isLoading || result.error) {
1027
1052
  return result;
1028
1053
  }
1054
+ const subscriptions = threadSubscriptions.get().subscriptions;
1029
1055
  const threads2 = this.outputs.threads.get().findMany(
1030
1056
  void 0,
1031
1057
  // Do _not_ filter by roomId
1032
1058
  query ?? {},
1033
- "desc"
1059
+ "desc",
1060
+ subscriptions
1034
1061
  );
1035
1062
  const page = result.data;
1036
1063
  return {
@@ -1074,7 +1101,8 @@ var UmbrellaStore = class {
1074
1101
  if (result.isLoading || result.error) {
1075
1102
  return result;
1076
1103
  }
1077
- const threads2 = this.outputs.threads.get().findMany(roomId, query ?? {}, "asc");
1104
+ const subscriptions = threadSubscriptions.get().subscriptions;
1105
+ const threads2 = this.outputs.threads.get().findMany(roomId, query ?? {}, "asc", subscriptions);
1078
1106
  const page = result.data;
1079
1107
  return {
1080
1108
  isLoading: false,
@@ -1305,6 +1333,22 @@ var UmbrellaStore = class {
1305
1333
  }, shallow);
1306
1334
  return { signal, waitUntilLoaded: resource.waitUntilLoaded };
1307
1335
  });
1336
+ const urlMetadataByUrl = new DefaultMap(
1337
+ (url) => {
1338
+ const resource = new SinglePageResource(async () => {
1339
+ const metadata = await this.#client[kInternal2].httpClient.getUrlMetadata(url);
1340
+ this.urlsMetadata.update(url, metadata);
1341
+ }, false);
1342
+ const signal = DerivedSignal.from(() => {
1343
+ const result = resource.get();
1344
+ if (result.isLoading || result.error) {
1345
+ return result;
1346
+ }
1347
+ return ASYNC_OK("metadata", nn(this.urlsMetadata.signal.get()[url]));
1348
+ }, shallow);
1349
+ return { signal, waitUntilLoaded: resource.waitUntilLoaded };
1350
+ }
1351
+ );
1308
1352
  this.outputs = {
1309
1353
  threadifications,
1310
1354
  threads,
@@ -1319,7 +1363,8 @@ var UmbrellaStore = class {
1319
1363
  threadSubscriptions,
1320
1364
  aiChats,
1321
1365
  messagesByChatId,
1322
- aiChatById
1366
+ aiChatById,
1367
+ urlMetadataByUrl
1323
1368
  };
1324
1369
  autobind(this);
1325
1370
  }
@@ -1800,9 +1845,14 @@ function applyOptimisticUpdates_forSubscriptions(subscriptionsLUT, threads, opti
1800
1845
  if (!update.settings.threads) {
1801
1846
  continue;
1802
1847
  }
1803
- const roomThreads = threads.findMany(update.roomId, void 0, "desc");
1848
+ const roomThreads = threads.findMany(
1849
+ update.roomId,
1850
+ void 0,
1851
+ "desc",
1852
+ void 0
1853
+ );
1804
1854
  for (const thread of roomThreads) {
1805
- const subscriptionKey = getSubscriptionKey("thread", thread.id);
1855
+ const subscriptionKey = getSubscriptionKey2("thread", thread.id);
1806
1856
  switch (update.settings.threads) {
1807
1857
  // Create subscriptions for all existing threads in the room
1808
1858
  case "all": {
@@ -2225,6 +2275,7 @@ function makeLiveblocksContextBundle(client) {
2225
2275
  useCreateAiChat,
2226
2276
  useDeleteAiChat,
2227
2277
  useSendAiMessage,
2278
+ useUrlMetadata,
2228
2279
  ...shared.classic,
2229
2280
  suspense: {
2230
2281
  LiveblocksProvider: LiveblocksProvider2,
@@ -2245,6 +2296,7 @@ function makeLiveblocksContextBundle(client) {
2245
2296
  useCreateAiChat,
2246
2297
  useDeleteAiChat,
2247
2298
  useSendAiMessage,
2299
+ useUrlMetadata: useUrlMetadataSuspense,
2248
2300
  ...shared.suspense
2249
2301
  }
2250
2302
  };
@@ -2822,6 +2874,32 @@ function useAiChatSuspense(chatId) {
2822
2874
  assert(!result.isLoading, "Did not expect loading");
2823
2875
  return result;
2824
2876
  }
2877
+ function useUrlMetadata(url) {
2878
+ const client = useClient();
2879
+ const store = getUmbrellaStoreForClient(client);
2880
+ useEffect4(
2881
+ () => void store.outputs.urlMetadataByUrl.getOrCreate(url).waitUntilLoaded()
2882
+ // NOTE: Deliberately *not* using a dependency array here!
2883
+ //
2884
+ // It is important to call waitUntil on *every* render.
2885
+ // This is harmless though, on most renders, except:
2886
+ // 1. The very first render, in which case we'll want to trigger the initial page fetch.
2887
+ // 2. All other subsequent renders now "just" return the same promise (a quick operation).
2888
+ // 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
2889
+ // *next* render after that, a *new* fetch/promise will get created.
2890
+ );
2891
+ return useSignal(store.outputs.urlMetadataByUrl.getOrCreate(url).signal);
2892
+ }
2893
+ function useUrlMetadataSuspense(url) {
2894
+ ensureNotServerSide();
2895
+ const client = useClient();
2896
+ const store = getUmbrellaStoreForClient(client);
2897
+ use(store.outputs.urlMetadataByUrl.getOrCreate(url).waitUntilLoaded());
2898
+ const result = useUrlMetadata(url);
2899
+ assert(!result.error, "Did not expect error");
2900
+ assert(!result.isLoading, "Did not expect loading");
2901
+ return result;
2902
+ }
2825
2903
  function useCreateAiChat() {
2826
2904
  const client = useClient();
2827
2905
  return useCallback2(
@@ -2854,6 +2932,7 @@ function useDeleteAiChat() {
2854
2932
  [client]
2855
2933
  );
2856
2934
  }
2935
+ var DISCONNECTED = Object.freeze({ status: "disconnected" });
2857
2936
  var LOADING = Object.freeze({ status: "loading" });
2858
2937
  var IDLE = Object.freeze({ status: "idle" });
2859
2938
  function useAiChatStatus(chatId, branchId) {
@@ -2863,7 +2942,14 @@ function useAiChatStatus(chatId, branchId) {
2863
2942
  useEffect4(
2864
2943
  () => void store.outputs.messagesByChatId.getOrCreate(chatId).getOrCreate(branchId ?? null).waitUntilLoaded()
2865
2944
  );
2866
- return useSignal(
2945
+ const isAvailable = useSignal(
2946
+ // Subscribe to connection status signal
2947
+ client[kInternal3].ai.signals.status\u03A3,
2948
+ // "Disconnected" means the AI service is not available
2949
+ // as it represents a final error status.
2950
+ (status) => status !== "disconnected"
2951
+ );
2952
+ const chatStatus = useSignal(
2867
2953
  // Signal
2868
2954
  store.outputs.messagesByChatId.getOrCreate(chatId).getOrCreate(branchId ?? null).signal,
2869
2955
  // Selector
@@ -2884,12 +2970,19 @@ function useAiChatStatus(chatId, branchId) {
2884
2970
  toolName: lastPart.name
2885
2971
  };
2886
2972
  } else {
2887
- return { status: "generating", partType: lastPart?.type };
2973
+ return {
2974
+ status: "generating",
2975
+ partType: lastPart?.type
2976
+ };
2888
2977
  }
2889
2978
  },
2890
2979
  // Consider { status: "generating", partType: "text" } and { status: "generating", partType: "text" } equal
2891
2980
  shallow3
2892
2981
  );
2982
+ if (!isAvailable) {
2983
+ return DISCONNECTED;
2984
+ }
2985
+ return chatStatus;
2893
2986
  }
2894
2987
  function useSendAiMessage(chatId, options) {
2895
2988
  const client = useClient();
@@ -3145,6 +3238,8 @@ var _useAiChat = useAiChat;
3145
3238
  var _useAiChatSuspense = useAiChatSuspense;
3146
3239
  var _useAiChatMessages = useAiChatMessages;
3147
3240
  var _useAiChatMessagesSuspense = useAiChatMessagesSuspense;
3241
+ var _useUrlMetadata = useUrlMetadata;
3242
+ var _useUrlMetadataSuspense = useUrlMetadataSuspense;
3148
3243
  function useSyncStatus_withClient(client, options) {
3149
3244
  const smooth = useInitial(options?.smooth ?? false);
3150
3245
  if (smooth) {
@@ -3203,7 +3298,7 @@ import {
3203
3298
  createThreadId,
3204
3299
  DefaultMap as DefaultMap3,
3205
3300
  errorIf,
3206
- getSubscriptionKey as getSubscriptionKey2,
3301
+ getSubscriptionKey as getSubscriptionKey3,
3207
3302
  HttpError as HttpError2,
3208
3303
  kInternal as kInternal4,
3209
3304
  makePoller as makePoller2,
@@ -4450,7 +4545,7 @@ function useUnsubscribeFromRoomThread(roomId) {
4450
4545
  client[kInternal4].httpClient.unsubscribeFromThread({ roomId, threadId }).then(
4451
4546
  () => {
4452
4547
  store.deleteSubscription(
4453
- getSubscriptionKey2("thread", threadId),
4548
+ getSubscriptionKey3("thread", threadId),
4454
4549
  optimisticId
4455
4550
  );
4456
4551
  },
@@ -4471,7 +4566,7 @@ function useRoomThreadSubscription(roomId, threadId) {
4471
4566
  const client = useClient();
4472
4567
  const { store } = getRoomExtrasForClient(client);
4473
4568
  const subscriptionKey = useMemo4(
4474
- () => getSubscriptionKey2("thread", threadId),
4569
+ () => getSubscriptionKey3("thread", threadId),
4475
4570
  [threadId]
4476
4571
  );
4477
4572
  const subscribeToThread = useSubscribeToRoomThread(roomId);
@@ -4859,6 +4954,8 @@ export {
4859
4954
  _useAiChatSuspense,
4860
4955
  _useAiChatMessages,
4861
4956
  _useAiChatMessagesSuspense,
4957
+ _useUrlMetadata,
4958
+ _useUrlMetadataSuspense,
4862
4959
  useSyncStatus,
4863
4960
  useErrorListener,
4864
4961
  useStatus,
@@ -4936,4 +5033,4 @@ export {
4936
5033
  _useStorageRoot,
4937
5034
  _useUpdateMyPresence
4938
5035
  };
4939
- //# sourceMappingURL=chunk-QY4EJ7GZ.js.map
5036
+ //# sourceMappingURL=chunk-J2LMX3A6.js.map