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