@liveblocks/react 1.12.0 → 2.0.0-alpha1

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/index.js CHANGED
@@ -1,64 +1,84 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+ var _chunkRCQYZVO3js = require('./chunk-RCQYZVO3.js');
2
56
 
3
57
  // src/index.ts
4
58
  var _core = require('@liveblocks/core');
59
+ var _client = require('@liveblocks/client');
60
+ _core.detectDupes.call(void 0, _chunkRCQYZVO3js.PKG_NAME, _chunkRCQYZVO3js.PKG_VERSION, _chunkRCQYZVO3js.PKG_FORMAT);
61
+
62
+
63
+
5
64
 
6
- // src/version.ts
7
- var PKG_NAME = "@liveblocks/react";
8
- var PKG_VERSION = "1.12.0";
9
- var PKG_FORMAT = "cjs";
10
65
 
11
- // src/ClientSideSuspense.tsx
12
- var _react = require('react'); var React = _interopRequireWildcard(_react); var React2 = _interopRequireWildcard(_react);
13
- function ClientSideSuspense(props) {
14
- const [mounted, setMounted] = React.useState(false);
15
- React.useEffect(() => {
16
- setMounted(true);
17
- }, []);
18
- return /* @__PURE__ */ React.createElement(React.Suspense, { fallback: props.fallback }, mounted ? props.children() : props.fallback);
19
- }
20
66
 
21
- // src/liveblocks.tsx
22
67
 
23
- var _nanoid = require('nanoid');
24
68
 
25
69
 
26
70
 
27
71
 
28
72
 
29
73
 
30
- var _indexjs = require('use-sync-external-store/shim/index.js');
31
- var _withselectorjs = require('use-sync-external-store/shim/with-selector.js');
32
74
 
33
- // src/comments/lib/selected-inbox-notifications.ts
34
75
 
35
- function selectedInboxNotifications(state) {
36
- const result = _core.applyOptimisticUpdates.call(void 0, state);
37
- return Object.values(result.inboxNotifications).sort(
38
- // Sort so that the most recent notifications are first
39
- (a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime()
40
- );
41
- }
42
76
 
43
- // src/lib/retry-error.ts
44
- var MAX_ERROR_RETRY_COUNT = 5;
45
- var ERROR_RETRY_INTERVAL = 5e3;
46
- function retryError(action, retryCount) {
47
- if (retryCount >= MAX_ERROR_RETRY_COUNT)
48
- return;
49
- const timeout = Math.pow(2, retryCount) * ERROR_RETRY_INTERVAL;
50
- setTimeout(() => {
51
- void action();
52
- }, timeout);
53
- }
54
77
 
55
- // src/shared.ts
56
78
 
57
79
 
58
80
 
59
81
 
60
- // src/room.tsx
61
- var _client = require('@liveblocks/client');
62
82
 
63
83
 
64
84
 
@@ -80,2281 +100,8 @@ var _client = require('@liveblocks/client');
80
100
 
81
101
 
82
102
 
83
- // src/comments/errors.ts
84
- var CreateThreadError = class extends Error {
85
- constructor(cause, context) {
86
- super("Create thread failed.");
87
- this.cause = cause;
88
- this.context = context;
89
- this.name = "CreateThreadError";
90
- }
91
- };
92
- var EditThreadMetadataError = class extends Error {
93
- constructor(cause, context) {
94
- super("Edit thread metadata failed.");
95
- this.cause = cause;
96
- this.context = context;
97
- this.name = "EditThreadMetadataError";
98
- }
99
- };
100
- var CreateCommentError = class extends Error {
101
- constructor(cause, context) {
102
- super("Create comment failed.");
103
- this.cause = cause;
104
- this.context = context;
105
- this.name = "CreateCommentError";
106
- }
107
- };
108
- var EditCommentError = class extends Error {
109
- constructor(cause, context) {
110
- super("Edit comment failed.");
111
- this.cause = cause;
112
- this.context = context;
113
- this.name = "EditCommentError";
114
- }
115
- };
116
- var DeleteCommentError = class extends Error {
117
- constructor(cause, context) {
118
- super("Delete comment failed.");
119
- this.cause = cause;
120
- this.context = context;
121
- this.name = "DeleteCommentError";
122
- }
123
- };
124
- var AddReactionError = class extends Error {
125
- constructor(cause, context) {
126
- super("Add reaction failed.");
127
- this.cause = cause;
128
- this.context = context;
129
- this.name = "AddReactionError";
130
- }
131
- };
132
- var RemoveReactionError = class extends Error {
133
- constructor(cause, context) {
134
- super("Remove reaction failed.");
135
- this.cause = cause;
136
- this.context = context;
137
- this.name = "RemoveReactionError";
138
- }
139
- };
140
- var MarkInboxNotificationAsReadError = class extends Error {
141
- constructor(cause, context) {
142
- super("Mark inbox notification as read failed.");
143
- this.cause = cause;
144
- this.context = context;
145
- this.name = "MarkInboxNotificationAsReadError";
146
- }
147
- };
148
- var UpdateNotificationSettingsError = class extends Error {
149
- constructor(cause, context) {
150
- super("Update notification settings failed.");
151
- this.cause = cause;
152
- this.context = context;
153
- this.name = "UpdateNotificationSettingsError";
154
- }
155
- };
156
-
157
- // src/comments/lib/createIds.ts
158
-
159
- var THREAD_ID_PREFIX = "th";
160
- var COMMENT_ID_PREFIX = "cm";
161
- function createOptimisticId(prefix) {
162
- return `${prefix}_${_nanoid.nanoid.call(void 0, )}`;
163
- }
164
- function createThreadId() {
165
- return createOptimisticId(THREAD_ID_PREFIX);
166
- }
167
- function createCommentId() {
168
- return createOptimisticId(COMMENT_ID_PREFIX);
169
- }
170
-
171
- // src/comments/lib/select-notification-settings.ts
172
-
173
-
174
-
175
-
176
- function selectNotificationSettings(roomId, state) {
177
- const { notificationSettings } = _core.applyOptimisticUpdates.call(void 0, state);
178
- return _core.nn.call(void 0, notificationSettings[roomId]);
179
- }
180
-
181
- // src/comments/lib/selected-threads.ts
182
-
183
-
184
-
185
- function selectedThreads(roomId, state, options) {
186
- const result = _core.applyOptimisticUpdates.call(void 0, state);
187
- const threads = Object.values(result.threads).filter((thread) => {
188
- if (thread.roomId !== roomId)
189
- return false;
190
- if (thread.deletedAt !== void 0) {
191
- return false;
192
- }
193
- const query = options.query;
194
- if (!query)
195
- return true;
196
- for (const key in query.metadata) {
197
- const metadataValue = thread.metadata[key];
198
- const filterValue = query.metadata[key];
199
- if (assertFilterIsStartsWithOperator(filterValue) && assertMetadataValueIsString(metadataValue)) {
200
- if (metadataValue.startsWith(filterValue.startsWith)) {
201
- return true;
202
- }
203
- }
204
- if (metadataValue !== filterValue) {
205
- return false;
206
- }
207
- }
208
- return true;
209
- });
210
- return threads.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
211
- }
212
- var assertFilterIsStartsWithOperator = (filter) => {
213
- if (typeof filter === "object" && typeof filter.startsWith === "string") {
214
- return true;
215
- } else {
216
- return false;
217
- }
218
- };
219
- var assertMetadataValueIsString = (value) => {
220
- return typeof value === "string";
221
- };
222
-
223
- // src/lib/use-initial.ts
224
-
225
- function useInitial(value) {
226
- return _react.useState.call(void 0, value)[0];
227
- }
228
-
229
- // src/lib/use-latest.ts
230
-
231
- function useLatest(value) {
232
- const ref = _react.useRef.call(void 0, value);
233
- _react.useEffect.call(void 0, () => {
234
- ref.current = value;
235
- }, [value]);
236
- return ref;
237
- }
238
-
239
- // src/lib/use-rerender.ts
240
-
241
- function useRerender() {
242
- const [, update] = _react.useReducer.call(void 0,
243
- // This implementation works by incrementing a hidden counter value that is
244
- // never consumed. Simply incrementing the counter changes the component's
245
- // state and, thus, trigger a re-render.
246
- (x) => x + 1,
247
- 0
248
- );
249
- return update;
250
- }
251
-
252
- // src/room.tsx
253
- var noop = () => {
254
- };
255
- var identity = (x) => x;
256
- var missing_unstable_batchedUpdates = (reactVersion, roomId) => `We noticed you\u2019re using React ${reactVersion}. Please pass unstable_batchedUpdates at the RoomProvider level until you\u2019re ready to upgrade to React 18:
257
-
258
- import { unstable_batchedUpdates } from "react-dom"; // or "react-native"
259
-
260
- <RoomProvider id=${JSON.stringify(
261
- roomId
262
- )} ... unstable_batchedUpdates={unstable_batchedUpdates}>
263
- ...
264
- </RoomProvider>
265
-
266
- Why? Please see https://liveblocks.io/docs/platform/troubleshooting#stale-props-zombie-child for more information`;
267
- var superfluous_unstable_batchedUpdates = "You don\u2019t need to pass unstable_batchedUpdates to RoomProvider anymore, since you\u2019re on React 18+ already.";
268
- function useSyncExternalStore(s, gs, gss) {
269
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0, s, gs, gss, identity);
270
- }
271
- var STABLE_EMPTY_LIST = Object.freeze([]);
272
- var POLLING_INTERVAL = 5 * 60 * 1e3;
273
- var MENTION_SUGGESTIONS_DEBOUNCE = 500;
274
- function alwaysEmptyList() {
275
- return STABLE_EMPTY_LIST;
276
- }
277
- function alwaysNull() {
278
- return null;
279
- }
280
- function makeMutationContext(room) {
281
- const errmsg = "This mutation cannot be used until connected to the Liveblocks room";
282
- return {
283
- get storage() {
284
- const mutableRoot = room.getStorageSnapshot();
285
- if (mutableRoot === null) {
286
- throw new Error(errmsg);
287
- }
288
- return mutableRoot;
289
- },
290
- get self() {
291
- const self = room.getSelf();
292
- if (self === null) {
293
- throw new Error(errmsg);
294
- }
295
- return self;
296
- },
297
- get others() {
298
- const others = room.getOthers();
299
- if (room.getSelf() === null) {
300
- throw new Error(errmsg);
301
- }
302
- return others;
303
- },
304
- setMyPresence: room.updatePresence
305
- };
306
- }
307
- var ContextBundle = React2.createContext(null);
308
- function useRoomContextBundle() {
309
- const bundle = React2.useContext(ContextBundle);
310
- if (bundle === null) {
311
- throw new Error("RoomProvider is missing from the React tree.");
312
- }
313
- return bundle;
314
- }
315
- function createRoomContext(client, options) {
316
- if (_optionalChain([options, 'optionalAccess', _ => _.resolveUsers])) {
317
- throw new Error(
318
- "The 'resolveUsers' option has moved to 'createClient' from '@liveblocks/client'. Please refer to our Upgrade Guide to learn more, see https://liveblocks.io/docs/platform/upgrading/1.10."
319
- );
320
- }
321
- if (_optionalChain([options, 'optionalAccess', _2 => _2.resolveMentionSuggestions])) {
322
- throw new Error(
323
- "The 'resolveMentionSuggestions' option has moved to 'createClient' from '@liveblocks/client'. Please refer to our Upgrade Guide to learn more, see https://liveblocks.io/docs/platform/upgrading/1.10."
324
- );
325
- }
326
- const RoomContext = React2.createContext(null);
327
- const commentsErrorEventSource = _core.makeEventSource.call(void 0, );
328
- const shared = createSharedContext(client);
329
- function RoomProviderOuter(props) {
330
- const [cache] = React2.useState(
331
- () => /* @__PURE__ */ new Map()
332
- );
333
- const stableEnterRoom = React2.useCallback(
334
- (roomId, options2) => {
335
- const cached = cache.get(roomId);
336
- if (cached)
337
- return cached;
338
- const rv = client.enterRoom(
339
- roomId,
340
- options2
341
- );
342
- const origLeave = rv.leave;
343
- rv.leave = () => {
344
- origLeave();
345
- cache.delete(roomId);
346
- };
347
- cache.set(roomId, rv);
348
- return rv;
349
- },
350
- [cache]
351
- );
352
- return /* @__PURE__ */ React2.createElement(RoomProviderInner, { ...props, stableEnterRoom });
353
- }
354
- function RoomProviderInner(props) {
355
- const { id: roomId, stableEnterRoom } = props;
356
- if (process.env.NODE_ENV !== "production") {
357
- if (!roomId) {
358
- throw new Error(
359
- "RoomProvider id property is required. For more information: https://liveblocks.io/docs/errors/liveblocks-react/RoomProvider-id-property-is-required"
360
- );
361
- }
362
- if (typeof roomId !== "string") {
363
- throw new Error("RoomProvider id property should be a string.");
364
- }
365
- const majorReactVersion = parseInt(React2.version) || 1;
366
- const oldReactVersion = majorReactVersion < 18;
367
- _core.errorIf.call(void 0,
368
- oldReactVersion && props.unstable_batchedUpdates === void 0,
369
- missing_unstable_batchedUpdates(majorReactVersion, roomId)
370
- );
371
- _core.deprecateIf.call(void 0,
372
- !oldReactVersion && props.unstable_batchedUpdates !== void 0,
373
- superfluous_unstable_batchedUpdates
374
- );
375
- }
376
- const frozenProps = useInitial({
377
- initialPresence: props.initialPresence,
378
- initialStorage: props.initialStorage,
379
- unstable_batchedUpdates: props.unstable_batchedUpdates,
380
- autoConnect: _nullishCoalesce(_nullishCoalesce(props.autoConnect, () => ( props.shouldInitiallyConnect)), () => ( typeof window !== "undefined"))
381
- });
382
- const [{ room }, setRoomLeavePair] = React2.useState(
383
- () => stableEnterRoom(roomId, {
384
- ...frozenProps,
385
- autoConnect: false
386
- // Deliberately using false here on the first render, see below
387
- })
388
- );
389
- React2.useEffect(() => {
390
- async function handleCommentEvent(message) {
391
- const info = await room[_core.kInternal].comments.getThread({
392
- threadId: message.threadId
393
- });
394
- if (!info) {
395
- store.deleteThread(message.threadId);
396
- return;
397
- }
398
- const { thread, inboxNotification } = info;
399
- const existingThread = store.get().threads[message.threadId];
400
- switch (message.type) {
401
- case _core.ServerMsgCode.COMMENT_EDITED:
402
- case _core.ServerMsgCode.THREAD_METADATA_UPDATED:
403
- case _core.ServerMsgCode.COMMENT_REACTION_ADDED:
404
- case _core.ServerMsgCode.COMMENT_REACTION_REMOVED:
405
- case _core.ServerMsgCode.COMMENT_DELETED:
406
- if (!existingThread)
407
- break;
408
- store.updateThreadAndNotification(thread, inboxNotification);
409
- break;
410
- case _core.ServerMsgCode.COMMENT_CREATED:
411
- store.updateThreadAndNotification(thread, inboxNotification);
412
- break;
413
- default:
414
- break;
415
- }
416
- }
417
- return room.events.comments.subscribe(
418
- (message) => void handleCommentEvent(message)
419
- );
420
- }, [room]);
421
- React2.useEffect(() => {
422
- void getThreadsUpdates(room.id);
423
- }, [room.id]);
424
- React2.useEffect(() => {
425
- function handleIsOnline() {
426
- void getThreadsUpdates(room.id);
427
- }
428
- window.addEventListener("online", handleIsOnline);
429
- return () => {
430
- window.removeEventListener("online", handleIsOnline);
431
- };
432
- }, [room.id]);
433
- React2.useEffect(() => {
434
- const pair = stableEnterRoom(roomId, frozenProps);
435
- setRoomLeavePair(pair);
436
- const { room: room2, leave } = pair;
437
- if (frozenProps.autoConnect) {
438
- room2.connect();
439
- }
440
- return () => {
441
- leave();
442
- };
443
- }, [roomId, frozenProps, stableEnterRoom]);
444
- return /* @__PURE__ */ React2.createElement(RoomContext.Provider, { value: room }, /* @__PURE__ */ React2.createElement(
445
- ContextBundle.Provider,
446
- {
447
- value: bundle
448
- },
449
- props.children
450
- ));
451
- }
452
- function connectionIdSelector(others) {
453
- return others.map((user) => user.connectionId);
454
- }
455
- function useRoom() {
456
- const room = React2.useContext(RoomContext);
457
- if (room === null) {
458
- throw new Error("RoomProvider is missing from the React tree.");
459
- }
460
- return room;
461
- }
462
- function useStatus() {
463
- const room = useRoom();
464
- const subscribe = room.events.status.subscribe;
465
- const getSnapshot = room.getStatus;
466
- const getServerSnapshot = room.getStatus;
467
- return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
468
- }
469
- function useMyPresence() {
470
- const room = useRoom();
471
- const subscribe = room.events.myPresence.subscribe;
472
- const getSnapshot = room.getPresence;
473
- const presence = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
474
- const setPresence = room.updatePresence;
475
- return [presence, setPresence];
476
- }
477
- function useUpdateMyPresence() {
478
- return useRoom().updatePresence;
479
- }
480
- function useOthers(selector, isEqual) {
481
- const room = useRoom();
482
- const subscribe = room.events.others.subscribe;
483
- const getSnapshot = room.getOthers;
484
- const getServerSnapshot = alwaysEmptyList;
485
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
486
- subscribe,
487
- getSnapshot,
488
- getServerSnapshot,
489
- _nullishCoalesce(selector, () => ( identity)),
490
- isEqual
491
- );
492
- }
493
- function useOthersConnectionIds() {
494
- return useOthers(connectionIdSelector, _client.shallow);
495
- }
496
- function useOthersMapped(itemSelector, itemIsEqual) {
497
- const wrappedSelector = React2.useCallback(
498
- (others) => others.map(
499
- (other) => [other.connectionId, itemSelector(other)]
500
- ),
501
- [itemSelector]
502
- );
503
- const wrappedIsEqual = React2.useCallback(
504
- (a, b) => {
505
- const eq = _nullishCoalesce(itemIsEqual, () => ( Object.is));
506
- return a.length === b.length && a.every((atuple, index) => {
507
- const btuple = b[index];
508
- return atuple[0] === btuple[0] && eq(atuple[1], btuple[1]);
509
- });
510
- },
511
- [itemIsEqual]
512
- );
513
- return useOthers(wrappedSelector, wrappedIsEqual);
514
- }
515
- const NOT_FOUND = Symbol();
516
- function useOther(connectionId, selector, isEqual) {
517
- const wrappedSelector = React2.useCallback(
518
- (others) => {
519
- const other2 = others.find(
520
- (other3) => other3.connectionId === connectionId
521
- );
522
- return other2 !== void 0 ? selector(other2) : NOT_FOUND;
523
- },
524
- [connectionId, selector]
525
- );
526
- const wrappedIsEqual = React2.useCallback(
527
- (prev, curr) => {
528
- if (prev === NOT_FOUND || curr === NOT_FOUND) {
529
- return prev === curr;
530
- }
531
- const eq = _nullishCoalesce(isEqual, () => ( Object.is));
532
- return eq(prev, curr);
533
- },
534
- [isEqual]
535
- );
536
- const other = useOthers(wrappedSelector, wrappedIsEqual);
537
- if (other === NOT_FOUND) {
538
- throw new Error(
539
- `No such other user with connection id ${connectionId} exists`
540
- );
541
- }
542
- return other;
543
- }
544
- function useBroadcastEvent() {
545
- const room = useRoom();
546
- return React2.useCallback(
547
- (event, options2 = { shouldQueueEventIfNotReady: false }) => {
548
- room.broadcastEvent(event, options2);
549
- },
550
- [room]
551
- );
552
- }
553
- function useOthersListener(callback) {
554
- const room = useRoom();
555
- const savedCallback = useLatest(callback);
556
- React2.useEffect(
557
- () => room.events.others.subscribe((event) => savedCallback.current(event)),
558
- [room, savedCallback]
559
- );
560
- }
561
- function useLostConnectionListener(callback) {
562
- const room = useRoom();
563
- const savedCallback = useLatest(callback);
564
- React2.useEffect(
565
- () => room.events.lostConnection.subscribe(
566
- (event) => savedCallback.current(event)
567
- ),
568
- [room, savedCallback]
569
- );
570
- }
571
- function useErrorListener(callback) {
572
- const room = useRoom();
573
- const savedCallback = useLatest(callback);
574
- React2.useEffect(
575
- () => room.events.error.subscribe((e) => savedCallback.current(e)),
576
- [room, savedCallback]
577
- );
578
- }
579
- function useEventListener(callback) {
580
- const room = useRoom();
581
- const savedCallback = useLatest(callback);
582
- React2.useEffect(() => {
583
- const listener = (eventData) => {
584
- savedCallback.current(eventData);
585
- };
586
- return room.events.customEvent.subscribe(listener);
587
- }, [room, savedCallback]);
588
- }
589
- function useSelf(maybeSelector, isEqual) {
590
- const room = useRoom();
591
- const subscribe = room.events.self.subscribe;
592
- const getSnapshot = room.getSelf;
593
- const selector = _nullishCoalesce(maybeSelector, () => ( identity));
594
- const wrappedSelector = React2.useCallback(
595
- (me) => me !== null ? selector(me) : null,
596
- [selector]
597
- );
598
- const getServerSnapshot = alwaysNull;
599
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
600
- subscribe,
601
- getSnapshot,
602
- getServerSnapshot,
603
- wrappedSelector,
604
- isEqual
605
- );
606
- }
607
- function useMutableStorageRoot() {
608
- const room = useRoom();
609
- const subscribe = room.events.storageDidLoad.subscribeOnce;
610
- const getSnapshot = room.getStorageSnapshot;
611
- const getServerSnapshot = alwaysNull;
612
- return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
613
- }
614
- function useStorageRoot() {
615
- return [useMutableStorageRoot()];
616
- }
617
- function useHistory() {
618
- return useRoom().history;
619
- }
620
- function useUndo() {
621
- return useHistory().undo;
622
- }
623
- function useRedo() {
624
- return useHistory().redo;
625
- }
626
- function useCanUndo() {
627
- const room = useRoom();
628
- const subscribe = room.events.history.subscribe;
629
- const canUndo = room.history.canUndo;
630
- return useSyncExternalStore(subscribe, canUndo, canUndo);
631
- }
632
- function useCanRedo() {
633
- const room = useRoom();
634
- const subscribe = room.events.history.subscribe;
635
- const canRedo = room.history.canRedo;
636
- return useSyncExternalStore(subscribe, canRedo, canRedo);
637
- }
638
- function useBatch() {
639
- return useRoom().batch;
640
- }
641
- function useLegacyKey(key) {
642
- const room = useRoom();
643
- const rootOrNull = useMutableStorageRoot();
644
- const rerender = useRerender();
645
- React2.useEffect(() => {
646
- if (rootOrNull === null) {
647
- return;
648
- }
649
- const root = rootOrNull;
650
- let unsubCurr;
651
- let curr = root.get(key);
652
- function subscribeToCurr() {
653
- unsubCurr = _core.isLiveNode.call(void 0, curr) ? room.subscribe(curr, rerender) : void 0;
654
- }
655
- function onRootChange() {
656
- const newValue = root.get(key);
657
- if (newValue !== curr) {
658
- _optionalChain([unsubCurr, 'optionalCall', _3 => _3()]);
659
- curr = newValue;
660
- subscribeToCurr();
661
- rerender();
662
- }
663
- }
664
- subscribeToCurr();
665
- rerender();
666
- const unsubscribeRoot = room.subscribe(root, onRootChange);
667
- return () => {
668
- unsubscribeRoot();
669
- _optionalChain([unsubCurr, 'optionalCall', _4 => _4()]);
670
- };
671
- }, [rootOrNull, room, key, rerender]);
672
- if (rootOrNull === null) {
673
- return null;
674
- } else {
675
- return rootOrNull.get(key);
676
- }
677
- }
678
- function useStorage(selector, isEqual) {
679
- const room = useRoom();
680
- const rootOrNull = useMutableStorageRoot();
681
- const wrappedSelector = React2.useCallback(
682
- (rootOrNull2) => rootOrNull2 !== null ? selector(rootOrNull2) : null,
683
- [selector]
684
- );
685
- const subscribe = React2.useCallback(
686
- (onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) : noop,
687
- [room, rootOrNull]
688
- );
689
- const getSnapshot = React2.useCallback(() => {
690
- if (rootOrNull === null) {
691
- return null;
692
- } else {
693
- const root = rootOrNull;
694
- const imm = root.toImmutable();
695
- return imm;
696
- }
697
- }, [rootOrNull]);
698
- const getServerSnapshot = alwaysNull;
699
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
700
- subscribe,
701
- getSnapshot,
702
- getServerSnapshot,
703
- wrappedSelector,
704
- isEqual
705
- );
706
- }
707
- function ensureNotServerSide() {
708
- if (typeof window === "undefined") {
709
- throw new Error(
710
- "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"
711
- );
712
- }
713
- }
714
- function useSuspendUntilStorageLoaded() {
715
- const room = useRoom();
716
- if (room.getStorageSnapshot() !== null) {
717
- return;
718
- }
719
- ensureNotServerSide();
720
- throw new Promise((res) => {
721
- room.events.storageDidLoad.subscribeOnce(() => res());
722
- });
723
- }
724
- function useSuspendUntilPresenceLoaded() {
725
- const room = useRoom();
726
- if (room.getSelf() !== null) {
727
- return;
728
- }
729
- ensureNotServerSide();
730
- throw new Promise((res) => {
731
- room.events.self.subscribeOnce(() => res());
732
- room.events.status.subscribeOnce(() => res());
733
- });
734
- }
735
- function useMutation(callback, deps) {
736
- const room = useRoom();
737
- return React2.useMemo(
738
- () => {
739
- return (...args) => (
740
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
741
- room.batch(
742
- () => (
743
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
744
- callback(
745
- makeMutationContext(room),
746
- ...args
747
- )
748
- )
749
- )
750
- );
751
- },
752
- // eslint-disable-next-line react-hooks/exhaustive-deps
753
- [room, ...deps]
754
- );
755
- }
756
- function useStorageSuspense(selector, isEqual) {
757
- useSuspendUntilStorageLoaded();
758
- return useStorage(
759
- selector,
760
- isEqual
761
- );
762
- }
763
- function useSelfSuspense(selector, isEqual) {
764
- useSuspendUntilPresenceLoaded();
765
- return useSelf(
766
- selector,
767
- isEqual
768
- );
769
- }
770
- function useOthersSuspense(selector, isEqual) {
771
- useSuspendUntilPresenceLoaded();
772
- return useOthers(
773
- selector,
774
- isEqual
775
- );
776
- }
777
- function useOthersConnectionIdsSuspense() {
778
- useSuspendUntilPresenceLoaded();
779
- return useOthersConnectionIds();
780
- }
781
- function useOthersMappedSuspense(itemSelector, itemIsEqual) {
782
- useSuspendUntilPresenceLoaded();
783
- return useOthersMapped(itemSelector, itemIsEqual);
784
- }
785
- function useOtherSuspense(connectionId, selector, isEqual) {
786
- useSuspendUntilPresenceLoaded();
787
- return useOther(connectionId, selector, isEqual);
788
- }
789
- function useLegacyKeySuspense(key) {
790
- useSuspendUntilStorageLoaded();
791
- return useLegacyKey(key);
792
- }
793
- const store = client[_core.kInternal].cacheStore;
794
- function onMutationFailure(innerError, optimisticUpdateId, createPublicError) {
795
- store.set((state) => ({
796
- ...state,
797
- optimisticUpdates: state.optimisticUpdates.filter(
798
- (update) => update.id !== optimisticUpdateId
799
- )
800
- }));
801
- if (innerError instanceof _core.CommentsApiError) {
802
- const error = handleApiError(innerError);
803
- commentsErrorEventSource.notify(createPublicError(error));
804
- return;
805
- }
806
- if (innerError instanceof _core.NotificationsApiError) {
807
- handleApiError(innerError);
808
- return;
809
- }
810
- throw innerError;
811
- }
812
- const subscribersByQuery = /* @__PURE__ */ new Map();
813
- const requestsByQuery = /* @__PURE__ */ new Map();
814
- const poller = _core.makePoller.call(void 0, refreshThreadsAndNotifications);
815
- async function refreshThreadsAndNotifications() {
816
- const requests = [];
817
- client[_core.kInternal].getRoomIds().map((roomId) => {
818
- const room = client.getRoom(roomId);
819
- if (room === null)
820
- return;
821
- requests.push(getThreadsUpdates(room.id));
822
- });
823
- await Promise.allSettled(requests);
824
- }
825
- function incrementQuerySubscribers(queryKey) {
826
- const subscribers = _nullishCoalesce(subscribersByQuery.get(queryKey), () => ( 0));
827
- subscribersByQuery.set(queryKey, subscribers + 1);
828
- poller.start(POLLING_INTERVAL);
829
- }
830
- function decrementQuerySubscribers(queryKey) {
831
- const subscribers = subscribersByQuery.get(queryKey);
832
- if (subscribers === void 0 || subscribers <= 0) {
833
- _core.console.warn(
834
- `Internal unexpected behavior. Cannot decrease subscriber count for query "${queryKey}"`
835
- );
836
- return;
837
- }
838
- subscribersByQuery.set(queryKey, subscribers - 1);
839
- let totalSubscribers = 0;
840
- for (const subscribers2 of subscribersByQuery.values()) {
841
- totalSubscribers += subscribers2;
842
- }
843
- if (totalSubscribers <= 0) {
844
- poller.stop();
845
- }
846
- }
847
- async function getThreadsAndInboxNotifications(room, queryKey, options2, { retryCount } = { retryCount: 0 }) {
848
- const existingRequest = requestsByQuery.get(queryKey);
849
- if (existingRequest !== void 0)
850
- return existingRequest;
851
- const request = room[_core.kInternal].comments.getThreads(options2);
852
- requestsByQuery.set(queryKey, request);
853
- store.setQueryState(queryKey, {
854
- isLoading: true
855
- });
856
- try {
857
- const result = await request;
858
- store.updateThreadsAndNotifications(
859
- result.threads,
860
- result.inboxNotifications,
861
- result.deletedThreads,
862
- result.deletedInboxNotifications,
863
- queryKey
864
- );
865
- const lastRequestedAt = lastRequestedAtByRoom.get(room.id);
866
- if (lastRequestedAt === void 0 || lastRequestedAt > result.meta.requestedAt) {
867
- lastRequestedAtByRoom.set(room.id, result.meta.requestedAt);
868
- }
869
- poller.start(POLLING_INTERVAL);
870
- } catch (err) {
871
- requestsByQuery.delete(queryKey);
872
- retryError(() => {
873
- void getThreadsAndInboxNotifications(room, queryKey, options2, {
874
- retryCount: retryCount + 1
875
- });
876
- }, retryCount);
877
- store.setQueryState(queryKey, {
878
- isLoading: false,
879
- error: err
880
- });
881
- return;
882
- }
883
- }
884
- const DEFAULT_DEDUPING_INTERVAL = 2e3;
885
- const lastRequestedAtByRoom = /* @__PURE__ */ new Map();
886
- const requestStatusByRoom = /* @__PURE__ */ new Map();
887
- async function getThreadsUpdates(roomId) {
888
- const room = client.getRoom(roomId);
889
- if (room === null)
890
- return;
891
- const since = lastRequestedAtByRoom.get(room.id);
892
- if (since === void 0)
893
- return;
894
- const isFetchingThreadsUpdates = _nullishCoalesce(requestStatusByRoom.get(room.id), () => ( false));
895
- if (isFetchingThreadsUpdates === true)
896
- return;
897
- try {
898
- requestStatusByRoom.set(room.id, true);
899
- const updates = await room[_core.kInternal].comments.getThreads({ since });
900
- setTimeout(() => {
901
- requestStatusByRoom.set(room.id, false);
902
- }, DEFAULT_DEDUPING_INTERVAL);
903
- store.updateThreadsAndNotifications(
904
- updates.threads,
905
- updates.inboxNotifications,
906
- updates.deletedThreads,
907
- updates.deletedInboxNotifications
908
- );
909
- lastRequestedAtByRoom.set(room.id, updates.meta.requestedAt);
910
- } catch (err) {
911
- requestStatusByRoom.set(room.id, false);
912
- return;
913
- }
914
- }
915
- function handleScrollToCommentOnLoad(isQueryLoading, shouldScrollOnLoad, state) {
916
- if (shouldScrollOnLoad === false)
917
- return;
918
- if (isQueryLoading === true)
919
- return;
920
- const isWindowDefined = typeof window !== "undefined";
921
- if (!isWindowDefined)
922
- return;
923
- const hash = window.location.hash;
924
- const commentId = hash.slice(1);
925
- if (!commentId.startsWith("cm_"))
926
- return;
927
- const comment = document.getElementById(commentId);
928
- if (comment === null)
929
- return;
930
- const comments = state.threads.flatMap((thread) => thread.comments);
931
- const isCommentInThreads = comments.some(
932
- (comment2) => comment2.id === commentId
933
- );
934
- if (!isCommentInThreads)
935
- return;
936
- comment.scrollIntoView();
937
- }
938
- function useThreads(options2 = {
939
- query: { metadata: {} }
940
- }) {
941
- const { scrollOnLoad = true } = options2;
942
- const room = useRoom();
943
- const queryKey = React2.useMemo(
944
- () => generateQueryKey(room.id, options2.query),
945
- [room, options2]
946
- );
947
- React2.useEffect(() => {
948
- void getThreadsAndInboxNotifications(room, queryKey, options2);
949
- incrementQuerySubscribers(queryKey);
950
- return () => decrementQuerySubscribers(queryKey);
951
- }, [room, queryKey]);
952
- const selector = React2.useCallback(
953
- (state2) => {
954
- const query = state2.queries[queryKey];
955
- if (query === void 0 || query.isLoading) {
956
- return {
957
- isLoading: true
958
- };
959
- }
960
- return {
961
- threads: selectedThreads(room.id, state2, options2),
962
- isLoading: false,
963
- error: query.error
964
- };
965
- },
966
- [room, queryKey]
967
- // eslint-disable-line react-hooks/exhaustive-deps
968
- );
969
- const state = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
970
- store.subscribe,
971
- store.get,
972
- store.get,
973
- selector
974
- );
975
- React2.useEffect(
976
- () => {
977
- if (state.isLoading === true)
978
- return;
979
- handleScrollToCommentOnLoad(state.isLoading, scrollOnLoad, state);
980
- },
981
- // eslint-disable-next-line react-hooks/exhaustive-deps -- We only want to run this effect once
982
- [state.isLoading]
983
- );
984
- return state;
985
- }
986
- function useThreadsSuspense(options2 = {
987
- query: { metadata: {} }
988
- }) {
989
- const { scrollOnLoad = true } = options2;
990
- const room = useRoom();
991
- const queryKey = React2.useMemo(
992
- () => generateQueryKey(room.id, options2.query),
993
- [room, options2]
994
- );
995
- const query = store.get().queries[queryKey];
996
- if (query === void 0 || query.isLoading) {
997
- throw getThreadsAndInboxNotifications(room, queryKey, options2);
998
- }
999
- if (query.error) {
1000
- throw query.error;
1001
- }
1002
- const selector = React2.useCallback(
1003
- (state2) => {
1004
- return {
1005
- threads: selectedThreads(room.id, state2, options2),
1006
- isLoading: false
1007
- };
1008
- },
1009
- [room, queryKey]
1010
- // eslint-disable-line react-hooks/exhaustive-deps
1011
- );
1012
- React2.useEffect(() => {
1013
- incrementQuerySubscribers(queryKey);
1014
- return () => {
1015
- decrementQuerySubscribers(queryKey);
1016
- };
1017
- }, [queryKey]);
1018
- const state = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1019
- store.subscribe,
1020
- store.get,
1021
- store.get,
1022
- selector
1023
- );
1024
- React2.useEffect(
1025
- () => {
1026
- handleScrollToCommentOnLoad(state.isLoading, scrollOnLoad, state);
1027
- },
1028
- // eslint-disable-next-line react-hooks/exhaustive-deps -- We only want to run this effect once
1029
- [state.isLoading]
1030
- );
1031
- return state;
1032
- }
1033
- function useCreateThread() {
1034
- const room = useRoom();
1035
- return React2.useCallback(
1036
- (options2) => {
1037
- const body = options2.body;
1038
- const metadata = "metadata" in options2 ? options2.metadata : {};
1039
- const threadId = createThreadId();
1040
- const commentId = createCommentId();
1041
- const createdAt = /* @__PURE__ */ new Date();
1042
- const newComment = {
1043
- id: commentId,
1044
- threadId,
1045
- roomId: room.id,
1046
- createdAt,
1047
- type: "comment",
1048
- userId: getCurrentUserId(room),
1049
- body,
1050
- reactions: []
1051
- };
1052
- const newThread = {
1053
- id: threadId,
1054
- type: "thread",
1055
- createdAt,
1056
- updatedAt: createdAt,
1057
- roomId: room.id,
1058
- metadata,
1059
- comments: [newComment]
1060
- };
1061
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1062
- store.pushOptimisticUpdate({
1063
- type: "create-thread",
1064
- thread: newThread,
1065
- id: optimisticUpdateId
1066
- });
1067
- room[_core.kInternal].comments.createThread({ threadId, commentId, body, metadata }).then(
1068
- (thread) => {
1069
- store.set((state) => ({
1070
- ...state,
1071
- threads: {
1072
- ...state.threads,
1073
- [threadId]: thread
1074
- },
1075
- optimisticUpdates: state.optimisticUpdates.filter(
1076
- (update) => update.id !== optimisticUpdateId
1077
- )
1078
- }));
1079
- },
1080
- (err) => onMutationFailure(
1081
- err,
1082
- optimisticUpdateId,
1083
- (err2) => new CreateThreadError(err2, {
1084
- roomId: room.id,
1085
- threadId,
1086
- commentId,
1087
- body,
1088
- metadata
1089
- })
1090
- )
1091
- );
1092
- return newThread;
1093
- },
1094
- [room]
1095
- );
1096
- }
1097
- function useEditThreadMetadata() {
1098
- const room = useRoom();
1099
- return React2.useCallback(
1100
- (options2) => {
1101
- if (!("metadata" in options2)) {
1102
- return;
1103
- }
1104
- const threadId = options2.threadId;
1105
- const metadata = options2.metadata;
1106
- const updatedAt = /* @__PURE__ */ new Date();
1107
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1108
- store.pushOptimisticUpdate({
1109
- type: "edit-thread-metadata",
1110
- metadata,
1111
- id: optimisticUpdateId,
1112
- threadId,
1113
- updatedAt
1114
- });
1115
- room[_core.kInternal].comments.editThreadMetadata({ metadata, threadId }).then(
1116
- (metadata2) => {
1117
- store.set((state) => {
1118
- const existingThread = state.threads[threadId];
1119
- const updatedOptimisticUpdates = state.optimisticUpdates.filter(
1120
- (update) => update.id !== optimisticUpdateId
1121
- );
1122
- if (existingThread === void 0) {
1123
- return {
1124
- ...state,
1125
- optimisticUpdates: updatedOptimisticUpdates
1126
- };
1127
- }
1128
- if (existingThread.deletedAt !== void 0) {
1129
- return {
1130
- ...state,
1131
- optimisticUpdates: updatedOptimisticUpdates
1132
- };
1133
- }
1134
- if (existingThread.updatedAt && existingThread.updatedAt > updatedAt) {
1135
- return {
1136
- ...state,
1137
- optimisticUpdates: updatedOptimisticUpdates
1138
- };
1139
- }
1140
- return {
1141
- ...state,
1142
- threads: {
1143
- ...state.threads,
1144
- [threadId]: {
1145
- ...existingThread,
1146
- metadata: metadata2
1147
- }
1148
- },
1149
- optimisticUpdates: updatedOptimisticUpdates
1150
- };
1151
- });
1152
- },
1153
- (err) => onMutationFailure(
1154
- err,
1155
- optimisticUpdateId,
1156
- (error) => new EditThreadMetadataError(error, {
1157
- roomId: room.id,
1158
- threadId,
1159
- metadata
1160
- })
1161
- )
1162
- );
1163
- },
1164
- [room]
1165
- );
1166
- }
1167
- function useAddReaction() {
1168
- const room = useRoom();
1169
- return React2.useCallback(
1170
- ({ threadId, commentId, emoji }) => {
1171
- const createdAt = /* @__PURE__ */ new Date();
1172
- const userId = getCurrentUserId(room);
1173
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1174
- store.pushOptimisticUpdate({
1175
- type: "add-reaction",
1176
- threadId,
1177
- commentId,
1178
- reaction: {
1179
- emoji,
1180
- userId,
1181
- createdAt
1182
- },
1183
- id: optimisticUpdateId
1184
- });
1185
- room[_core.kInternal].comments.addReaction({ threadId, commentId, emoji }).then(
1186
- (addedReaction) => {
1187
- store.set((state) => {
1188
- const existingThread = state.threads[threadId];
1189
- const updatedOptimisticUpdates = state.optimisticUpdates.filter(
1190
- (update) => update.id !== optimisticUpdateId
1191
- );
1192
- if (existingThread === void 0) {
1193
- return {
1194
- ...state,
1195
- optimisticUpdates: updatedOptimisticUpdates
1196
- };
1197
- }
1198
- return {
1199
- ...state,
1200
- threads: {
1201
- ...state.threads,
1202
- [threadId]: _core.addReaction.call(void 0,
1203
- existingThread,
1204
- commentId,
1205
- addedReaction
1206
- )
1207
- },
1208
- optimisticUpdates: updatedOptimisticUpdates
1209
- };
1210
- });
1211
- },
1212
- (err) => onMutationFailure(
1213
- err,
1214
- optimisticUpdateId,
1215
- (error) => new AddReactionError(error, {
1216
- roomId: room.id,
1217
- threadId,
1218
- commentId,
1219
- emoji
1220
- })
1221
- )
1222
- );
1223
- },
1224
- [room]
1225
- );
1226
- }
1227
- function useRemoveReaction() {
1228
- const room = useRoom();
1229
- return React2.useCallback(
1230
- ({ threadId, commentId, emoji }) => {
1231
- const userId = getCurrentUserId(room);
1232
- const removedAt = /* @__PURE__ */ new Date();
1233
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1234
- store.pushOptimisticUpdate({
1235
- type: "remove-reaction",
1236
- threadId,
1237
- commentId,
1238
- emoji,
1239
- userId,
1240
- removedAt,
1241
- id: optimisticUpdateId
1242
- });
1243
- room[_core.kInternal].comments.removeReaction({ threadId, commentId, emoji }).then(
1244
- () => {
1245
- store.set((state) => {
1246
- const existingThread = state.threads[threadId];
1247
- const updatedOptimisticUpdates = state.optimisticUpdates.filter(
1248
- (update) => update.id !== optimisticUpdateId
1249
- );
1250
- if (existingThread === void 0) {
1251
- return {
1252
- ...state,
1253
- optimisticUpdates: updatedOptimisticUpdates
1254
- };
1255
- }
1256
- return {
1257
- ...state,
1258
- threads: {
1259
- ...state.threads,
1260
- [threadId]: _core.removeReaction.call(void 0,
1261
- existingThread,
1262
- commentId,
1263
- emoji,
1264
- userId,
1265
- removedAt
1266
- )
1267
- },
1268
- optimisticUpdates: updatedOptimisticUpdates
1269
- };
1270
- });
1271
- },
1272
- (err) => onMutationFailure(
1273
- err,
1274
- optimisticUpdateId,
1275
- (error) => new RemoveReactionError(error, {
1276
- roomId: room.id,
1277
- threadId,
1278
- commentId,
1279
- emoji
1280
- })
1281
- )
1282
- );
1283
- },
1284
- [room]
1285
- );
1286
- }
1287
- function useCreateComment() {
1288
- const room = useRoom();
1289
- return React2.useCallback(
1290
- ({ threadId, body }) => {
1291
- const commentId = createCommentId();
1292
- const createdAt = /* @__PURE__ */ new Date();
1293
- const comment = {
1294
- id: commentId,
1295
- threadId,
1296
- roomId: room.id,
1297
- type: "comment",
1298
- createdAt,
1299
- userId: getCurrentUserId(room),
1300
- body,
1301
- reactions: []
1302
- };
1303
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1304
- store.pushOptimisticUpdate({
1305
- type: "create-comment",
1306
- comment,
1307
- id: optimisticUpdateId
1308
- });
1309
- room[_core.kInternal].comments.createComment({ threadId, commentId, body }).then(
1310
- (newComment) => {
1311
- store.set((state) => {
1312
- const existingThread = state.threads[threadId];
1313
- const updatedOptimisticUpdates = state.optimisticUpdates.filter(
1314
- (update) => update.id !== optimisticUpdateId
1315
- );
1316
- if (existingThread === void 0) {
1317
- return {
1318
- ...state,
1319
- optimisticUpdates: updatedOptimisticUpdates
1320
- };
1321
- }
1322
- const inboxNotification = Object.values(
1323
- state.inboxNotifications
1324
- ).find(
1325
- (notification) => notification.kind === "thread" && notification.threadId === threadId
1326
- );
1327
- const updatedInboxNotifications = inboxNotification !== void 0 ? {
1328
- ...state.inboxNotifications,
1329
- [inboxNotification.id]: {
1330
- ...inboxNotification,
1331
- notifiedAt: newComment.createdAt,
1332
- readAt: newComment.createdAt
1333
- }
1334
- } : state.inboxNotifications;
1335
- return {
1336
- ...state,
1337
- threads: {
1338
- ...state.threads,
1339
- [threadId]: _core.upsertComment.call(void 0, existingThread, newComment)
1340
- // Upsert the new comment into the thread comments list (if applicable)
1341
- },
1342
- inboxNotifications: updatedInboxNotifications,
1343
- optimisticUpdates: updatedOptimisticUpdates
1344
- };
1345
- });
1346
- },
1347
- (err) => onMutationFailure(
1348
- err,
1349
- optimisticUpdateId,
1350
- (err2) => new CreateCommentError(err2, {
1351
- roomId: room.id,
1352
- threadId,
1353
- commentId,
1354
- body
1355
- })
1356
- )
1357
- );
1358
- return comment;
1359
- },
1360
- [room]
1361
- );
1362
- }
1363
- function useEditComment() {
1364
- const room = useRoom();
1365
- return React2.useCallback(
1366
- ({ threadId, commentId, body }) => {
1367
- const editedAt = /* @__PURE__ */ new Date();
1368
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1369
- const thread = store.get().threads[threadId];
1370
- if (thread === void 0) {
1371
- _core.console.warn(
1372
- `Internal unexpected behavior. Cannot edit comment in thread "${threadId}" because the thread does not exist in the cache.`
1373
- );
1374
- return;
1375
- }
1376
- const comment = thread.comments.find(
1377
- (comment2) => comment2.id === commentId
1378
- );
1379
- if (comment === void 0 || comment.deletedAt !== void 0) {
1380
- _core.console.warn(
1381
- `Internal unexpected behavior. Cannot edit comment "${commentId}" in thread "${threadId}" because the comment does not exist in the cache.`
1382
- );
1383
- return;
1384
- }
1385
- store.pushOptimisticUpdate({
1386
- type: "edit-comment",
1387
- comment: {
1388
- ...comment,
1389
- editedAt,
1390
- body
1391
- },
1392
- id: optimisticUpdateId
1393
- });
1394
- room[_core.kInternal].comments.editComment({ threadId, commentId, body }).then(
1395
- (editedComment) => {
1396
- store.set((state) => {
1397
- const existingThread = state.threads[threadId];
1398
- const updatedOptimisticUpdates = state.optimisticUpdates.filter(
1399
- (update) => update.id !== optimisticUpdateId
1400
- );
1401
- if (existingThread === void 0) {
1402
- return {
1403
- ...state,
1404
- optimisticUpdates: updatedOptimisticUpdates
1405
- };
1406
- }
1407
- return {
1408
- ...state,
1409
- threads: {
1410
- ...state.threads,
1411
- [threadId]: _core.upsertComment.call(void 0, existingThread, editedComment)
1412
- // Upsert the edited comment into the thread comments list (if applicable)
1413
- },
1414
- optimisticUpdates: updatedOptimisticUpdates
1415
- };
1416
- });
1417
- },
1418
- (err) => onMutationFailure(
1419
- err,
1420
- optimisticUpdateId,
1421
- (error) => new EditCommentError(error, {
1422
- roomId: room.id,
1423
- threadId,
1424
- commentId,
1425
- body
1426
- })
1427
- )
1428
- );
1429
- },
1430
- [room]
1431
- );
1432
- }
1433
- function useDeleteComment() {
1434
- const room = useRoom();
1435
- return React2.useCallback(
1436
- ({ threadId, commentId }) => {
1437
- const deletedAt = /* @__PURE__ */ new Date();
1438
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1439
- store.pushOptimisticUpdate({
1440
- type: "delete-comment",
1441
- threadId,
1442
- commentId,
1443
- deletedAt,
1444
- id: optimisticUpdateId
1445
- });
1446
- room[_core.kInternal].comments.deleteComment({ threadId, commentId }).then(
1447
- () => {
1448
- store.set((state) => {
1449
- const existingThread = state.threads[threadId];
1450
- const updatedOptimisticUpdates = state.optimisticUpdates.filter(
1451
- (update) => update.id !== optimisticUpdateId
1452
- );
1453
- if (existingThread === void 0) {
1454
- return {
1455
- ...state,
1456
- optimisticUpdates: updatedOptimisticUpdates
1457
- };
1458
- }
1459
- return {
1460
- ...state,
1461
- threads: {
1462
- ...state.threads,
1463
- [threadId]: _core.deleteComment.call(void 0,
1464
- existingThread,
1465
- commentId,
1466
- deletedAt
1467
- )
1468
- },
1469
- optimisticUpdates: updatedOptimisticUpdates
1470
- };
1471
- });
1472
- },
1473
- (err) => onMutationFailure(
1474
- err,
1475
- optimisticUpdateId,
1476
- (error) => new DeleteCommentError(error, {
1477
- roomId: room.id,
1478
- threadId,
1479
- commentId
1480
- })
1481
- )
1482
- );
1483
- },
1484
- [room]
1485
- );
1486
- }
1487
- const resolveMentionSuggestions = client[_core.kInternal].resolveMentionSuggestions;
1488
- const mentionSuggestionsCache = /* @__PURE__ */ new Map();
1489
- function useMentionSuggestions(search) {
1490
- const room = useRoom();
1491
- const [mentionSuggestions, setMentionSuggestions] = React2.useState();
1492
- const lastInvokedAt = React2.useRef();
1493
- React2.useEffect(() => {
1494
- if (search === void 0 || !resolveMentionSuggestions) {
1495
- return;
1496
- }
1497
- const resolveMentionSuggestionsArgs = { text: search, roomId: room.id };
1498
- const mentionSuggestionsCacheKey = _core.stringify.call(void 0,
1499
- resolveMentionSuggestionsArgs
1500
- );
1501
- let debounceTimeout;
1502
- let isCanceled = false;
1503
- const getMentionSuggestions = async () => {
1504
- try {
1505
- lastInvokedAt.current = performance.now();
1506
- const mentionSuggestions2 = await resolveMentionSuggestions(
1507
- resolveMentionSuggestionsArgs
1508
- );
1509
- if (!isCanceled) {
1510
- setMentionSuggestions(mentionSuggestions2);
1511
- mentionSuggestionsCache.set(
1512
- mentionSuggestionsCacheKey,
1513
- mentionSuggestions2
1514
- );
1515
- }
1516
- } catch (error) {
1517
- _core.console.error(_optionalChain([error, 'optionalAccess', _5 => _5.message]));
1518
- }
1519
- };
1520
- if (mentionSuggestionsCache.has(mentionSuggestionsCacheKey)) {
1521
- setMentionSuggestions(
1522
- mentionSuggestionsCache.get(mentionSuggestionsCacheKey)
1523
- );
1524
- } else if (!lastInvokedAt.current || Math.abs(performance.now() - lastInvokedAt.current) > MENTION_SUGGESTIONS_DEBOUNCE) {
1525
- void getMentionSuggestions();
1526
- } else {
1527
- debounceTimeout = window.setTimeout(() => {
1528
- void getMentionSuggestions();
1529
- }, MENTION_SUGGESTIONS_DEBOUNCE);
1530
- }
1531
- return () => {
1532
- isCanceled = true;
1533
- window.clearTimeout(debounceTimeout);
1534
- };
1535
- }, [room.id, search]);
1536
- return mentionSuggestions;
1537
- }
1538
- function useThreadSubscription(threadId) {
1539
- const selector = React2.useCallback(
1540
- (state) => {
1541
- const inboxNotification = selectedInboxNotifications(state).find(
1542
- (inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
1543
- );
1544
- const thread = state.threads[threadId];
1545
- if (inboxNotification === void 0 || thread === void 0) {
1546
- return {
1547
- status: "not-subscribed"
1548
- };
1549
- }
1550
- return {
1551
- status: "subscribed",
1552
- unreadSince: inboxNotification.readAt
1553
- };
1554
- },
1555
- [threadId]
1556
- );
1557
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1558
- store.subscribe,
1559
- store.get,
1560
- store.get,
1561
- selector
1562
- );
1563
- }
1564
- function useMarkThreadAsRead() {
1565
- const room = useRoom();
1566
- return React2.useCallback(
1567
- (threadId) => {
1568
- const inboxNotification = Object.values(
1569
- store.get().inboxNotifications
1570
- ).find(
1571
- (inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
1572
- );
1573
- if (!inboxNotification)
1574
- return;
1575
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1576
- const now = /* @__PURE__ */ new Date();
1577
- store.pushOptimisticUpdate({
1578
- type: "mark-inbox-notification-as-read",
1579
- id: optimisticUpdateId,
1580
- inboxNotificationId: inboxNotification.id,
1581
- readAt: now
1582
- });
1583
- room[_core.kInternal].notifications.markInboxNotificationAsRead(inboxNotification.id).then(
1584
- () => {
1585
- store.set((state) => ({
1586
- ...state,
1587
- inboxNotifications: {
1588
- ...state.inboxNotifications,
1589
- [inboxNotification.id]: {
1590
- ...inboxNotification,
1591
- readAt: now
1592
- }
1593
- },
1594
- optimisticUpdates: state.optimisticUpdates.filter(
1595
- (update) => update.id !== optimisticUpdateId
1596
- )
1597
- }));
1598
- },
1599
- (err) => {
1600
- onMutationFailure(
1601
- err,
1602
- optimisticUpdateId,
1603
- (error) => new MarkInboxNotificationAsReadError(error, {
1604
- inboxNotificationId: inboxNotification.id
1605
- })
1606
- );
1607
- return;
1608
- }
1609
- );
1610
- },
1611
- [room]
1612
- );
1613
- }
1614
- function makeNotificationSettingsQueryKey(roomId) {
1615
- return `${roomId}:NOTIFICATION_SETTINGS`;
1616
- }
1617
- async function getInboxNotificationSettings(room, queryKey, { retryCount } = { retryCount: 0 }) {
1618
- const existingRequest = requestsByQuery.get(queryKey);
1619
- if (existingRequest !== void 0)
1620
- return existingRequest;
1621
- try {
1622
- const request = room[_core.kInternal].notifications.getRoomNotificationSettings();
1623
- requestsByQuery.set(queryKey, request);
1624
- store.setQueryState(queryKey, {
1625
- isLoading: true
1626
- });
1627
- const settings = await request;
1628
- store.updateRoomInboxNotificationSettings(room.id, settings, queryKey);
1629
- } catch (err) {
1630
- requestsByQuery.delete(queryKey);
1631
- retryError(() => {
1632
- void getInboxNotificationSettings(room, queryKey, {
1633
- retryCount: retryCount + 1
1634
- });
1635
- }, retryCount);
1636
- store.setQueryState(queryKey, {
1637
- isLoading: false,
1638
- error: err
1639
- });
1640
- return;
1641
- }
1642
- }
1643
- function useRoomNotificationSettings() {
1644
- const room = useRoom();
1645
- React2.useEffect(() => {
1646
- const queryKey = makeNotificationSettingsQueryKey(room.id);
1647
- void getInboxNotificationSettings(room, queryKey);
1648
- }, [room]);
1649
- const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
1650
- const selector = React2.useCallback(
1651
- (state) => {
1652
- const query = state.queries[makeNotificationSettingsQueryKey(room.id)];
1653
- if (query === void 0 || query.isLoading) {
1654
- return { isLoading: true };
1655
- }
1656
- if (query.error !== void 0) {
1657
- return { isLoading: false, error: query.error };
1658
- }
1659
- return {
1660
- isLoading: false,
1661
- settings: selectNotificationSettings(room.id, state)
1662
- };
1663
- },
1664
- [room]
1665
- );
1666
- const settings = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1667
- store.subscribe,
1668
- store.get,
1669
- store.get,
1670
- selector
1671
- );
1672
- return React2.useMemo(() => {
1673
- return [settings, updateRoomNotificationSettings];
1674
- }, [settings, updateRoomNotificationSettings]);
1675
- }
1676
- function useRoomNotificationSettingsSuspense() {
1677
- const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
1678
- const room = useRoom();
1679
- const queryKey = makeNotificationSettingsQueryKey(room.id);
1680
- const query = store.get().queries[queryKey];
1681
- if (query === void 0 || query.isLoading) {
1682
- throw getInboxNotificationSettings(room, queryKey);
1683
- }
1684
- if (query.error) {
1685
- throw query.error;
1686
- }
1687
- const selector = React2.useCallback(
1688
- (state) => {
1689
- return {
1690
- isLoading: false,
1691
- settings: selectNotificationSettings(room.id, state)
1692
- };
1693
- },
1694
- [room]
1695
- );
1696
- const settings = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
1697
- store.subscribe,
1698
- store.get,
1699
- store.get,
1700
- selector
1701
- );
1702
- return React2.useMemo(() => {
1703
- return [settings, updateRoomNotificationSettings];
1704
- }, [settings, updateRoomNotificationSettings]);
1705
- }
1706
- function useUpdateRoomNotificationSettings() {
1707
- const room = useRoom();
1708
- return React2.useCallback(
1709
- (settings) => {
1710
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
1711
- store.pushOptimisticUpdate({
1712
- id: optimisticUpdateId,
1713
- type: "update-notification-settings",
1714
- roomId: room.id,
1715
- settings
1716
- });
1717
- room[_core.kInternal].notifications.updateRoomNotificationSettings(settings).then(
1718
- (settings2) => {
1719
- store.set((state) => ({
1720
- ...state,
1721
- notificationSettings: {
1722
- [room.id]: settings2
1723
- },
1724
- optimisticUpdates: state.optimisticUpdates.filter(
1725
- (update) => update.id !== optimisticUpdateId
1726
- )
1727
- }));
1728
- },
1729
- (err) => onMutationFailure(
1730
- err,
1731
- optimisticUpdateId,
1732
- (error) => new UpdateNotificationSettingsError(error, {
1733
- roomId: room.id
1734
- })
1735
- )
1736
- );
1737
- },
1738
- [room]
1739
- );
1740
- }
1741
- function useCurrentUserId() {
1742
- return useSelf((user) => typeof user.id === "string" ? user.id : null);
1743
- }
1744
- const bundle = {
1745
- RoomContext,
1746
- RoomProvider: RoomProviderOuter,
1747
- useRoom,
1748
- useStatus,
1749
- useBatch,
1750
- useBroadcastEvent,
1751
- useOthersListener,
1752
- useLostConnectionListener,
1753
- useErrorListener,
1754
- useEventListener,
1755
- useHistory,
1756
- useUndo,
1757
- useRedo,
1758
- useCanRedo,
1759
- useCanUndo,
1760
- // These are just aliases. The passed-in key will define their return values.
1761
- useList: useLegacyKey,
1762
- useMap: useLegacyKey,
1763
- useObject: useLegacyKey,
1764
- useStorageRoot,
1765
- useStorage,
1766
- useSelf,
1767
- useMyPresence,
1768
- useUpdateMyPresence,
1769
- useOthers,
1770
- useOthersMapped,
1771
- useOthersConnectionIds,
1772
- useOther,
1773
- useMutation,
1774
- useThreads,
1775
- useCreateThread,
1776
- useEditThreadMetadata,
1777
- useCreateComment,
1778
- useEditComment,
1779
- useDeleteComment,
1780
- useAddReaction,
1781
- useRemoveReaction,
1782
- useMarkThreadAsRead,
1783
- useThreadSubscription,
1784
- useRoomNotificationSettings,
1785
- useUpdateRoomNotificationSettings,
1786
- ...shared,
1787
- suspense: {
1788
- RoomContext,
1789
- RoomProvider: RoomProviderOuter,
1790
- useRoom,
1791
- useStatus,
1792
- useBatch,
1793
- useBroadcastEvent,
1794
- useOthersListener,
1795
- useLostConnectionListener,
1796
- useErrorListener,
1797
- useEventListener,
1798
- useHistory,
1799
- useUndo,
1800
- useRedo,
1801
- useCanRedo,
1802
- useCanUndo,
1803
- // Legacy hooks
1804
- useList: useLegacyKeySuspense,
1805
- useMap: useLegacyKeySuspense,
1806
- useObject: useLegacyKeySuspense,
1807
- useStorageRoot,
1808
- useStorage: useStorageSuspense,
1809
- useSelf: useSelfSuspense,
1810
- useMyPresence,
1811
- useUpdateMyPresence,
1812
- useOthers: useOthersSuspense,
1813
- useOthersMapped: useOthersMappedSuspense,
1814
- useOthersConnectionIds: useOthersConnectionIdsSuspense,
1815
- useOther: useOtherSuspense,
1816
- useMutation,
1817
- useThreads: useThreadsSuspense,
1818
- useCreateThread,
1819
- useEditThreadMetadata,
1820
- useCreateComment,
1821
- useEditComment,
1822
- useDeleteComment,
1823
- useAddReaction,
1824
- useRemoveReaction,
1825
- useMarkThreadAsRead,
1826
- useThreadSubscription,
1827
- useRoomNotificationSettings: useRoomNotificationSettingsSuspense,
1828
- useUpdateRoomNotificationSettings,
1829
- ...shared.suspense
1830
- },
1831
- [_core.kInternal]: {
1832
- useCurrentUserId,
1833
- hasResolveMentionSuggestions: resolveMentionSuggestions !== void 0,
1834
- useMentionSuggestions
1835
- }
1836
- };
1837
- return Object.defineProperty(bundle, _core.kInternal, {
1838
- enumerable: false
1839
- });
1840
- }
1841
- function getCurrentUserId(room) {
1842
- const self = room.getSelf();
1843
- if (self === null || self.id === void 0) {
1844
- return "anonymous";
1845
- } else {
1846
- return self.id;
1847
- }
1848
- }
1849
- function handleApiError(err) {
1850
- const message = `Request failed with status ${err.status}: ${err.message}`;
1851
- if (_optionalChain([err, 'access', _6 => _6.details, 'optionalAccess', _7 => _7.error]) === "FORBIDDEN") {
1852
- const detailedMessage = [message, err.details.suggestion, err.details.docs].filter(Boolean).join("\n");
1853
- _core.console.error(detailedMessage);
1854
- }
1855
- return new Error(message);
1856
- }
1857
- function generateQueryKey(roomId, options) {
1858
- return `${roomId}-${_core.stringify.call(void 0, _nullishCoalesce(options, () => ( {})))}`;
1859
- }
1860
-
1861
- // src/shared.ts
1862
- function useSharedContextBundle() {
1863
- const roomContextBundle = _react.useContext.call(void 0, ContextBundle);
1864
- const liveblocksContextBundle = _react.useContext.call(void 0, ContextBundle2);
1865
- if (roomContextBundle !== null) {
1866
- return roomContextBundle;
1867
- } else if (liveblocksContextBundle !== null) {
1868
- return liveblocksContextBundle;
1869
- } else {
1870
- throw new Error(
1871
- "LiveblocksProvider or RoomProvider are missing from the React tree."
1872
- );
1873
- }
1874
- }
1875
- var missingUserError = new Error(
1876
- "resolveUsers didn't return anything for this user ID."
1877
- );
1878
- var missingRoomInfoError = new Error(
1879
- "resolveRoomsInfo didn't return anything for this room ID."
1880
- );
1881
- function createSharedContext(client) {
1882
- const usersStore = client[_core.kInternal].usersStore;
1883
- const roomsInfoStore = client[_core.kInternal].roomsInfoStore;
1884
- function useUser(userId) {
1885
- const getUserState = _react.useCallback.call(void 0,
1886
- () => usersStore.getState(userId),
1887
- [userId]
1888
- );
1889
- _react.useEffect.call(void 0, () => {
1890
- void usersStore.get(userId);
1891
- }, [userId]);
1892
- const state = _indexjs.useSyncExternalStore.call(void 0,
1893
- usersStore.subscribe,
1894
- getUserState,
1895
- getUserState
1896
- );
1897
- return state ? {
1898
- isLoading: state.isLoading,
1899
- user: state.data,
1900
- // Return an error if `undefined` was returned by `resolveUsers` for this user ID
1901
- error: !state.isLoading && !state.data && !state.error ? missingUserError : state.error
1902
- } : { isLoading: true };
1903
- }
1904
- function useUserSuspense(userId) {
1905
- const getUserState = _react.useCallback.call(void 0,
1906
- () => usersStore.getState(userId),
1907
- [userId]
1908
- );
1909
- const userState = getUserState();
1910
- if (!userState || userState.isLoading) {
1911
- throw usersStore.get(userId);
1912
- }
1913
- if (userState.error) {
1914
- throw userState.error;
1915
- }
1916
- if (!userState.data) {
1917
- throw missingUserError;
1918
- }
1919
- const state = _indexjs.useSyncExternalStore.call(void 0,
1920
- usersStore.subscribe,
1921
- getUserState,
1922
- getUserState
1923
- );
1924
- return {
1925
- isLoading: false,
1926
- user: _optionalChain([state, 'optionalAccess', _8 => _8.data]),
1927
- error: _optionalChain([state, 'optionalAccess', _9 => _9.error])
1928
- };
1929
- }
1930
- function useRoomInfo(roomId) {
1931
- const getRoomInfoState = _react.useCallback.call(void 0,
1932
- () => roomsInfoStore.getState(roomId),
1933
- [roomId]
1934
- );
1935
- _react.useEffect.call(void 0, () => {
1936
- void roomsInfoStore.get(roomId);
1937
- }, [roomId]);
1938
- const state = _indexjs.useSyncExternalStore.call(void 0,
1939
- roomsInfoStore.subscribe,
1940
- getRoomInfoState,
1941
- getRoomInfoState
1942
- );
1943
- return state ? {
1944
- isLoading: state.isLoading,
1945
- info: state.data,
1946
- // Return an error if `undefined` was returned by `resolveRoomsInfo` for this room ID
1947
- error: !state.isLoading && !state.data && !state.error ? missingRoomInfoError : state.error
1948
- } : { isLoading: true };
1949
- }
1950
- function useRoomInfoSuspense(roomId) {
1951
- const getRoomInfoState = _react.useCallback.call(void 0,
1952
- () => roomsInfoStore.getState(roomId),
1953
- [roomId]
1954
- );
1955
- const roomInfoState = getRoomInfoState();
1956
- if (!roomInfoState || roomInfoState.isLoading) {
1957
- throw roomsInfoStore.get(roomId);
1958
- }
1959
- if (roomInfoState.error) {
1960
- throw roomInfoState.error;
1961
- }
1962
- if (!roomInfoState.data) {
1963
- throw missingRoomInfoError;
1964
- }
1965
- const state = _indexjs.useSyncExternalStore.call(void 0,
1966
- roomsInfoStore.subscribe,
1967
- getRoomInfoState,
1968
- getRoomInfoState
1969
- );
1970
- return {
1971
- isLoading: false,
1972
- info: _optionalChain([state, 'optionalAccess', _10 => _10.data]),
1973
- error: _optionalChain([state, 'optionalAccess', _11 => _11.error])
1974
- };
1975
- }
1976
- const bundle = {
1977
- useUser,
1978
- useRoomInfo,
1979
- suspense: {
1980
- useUser: useUserSuspense,
1981
- useRoomInfo: useRoomInfoSuspense
1982
- }
1983
- };
1984
- return bundle;
1985
- }
1986
-
1987
- // src/liveblocks.tsx
1988
- var ContextBundle2 = _react.createContext.call(void 0, null);
1989
- function useLiveblocksContextBundle() {
1990
- const bundle = _react.useContext.call(void 0, ContextBundle2);
1991
- if (bundle === null) {
1992
- throw new Error("LiveblocksProvider is missing from the React tree.");
1993
- }
1994
- return bundle;
1995
- }
1996
- var POLLING_INTERVAL2 = 60 * 1e3;
1997
- var INBOX_NOTIFICATIONS_QUERY = "INBOX_NOTIFICATIONS";
1998
- function createLiveblocksContext(client) {
1999
- const shared = createSharedContext(client);
2000
- const store = client[_core.kInternal].cacheStore;
2001
- const notifications = client[_core.kInternal].notifications;
2002
- function LiveblocksProvider(props) {
2003
- return /* @__PURE__ */ React.default.createElement(
2004
- ContextBundle2.Provider,
2005
- {
2006
- value: bundle
2007
- },
2008
- props.children
2009
- );
2010
- }
2011
- let fetchInboxNotificationsRequest = null;
2012
- let inboxNotificationsSubscribers = 0;
2013
- let lastRequestedAt;
2014
- const poller = _core.makePoller.call(void 0, refreshThreadsAndNotifications);
2015
- function refreshThreadsAndNotifications() {
2016
- return notifications.getInboxNotifications({ since: lastRequestedAt }).then(
2017
- (result) => {
2018
- lastRequestedAt = result.meta.requestedAt;
2019
- store.updateThreadsAndNotifications(
2020
- result.threads,
2021
- result.inboxNotifications,
2022
- result.deletedThreads,
2023
- result.deletedInboxNotifications,
2024
- INBOX_NOTIFICATIONS_QUERY
2025
- );
2026
- },
2027
- () => {
2028
- }
2029
- );
2030
- }
2031
- function incrementInboxNotificationsSubscribers() {
2032
- inboxNotificationsSubscribers++;
2033
- poller.start(POLLING_INTERVAL2);
2034
- }
2035
- function decrementInboxNotificationsSubscribers() {
2036
- if (inboxNotificationsSubscribers <= 0) {
2037
- console.warn(
2038
- `Internal unexpected behavior. Cannot decrease subscriber count for query "${INBOX_NOTIFICATIONS_QUERY}"`
2039
- );
2040
- return;
2041
- }
2042
- inboxNotificationsSubscribers--;
2043
- if (inboxNotificationsSubscribers <= 0) {
2044
- poller.stop();
2045
- }
2046
- }
2047
- async function fetchInboxNotifications({ retryCount } = { retryCount: 0 }) {
2048
- if (fetchInboxNotificationsRequest !== null) {
2049
- return fetchInboxNotificationsRequest;
2050
- }
2051
- store.setQueryState(INBOX_NOTIFICATIONS_QUERY, {
2052
- isLoading: true
2053
- });
2054
- try {
2055
- fetchInboxNotificationsRequest = notifications.getInboxNotifications();
2056
- const result = await fetchInboxNotificationsRequest;
2057
- store.updateThreadsAndNotifications(
2058
- result.threads,
2059
- result.inboxNotifications,
2060
- result.deletedThreads,
2061
- result.deletedInboxNotifications,
2062
- INBOX_NOTIFICATIONS_QUERY
2063
- );
2064
- if (lastRequestedAt === void 0 || lastRequestedAt > result.meta.requestedAt) {
2065
- lastRequestedAt = result.meta.requestedAt;
2066
- }
2067
- poller.start(POLLING_INTERVAL2);
2068
- } catch (er) {
2069
- fetchInboxNotificationsRequest = null;
2070
- retryError(() => {
2071
- void fetchInboxNotifications({
2072
- retryCount: retryCount + 1
2073
- });
2074
- }, retryCount);
2075
- store.setQueryState(INBOX_NOTIFICATIONS_QUERY, {
2076
- isLoading: false,
2077
- error: er
2078
- });
2079
- }
2080
- return;
2081
- }
2082
- function useInboxNotificationsSelectorCallback(state) {
2083
- const query = state.queries[INBOX_NOTIFICATIONS_QUERY];
2084
- if (query === void 0 || query.isLoading) {
2085
- return {
2086
- isLoading: true
2087
- };
2088
- }
2089
- if (query.error !== void 0) {
2090
- return {
2091
- error: query.error,
2092
- isLoading: false
2093
- };
2094
- }
2095
- return {
2096
- inboxNotifications: selectedInboxNotifications(state),
2097
- isLoading: false
2098
- };
2099
- }
2100
- function useInboxNotifications() {
2101
- _react.useEffect.call(void 0, () => {
2102
- void fetchInboxNotifications();
2103
- incrementInboxNotificationsSubscribers();
2104
- return () => decrementInboxNotificationsSubscribers();
2105
- }, []);
2106
- const result = _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
2107
- store.subscribe,
2108
- store.get,
2109
- store.get,
2110
- useInboxNotificationsSelectorCallback
2111
- );
2112
- return result;
2113
- }
2114
- function useInboxNotificationsSuspenseSelector(state) {
2115
- return {
2116
- inboxNotifications: selectedInboxNotifications(state),
2117
- isLoading: false
2118
- };
2119
- }
2120
- function useInboxNotificationsSuspense() {
2121
- const query = store.get().queries[INBOX_NOTIFICATIONS_QUERY];
2122
- if (query === void 0 || query.isLoading) {
2123
- throw fetchInboxNotifications();
2124
- }
2125
- if (query.error !== void 0) {
2126
- throw query.error;
2127
- }
2128
- React.default.useEffect(() => {
2129
- incrementInboxNotificationsSubscribers();
2130
- return () => {
2131
- decrementInboxNotificationsSubscribers();
2132
- };
2133
- }, []);
2134
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
2135
- store.subscribe,
2136
- store.get,
2137
- store.get,
2138
- useInboxNotificationsSuspenseSelector
2139
- );
2140
- }
2141
- function selectUnreadInboxNotificationsCount(state) {
2142
- let count = 0;
2143
- for (const notification of selectedInboxNotifications(state)) {
2144
- if (notification.readAt === null || notification.readAt < notification.notifiedAt) {
2145
- count++;
2146
- }
2147
- }
2148
- return count;
2149
- }
2150
- function useUnreadInboxNotificationsCountSelector(state) {
2151
- const query = state.queries[INBOX_NOTIFICATIONS_QUERY];
2152
- if (query === void 0 || query.isLoading) {
2153
- return {
2154
- isLoading: true
2155
- };
2156
- }
2157
- if (query.error !== void 0) {
2158
- return {
2159
- error: query.error,
2160
- isLoading: false
2161
- };
2162
- }
2163
- return {
2164
- isLoading: false,
2165
- count: selectUnreadInboxNotificationsCount(state)
2166
- };
2167
- }
2168
- function useUnreadInboxNotificationsCount() {
2169
- _react.useEffect.call(void 0, () => {
2170
- void fetchInboxNotifications();
2171
- incrementInboxNotificationsSubscribers();
2172
- return () => decrementInboxNotificationsSubscribers();
2173
- }, []);
2174
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
2175
- store.subscribe,
2176
- store.get,
2177
- store.get,
2178
- useUnreadInboxNotificationsCountSelector
2179
- );
2180
- }
2181
- function useUnreadInboxNotificationsCountSuspenseSelector(state) {
2182
- return {
2183
- isLoading: false,
2184
- count: selectUnreadInboxNotificationsCount(state)
2185
- };
2186
- }
2187
- function useUnreadInboxNotificationsCountSuspense() {
2188
- const query = store.get().queries[INBOX_NOTIFICATIONS_QUERY];
2189
- if (query === void 0 || query.isLoading) {
2190
- throw fetchInboxNotifications();
2191
- }
2192
- React.default.useEffect(() => {
2193
- incrementInboxNotificationsSubscribers();
2194
- return () => {
2195
- decrementInboxNotificationsSubscribers();
2196
- };
2197
- }, []);
2198
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
2199
- store.subscribe,
2200
- store.get,
2201
- store.get,
2202
- useUnreadInboxNotificationsCountSuspenseSelector
2203
- );
2204
- }
2205
- function useMarkInboxNotificationAsRead() {
2206
- return _react.useCallback.call(void 0, (inboxNotificationId) => {
2207
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
2208
- const readAt = /* @__PURE__ */ new Date();
2209
- store.pushOptimisticUpdate({
2210
- type: "mark-inbox-notification-as-read",
2211
- id: optimisticUpdateId,
2212
- inboxNotificationId,
2213
- readAt
2214
- });
2215
- notifications.markInboxNotificationAsRead(inboxNotificationId).then(
2216
- () => {
2217
- store.set((state) => {
2218
- const existingNotification = state.inboxNotifications[inboxNotificationId];
2219
- if (existingNotification === void 0) {
2220
- return {
2221
- ...state,
2222
- optimisticUpdates: state.optimisticUpdates.filter(
2223
- (update) => update.id !== optimisticUpdateId
2224
- )
2225
- };
2226
- }
2227
- return {
2228
- ...state,
2229
- inboxNotifications: {
2230
- ...state.inboxNotifications,
2231
- [inboxNotificationId]: {
2232
- ...existingNotification,
2233
- readAt
2234
- }
2235
- },
2236
- optimisticUpdates: state.optimisticUpdates.filter(
2237
- (update) => update.id !== optimisticUpdateId
2238
- )
2239
- };
2240
- });
2241
- },
2242
- () => {
2243
- store.set((state) => ({
2244
- ...state,
2245
- optimisticUpdates: state.optimisticUpdates.filter(
2246
- (update) => update.id !== optimisticUpdateId
2247
- )
2248
- }));
2249
- }
2250
- );
2251
- }, []);
2252
- }
2253
- function useMarkAllInboxNotificationsAsRead() {
2254
- return _react.useCallback.call(void 0, () => {
2255
- const optimisticUpdateId = _nanoid.nanoid.call(void 0, );
2256
- const readAt = /* @__PURE__ */ new Date();
2257
- store.pushOptimisticUpdate({
2258
- type: "mark-inbox-notifications-as-read",
2259
- id: optimisticUpdateId,
2260
- readAt
2261
- });
2262
- notifications.markAllInboxNotificationsAsRead().then(
2263
- () => {
2264
- store.set((state) => ({
2265
- ...state,
2266
- inboxNotifications: Object.fromEntries(
2267
- Array.from(Object.entries(state.inboxNotifications)).map(
2268
- ([id, inboxNotification]) => [
2269
- id,
2270
- { ...inboxNotification, readAt }
2271
- ]
2272
- )
2273
- ),
2274
- optimisticUpdates: state.optimisticUpdates.filter(
2275
- (update) => update.id !== optimisticUpdateId
2276
- )
2277
- }));
2278
- },
2279
- () => {
2280
- store.set((state) => ({
2281
- ...state,
2282
- optimisticUpdates: state.optimisticUpdates.filter(
2283
- (update) => update.id !== optimisticUpdateId
2284
- )
2285
- }));
2286
- }
2287
- );
2288
- }, []);
2289
- }
2290
- function useInboxNotificationThread(inboxNotificationId) {
2291
- const selector = _react.useCallback.call(void 0,
2292
- (state) => {
2293
- const inboxNotification = state.inboxNotifications[inboxNotificationId];
2294
- if (inboxNotification === void 0) {
2295
- throw new Error(
2296
- `Inbox notification with ID "${inboxNotificationId}" not found`
2297
- );
2298
- }
2299
- if (inboxNotification.kind !== "thread") {
2300
- throw new Error(
2301
- `Inbox notification with ID "${inboxNotificationId}" is not of kind "thread"`
2302
- );
2303
- }
2304
- const thread = state.threads[inboxNotification.threadId];
2305
- if (thread === void 0) {
2306
- throw new Error(
2307
- `Thread with ID "${inboxNotification.threadId}" not found, this inbox notification might not be of kind "thread"`
2308
- );
2309
- }
2310
- return thread;
2311
- },
2312
- [inboxNotificationId]
2313
- );
2314
- return _withselectorjs.useSyncExternalStoreWithSelector.call(void 0,
2315
- store.subscribe,
2316
- store.get,
2317
- store.get,
2318
- selector
2319
- );
2320
- }
2321
- const currentUserIdStore = client[_core.kInternal].currentUserIdStore;
2322
- function useCurrentUserId() {
2323
- return _indexjs.useSyncExternalStore.call(void 0,
2324
- currentUserIdStore.subscribe,
2325
- currentUserIdStore.get,
2326
- currentUserIdStore.get
2327
- );
2328
- }
2329
- const bundle = {
2330
- LiveblocksProvider,
2331
- useInboxNotifications,
2332
- useUnreadInboxNotificationsCount,
2333
- useMarkInboxNotificationAsRead,
2334
- useMarkAllInboxNotificationsAsRead,
2335
- useInboxNotificationThread,
2336
- ...shared,
2337
- suspense: {
2338
- LiveblocksProvider,
2339
- useInboxNotifications: useInboxNotificationsSuspense,
2340
- useUnreadInboxNotificationsCount: useUnreadInboxNotificationsCountSuspense,
2341
- useMarkInboxNotificationAsRead,
2342
- useMarkAllInboxNotificationsAsRead,
2343
- useInboxNotificationThread,
2344
- ...shared.suspense
2345
- },
2346
- [_core.kInternal]: {
2347
- useCurrentUserId
2348
- }
2349
- };
2350
- return Object.defineProperty(bundle, _core.kInternal, {
2351
- enumerable: false
2352
- });
2353
- }
2354
103
 
2355
- // src/index.ts
2356
104
 
2357
- _core.detectDupes.call(void 0, PKG_NAME, PKG_VERSION, PKG_FORMAT);
2358
105
 
2359
106
 
2360
107
 
@@ -2363,5 +110,5 @@ _core.detectDupes.call(void 0, PKG_NAME, PKG_VERSION, PKG_FORMAT);
2363
110
 
2364
111
 
2365
112
 
2366
- exports.ClientSideSuspense = ClientSideSuspense; exports.createLiveblocksContext = createLiveblocksContext; exports.createRoomContext = createRoomContext; exports.shallow = _client.shallow; exports.useLiveblocksContextBundle = useLiveblocksContextBundle; exports.useRoomContextBundle = useRoomContextBundle; exports.useSharedContextBundle = useSharedContextBundle;
113
+ exports.ClientContext = _chunkRCQYZVO3js.ClientContext; exports.ClientSideSuspense = _chunkRCQYZVO3js.ClientSideSuspense; exports.LiveblocksProvider = _chunkRCQYZVO3js.LiveblocksProvider; exports.RoomContext = _chunkRCQYZVO3js.RoomContext; exports.RoomProvider = _chunkRCQYZVO3js._RoomProvider; exports.createLiveblocksContext = _chunkRCQYZVO3js.createLiveblocksContext; exports.createRoomContext = _chunkRCQYZVO3js.createRoomContext; exports.shallow = _client.shallow; exports.useAddReaction = _chunkRCQYZVO3js._useAddReaction; exports.useBatch = _chunkRCQYZVO3js.useBatch; exports.useBroadcastEvent = _chunkRCQYZVO3js._useBroadcastEvent; exports.useCanRedo = _chunkRCQYZVO3js.useCanRedo; exports.useCanUndo = _chunkRCQYZVO3js.useCanUndo; exports.useClient = _chunkRCQYZVO3js.useClient; exports.useCreateComment = _chunkRCQYZVO3js.useCreateComment; exports.useCreateThread = _chunkRCQYZVO3js._useCreateThread; exports.useDeleteComment = _chunkRCQYZVO3js.useDeleteComment; exports.useEditComment = _chunkRCQYZVO3js.useEditComment; exports.useEditThreadMetadata = _chunkRCQYZVO3js._useEditThreadMetadata; exports.useErrorListener = _chunkRCQYZVO3js.useErrorListener; exports.useEventListener = _chunkRCQYZVO3js._useEventListener; exports.useHistory = _chunkRCQYZVO3js.useHistory; exports.useInboxNotificationThread = _chunkRCQYZVO3js.__1; exports.useInboxNotifications = _chunkRCQYZVO3js.useInboxNotifications; exports.useLostConnectionListener = _chunkRCQYZVO3js.useLostConnectionListener; exports.useMarkAllInboxNotificationsAsRead = _chunkRCQYZVO3js.useMarkAllInboxNotificationsAsRead; exports.useMarkInboxNotificationAsRead = _chunkRCQYZVO3js.useMarkInboxNotificationAsRead; exports.useMarkThreadAsRead = _chunkRCQYZVO3js.useMarkThreadAsRead; exports.useMutation = _chunkRCQYZVO3js._useMutation; exports.useMyPresence = _chunkRCQYZVO3js._useMyPresence; exports.useOther = _chunkRCQYZVO3js._useOther; exports.useOthers = _chunkRCQYZVO3js._useOthers; exports.useOthersConnectionIds = _chunkRCQYZVO3js.useOthersConnectionIds; exports.useOthersListener = _chunkRCQYZVO3js._useOthersListener; exports.useOthersMapped = _chunkRCQYZVO3js._useOthersMapped; exports.useRedo = _chunkRCQYZVO3js.useRedo; exports.useRemoveReaction = _chunkRCQYZVO3js.useRemoveReaction; exports.useRoom = _chunkRCQYZVO3js._useRoom; exports.useRoomInfo = _chunkRCQYZVO3js.useRoomInfo; exports.useRoomNotificationSettings = _chunkRCQYZVO3js.useRoomNotificationSettings; exports.useSelf = _chunkRCQYZVO3js._useSelf; exports.useStatus = _chunkRCQYZVO3js.useStatus; exports.useStorage = _chunkRCQYZVO3js._useStorage; exports.useStorageRoot = _chunkRCQYZVO3js._useStorageRoot; exports.useThreadSubscription = _chunkRCQYZVO3js.useThreadSubscription; exports.useThreads = _chunkRCQYZVO3js._useThreads; exports.useUndo = _chunkRCQYZVO3js.useUndo; exports.useUnreadInboxNotificationsCount = _chunkRCQYZVO3js.useUnreadInboxNotificationsCount; exports.useUpdateMyPresence = _chunkRCQYZVO3js._useUpdateMyPresence; exports.useUpdateRoomNotificationSettings = _chunkRCQYZVO3js.useUpdateRoomNotificationSettings; exports.useUser = _chunkRCQYZVO3js.__2;
2367
114
  //# sourceMappingURL=index.js.map