@liveblocks/react 1.3.3 → 1.3.5
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 +44 -20
- package/dist/index.d.ts +44 -20
- package/dist/index.js +296 -230
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +291 -225
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { detectDupes } from "@liveblocks/core";
|
|
|
5
5
|
|
|
6
6
|
// src/version.ts
|
|
7
7
|
var PKG_NAME = "@liveblocks/react";
|
|
8
|
-
var PKG_VERSION = "1.3.
|
|
8
|
+
var PKG_VERSION = "1.3.5";
|
|
9
9
|
var PKG_FORMAT = "esm";
|
|
10
10
|
|
|
11
11
|
// src/ClientSideSuspense.tsx
|
|
@@ -24,13 +24,16 @@ import {
|
|
|
24
24
|
createAsyncCache,
|
|
25
25
|
deprecateIf,
|
|
26
26
|
errorIf,
|
|
27
|
+
isLiveNode,
|
|
27
28
|
makeEventSource as makeEventSource2
|
|
28
29
|
} from "@liveblocks/core";
|
|
29
30
|
import * as React2 from "react";
|
|
30
31
|
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/shim/with-selector.js";
|
|
31
32
|
|
|
32
33
|
// src/comments/CommentsRoom.ts
|
|
33
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
makeEventSource
|
|
36
|
+
} from "@liveblocks/core";
|
|
34
37
|
import { nanoid } from "nanoid";
|
|
35
38
|
import { useEffect as useEffect2 } from "react";
|
|
36
39
|
import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
|
|
@@ -77,158 +80,166 @@ var DeleteCommentError = class extends Error {
|
|
|
77
80
|
}
|
|
78
81
|
};
|
|
79
82
|
|
|
80
|
-
// src/comments/
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
// src/comments/CommentsRoom.ts
|
|
84
|
+
var POLLING_INTERVAL_REALTIME = 3e4;
|
|
85
|
+
var POLLING_INTERVAL = 5e3;
|
|
86
|
+
var MAX_ERROR_RETRY_COUNT = 5;
|
|
87
|
+
var ERROR_RETRY_INTERVAL = 5e3;
|
|
88
|
+
var THREAD_ID_PREFIX = "th";
|
|
89
|
+
var COMMENT_ID_PREFIX = "cm";
|
|
90
|
+
var DEDUPING_INTERVAL = 1e3;
|
|
91
|
+
function createOptimisticId(prefix) {
|
|
92
|
+
return `${prefix}_${nanoid()}`;
|
|
93
|
+
}
|
|
94
|
+
function createThreadsManager() {
|
|
95
|
+
let cache;
|
|
96
|
+
let request;
|
|
97
|
+
let mutation;
|
|
84
98
|
const eventSource = makeEventSource();
|
|
85
99
|
return {
|
|
86
|
-
get() {
|
|
87
|
-
return
|
|
100
|
+
get cache() {
|
|
101
|
+
return cache;
|
|
88
102
|
},
|
|
89
|
-
set(
|
|
90
|
-
|
|
91
|
-
eventSource.notify(
|
|
103
|
+
set cache(value) {
|
|
104
|
+
cache = value;
|
|
105
|
+
eventSource.notify(cache);
|
|
92
106
|
},
|
|
93
|
-
|
|
94
|
-
return
|
|
107
|
+
get request() {
|
|
108
|
+
return request;
|
|
109
|
+
},
|
|
110
|
+
set request(value) {
|
|
111
|
+
request = value;
|
|
95
112
|
},
|
|
96
|
-
|
|
97
|
-
return
|
|
113
|
+
get mutation() {
|
|
114
|
+
return mutation;
|
|
98
115
|
},
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
set mutation(value) {
|
|
117
|
+
mutation = value;
|
|
101
118
|
},
|
|
102
|
-
|
|
103
|
-
return eventSource.
|
|
119
|
+
subscribe(callback) {
|
|
120
|
+
return eventSource.subscribe(callback);
|
|
104
121
|
}
|
|
105
122
|
};
|
|
106
123
|
}
|
|
107
|
-
|
|
108
|
-
// src/comments/CommentsRoom.ts
|
|
109
|
-
var POLLING_INTERVAL_REALTIME = 3e4;
|
|
110
|
-
var POLLING_INTERVAL = 5e3;
|
|
111
|
-
var THREAD_ID_PREFIX = "th";
|
|
112
|
-
var COMMENT_ID_PREFIX = "cm";
|
|
113
|
-
function createOptimisticId(prefix) {
|
|
114
|
-
return `${prefix}_${nanoid()}`;
|
|
115
|
-
}
|
|
116
124
|
function createCommentsRoom(room, errorEventSource) {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
let
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
let unsubscribeRealtimeConnection;
|
|
138
|
-
let realtimeClientConnected = false;
|
|
139
|
-
function getPollingInterval() {
|
|
140
|
-
return realtimeClientConnected ? POLLING_INTERVAL_REALTIME : POLLING_INTERVAL;
|
|
141
|
-
}
|
|
142
|
-
function ensureThreadsAreLoadedForMutations() {
|
|
143
|
-
const state = store.get();
|
|
144
|
-
if (state.isLoading || state.error) {
|
|
145
|
-
throw new Error(
|
|
146
|
-
"Cannot update threads or comments before they are loaded"
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
return state.threads;
|
|
150
|
-
}
|
|
151
|
-
async function revalidateThreads() {
|
|
152
|
-
pollingHub.threads.pause();
|
|
153
|
-
if (numberOfMutations === 0) {
|
|
154
|
-
if (fetchThreadsPromise === null) {
|
|
155
|
-
fetchThreadsPromise = room.getThreads();
|
|
125
|
+
const manager = createThreadsManager();
|
|
126
|
+
let timestamp = 0;
|
|
127
|
+
let commentsEventRefCount = 0;
|
|
128
|
+
let commentsEventDisposer;
|
|
129
|
+
async function mutate(data, options) {
|
|
130
|
+
const beforeMutationTimestamp = ++timestamp;
|
|
131
|
+
manager.mutation = {
|
|
132
|
+
startTime: beforeMutationTimestamp,
|
|
133
|
+
endTime: 0
|
|
134
|
+
};
|
|
135
|
+
const currentCache = manager.cache;
|
|
136
|
+
manager.cache = {
|
|
137
|
+
isLoading: false,
|
|
138
|
+
threads: options.optimisticData
|
|
139
|
+
};
|
|
140
|
+
try {
|
|
141
|
+
await data;
|
|
142
|
+
const activeMutation = manager.mutation;
|
|
143
|
+
if (activeMutation && beforeMutationTimestamp !== activeMutation.startTime) {
|
|
144
|
+
return;
|
|
156
145
|
}
|
|
157
|
-
|
|
158
|
-
|
|
146
|
+
} catch (err) {
|
|
147
|
+
manager.cache = currentCache;
|
|
148
|
+
throw err;
|
|
159
149
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
150
|
+
manager.mutation = {
|
|
151
|
+
startTime: beforeMutationTimestamp,
|
|
152
|
+
endTime: ++timestamp
|
|
153
|
+
};
|
|
154
|
+
manager.request = void 0;
|
|
155
|
+
void revalidateCache(false);
|
|
156
|
+
}
|
|
157
|
+
async function revalidateCache(shouldDedupe, retryCount = 0) {
|
|
158
|
+
let startAt;
|
|
159
|
+
const shouldStartRequest = !manager.request || !shouldDedupe;
|
|
160
|
+
function deleteActiveRequest() {
|
|
161
|
+
const activeRequest = manager.request;
|
|
162
|
+
if (!activeRequest)
|
|
163
|
+
return;
|
|
164
|
+
if (activeRequest.timestamp !== startAt)
|
|
165
|
+
return;
|
|
166
|
+
manager.request = void 0;
|
|
168
167
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
});
|
|
168
|
+
function handleError() {
|
|
169
|
+
const timeout = ~~((Math.random() + 0.5) * (1 << (retryCount < 8 ? retryCount : 8))) * ERROR_RETRY_INTERVAL;
|
|
170
|
+
if (retryCount > MAX_ERROR_RETRY_COUNT)
|
|
171
|
+
return;
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
void revalidateCache(true, retryCount + 1);
|
|
174
|
+
}, timeout);
|
|
177
175
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
try {
|
|
177
|
+
if (shouldStartRequest) {
|
|
178
|
+
const currentCache = manager.cache;
|
|
179
|
+
if (!currentCache)
|
|
180
|
+
manager.cache = { isLoading: true };
|
|
181
|
+
manager.request = {
|
|
182
|
+
fetcher: room.getThreads(),
|
|
183
|
+
timestamp: ++timestamp
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const activeRequest = manager.request;
|
|
187
|
+
if (!activeRequest)
|
|
181
188
|
return;
|
|
189
|
+
const newData = await activeRequest.fetcher;
|
|
190
|
+
startAt = activeRequest.timestamp;
|
|
191
|
+
if (shouldStartRequest) {
|
|
192
|
+
setTimeout(deleteActiveRequest, DEDUPING_INTERVAL);
|
|
182
193
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
store.get
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
function useThreads() {
|
|
205
|
-
useEffect2(() => {
|
|
206
|
-
void revalidateThreads();
|
|
207
|
-
}, []);
|
|
208
|
-
return useThreadsInternal();
|
|
209
|
-
}
|
|
210
|
-
function useThreadsSuspense() {
|
|
211
|
-
const result = useThreadsInternal();
|
|
212
|
-
if (result.isLoading) {
|
|
213
|
-
throw revalidateThreads();
|
|
214
|
-
}
|
|
215
|
-
if (result.error) {
|
|
216
|
-
throw result.error;
|
|
194
|
+
if (!manager.request || manager.request.timestamp !== startAt)
|
|
195
|
+
return;
|
|
196
|
+
const activeMutation = manager.mutation;
|
|
197
|
+
if (activeMutation && (activeMutation.startTime > startAt || activeMutation.endTime > startAt || activeMutation.endTime === 0)) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
manager.cache = {
|
|
201
|
+
isLoading: false,
|
|
202
|
+
threads: newData
|
|
203
|
+
};
|
|
204
|
+
} catch (err) {
|
|
205
|
+
if (shouldStartRequest)
|
|
206
|
+
handleError();
|
|
207
|
+
deleteActiveRequest();
|
|
208
|
+
manager.cache = {
|
|
209
|
+
isLoading: false,
|
|
210
|
+
error: err
|
|
211
|
+
};
|
|
217
212
|
}
|
|
218
|
-
return result.threads;
|
|
219
213
|
}
|
|
220
|
-
function
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
214
|
+
function editThreadMetadata(options) {
|
|
215
|
+
const threadId = options.threadId;
|
|
216
|
+
const metadata = "metadata" in options ? options.metadata : {};
|
|
217
|
+
const threads = getThreads();
|
|
218
|
+
const optimisticData = threads.map(
|
|
219
|
+
(thread) => thread.id === threadId ? {
|
|
220
|
+
...thread,
|
|
221
|
+
metadata: {
|
|
222
|
+
...thread.metadata,
|
|
223
|
+
...metadata
|
|
224
|
+
}
|
|
225
|
+
} : thread
|
|
226
|
+
);
|
|
227
|
+
mutate(room.editThreadMetadata({ metadata, threadId }), {
|
|
228
|
+
optimisticData
|
|
229
|
+
}).catch((err) => {
|
|
230
|
+
errorEventSource.notify(
|
|
231
|
+
new EditThreadMetadataError(err, {
|
|
232
|
+
roomId: room.id,
|
|
233
|
+
threadId,
|
|
234
|
+
metadata
|
|
235
|
+
})
|
|
236
|
+
);
|
|
237
|
+
});
|
|
227
238
|
}
|
|
228
239
|
function createThread(options) {
|
|
229
240
|
const body = options.body;
|
|
230
241
|
const metadata = "metadata" in options ? options.metadata : {};
|
|
231
|
-
const threads =
|
|
242
|
+
const threads = getThreads();
|
|
232
243
|
const threadId = createOptimisticId(THREAD_ID_PREFIX);
|
|
233
244
|
const commentId = createOptimisticId(COMMENT_ID_PREFIX);
|
|
234
245
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -248,9 +259,9 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
248
259
|
}
|
|
249
260
|
]
|
|
250
261
|
};
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
262
|
+
mutate(room.createThread({ threadId, commentId, body, metadata }), {
|
|
263
|
+
optimisticData: [...threads, newThread]
|
|
264
|
+
}).catch(
|
|
254
265
|
(er) => errorEventSource.notify(
|
|
255
266
|
new CreateThreadError(er, {
|
|
256
267
|
roomId: room.id,
|
|
@@ -260,40 +271,14 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
260
271
|
metadata
|
|
261
272
|
})
|
|
262
273
|
)
|
|
263
|
-
).finally(endMutation);
|
|
264
|
-
return newThread;
|
|
265
|
-
}
|
|
266
|
-
function editThreadMetadata(options) {
|
|
267
|
-
const threadId = options.threadId;
|
|
268
|
-
const metadata = "metadata" in options ? options.metadata : {};
|
|
269
|
-
const threads = ensureThreadsAreLoadedForMutations();
|
|
270
|
-
setThreads(
|
|
271
|
-
threads.map(
|
|
272
|
-
(thread) => thread.id === threadId ? {
|
|
273
|
-
...thread,
|
|
274
|
-
metadata: {
|
|
275
|
-
...thread.metadata,
|
|
276
|
-
...metadata
|
|
277
|
-
}
|
|
278
|
-
} : thread
|
|
279
|
-
)
|
|
280
274
|
);
|
|
281
|
-
|
|
282
|
-
room.editThreadMetadata({ metadata, threadId }).catch(
|
|
283
|
-
(er) => errorEventSource.notify(
|
|
284
|
-
new EditThreadMetadataError(er, {
|
|
285
|
-
roomId: room.id,
|
|
286
|
-
threadId,
|
|
287
|
-
metadata
|
|
288
|
-
})
|
|
289
|
-
)
|
|
290
|
-
).finally(endMutation);
|
|
275
|
+
return newThread;
|
|
291
276
|
}
|
|
292
277
|
function createComment({
|
|
293
278
|
threadId,
|
|
294
279
|
body
|
|
295
280
|
}) {
|
|
296
|
-
const threads =
|
|
281
|
+
const threads = getThreads();
|
|
297
282
|
const commentId = createOptimisticId(COMMENT_ID_PREFIX);
|
|
298
283
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
299
284
|
const comment = {
|
|
@@ -305,16 +290,15 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
305
290
|
userId: getCurrentUserId(),
|
|
306
291
|
body
|
|
307
292
|
};
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
} : thread
|
|
314
|
-
)
|
|
293
|
+
const optimisticData = threads.map(
|
|
294
|
+
(thread) => thread.id === threadId ? {
|
|
295
|
+
...thread,
|
|
296
|
+
comments: [...thread.comments, comment]
|
|
297
|
+
} : thread
|
|
315
298
|
);
|
|
316
|
-
|
|
317
|
-
|
|
299
|
+
mutate(room.createComment({ threadId, commentId, body }), {
|
|
300
|
+
optimisticData
|
|
301
|
+
}).catch(
|
|
318
302
|
(er) => errorEventSource.notify(
|
|
319
303
|
new CreateCommentError(er, {
|
|
320
304
|
roomId: room.id,
|
|
@@ -323,28 +307,27 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
323
307
|
body
|
|
324
308
|
})
|
|
325
309
|
)
|
|
326
|
-
)
|
|
310
|
+
);
|
|
327
311
|
return comment;
|
|
328
312
|
}
|
|
329
313
|
function editComment({ threadId, commentId, body }) {
|
|
330
|
-
const threads =
|
|
314
|
+
const threads = getThreads();
|
|
331
315
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
} : thread
|
|
344
|
-
)
|
|
316
|
+
const optimisticData = threads.map(
|
|
317
|
+
(thread) => thread.id === threadId ? {
|
|
318
|
+
...thread,
|
|
319
|
+
comments: thread.comments.map(
|
|
320
|
+
(comment) => comment.id === commentId ? {
|
|
321
|
+
...comment,
|
|
322
|
+
editedAt: now,
|
|
323
|
+
body
|
|
324
|
+
} : comment
|
|
325
|
+
)
|
|
326
|
+
} : thread
|
|
345
327
|
);
|
|
346
|
-
|
|
347
|
-
|
|
328
|
+
mutate(room.editComment({ threadId, commentId, body }), {
|
|
329
|
+
optimisticData
|
|
330
|
+
}).catch(
|
|
348
331
|
(er) => errorEventSource.notify(
|
|
349
332
|
new EditCommentError(er, {
|
|
350
333
|
roomId: room.id,
|
|
@@ -353,10 +336,10 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
353
336
|
body
|
|
354
337
|
})
|
|
355
338
|
)
|
|
356
|
-
)
|
|
339
|
+
);
|
|
357
340
|
}
|
|
358
341
|
function deleteComment({ threadId, commentId }) {
|
|
359
|
-
const threads =
|
|
342
|
+
const threads = getThreads();
|
|
360
343
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
361
344
|
const newThreads = [];
|
|
362
345
|
for (const thread of threads) {
|
|
@@ -378,9 +361,9 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
378
361
|
newThreads.push(thread);
|
|
379
362
|
}
|
|
380
363
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
364
|
+
mutate(room.deleteComment({ threadId, commentId }), {
|
|
365
|
+
optimisticData: newThreads
|
|
366
|
+
}).catch(
|
|
384
367
|
(er) => errorEventSource.notify(
|
|
385
368
|
new DeleteCommentError(er, {
|
|
386
369
|
roomId: room.id,
|
|
@@ -388,13 +371,103 @@ function createCommentsRoom(room, errorEventSource) {
|
|
|
388
371
|
commentId
|
|
389
372
|
})
|
|
390
373
|
)
|
|
391
|
-
)
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
function getCurrentUserId() {
|
|
377
|
+
const self = room.getSelf();
|
|
378
|
+
if (self === null || self.id === void 0) {
|
|
379
|
+
return "anonymous";
|
|
380
|
+
} else {
|
|
381
|
+
return self.id;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
function getThreads() {
|
|
385
|
+
const threads = manager.cache;
|
|
386
|
+
if (!threads || threads.isLoading || threads.error) {
|
|
387
|
+
throw new Error(
|
|
388
|
+
"Cannot update threads or comments before they are loaded."
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
return threads.threads;
|
|
392
|
+
}
|
|
393
|
+
function _subscribe() {
|
|
394
|
+
if (commentsEventRefCount === 0) {
|
|
395
|
+
commentsEventDisposer = room.events.comments.subscribe(() => {
|
|
396
|
+
void revalidateCache(true);
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
commentsEventRefCount = commentsEventRefCount + 1;
|
|
400
|
+
return () => {
|
|
401
|
+
commentsEventRefCount = commentsEventRefCount - 1;
|
|
402
|
+
if (commentsEventRefCount > 0)
|
|
403
|
+
return;
|
|
404
|
+
commentsEventDisposer?.();
|
|
405
|
+
commentsEventDisposer = void 0;
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
function usePolling() {
|
|
409
|
+
const status = useSyncExternalStore(
|
|
410
|
+
room.events.status.subscribe,
|
|
411
|
+
room.getStatus,
|
|
412
|
+
room.getStatus
|
|
413
|
+
);
|
|
414
|
+
useEffect2(
|
|
415
|
+
() => {
|
|
416
|
+
const interval = status === "connected" ? POLLING_INTERVAL_REALTIME : POLLING_INTERVAL;
|
|
417
|
+
let revalidationTimerId;
|
|
418
|
+
function scheduleRevalidation() {
|
|
419
|
+
revalidationTimerId = window.setTimeout(
|
|
420
|
+
executeRevalidation,
|
|
421
|
+
interval
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
function executeRevalidation() {
|
|
425
|
+
void revalidateCache(true).then(scheduleRevalidation);
|
|
426
|
+
}
|
|
427
|
+
scheduleRevalidation();
|
|
428
|
+
return () => {
|
|
429
|
+
window.clearTimeout(revalidationTimerId);
|
|
430
|
+
};
|
|
431
|
+
},
|
|
432
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- ESLint recommends against adding `revalidateCache` as a dependency, but not doing so causes the code inside `useEffect` to reference an outdated version of `revalidateCache`
|
|
433
|
+
[status, revalidateCache]
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
function useThreadsInternal() {
|
|
437
|
+
useEffect2(_subscribe, [_subscribe]);
|
|
438
|
+
usePolling();
|
|
439
|
+
const cache = useSyncExternalStore(
|
|
440
|
+
manager.subscribe,
|
|
441
|
+
() => manager.cache,
|
|
442
|
+
() => manager.cache
|
|
443
|
+
);
|
|
444
|
+
return cache ?? { isLoading: true };
|
|
445
|
+
}
|
|
446
|
+
function useThreads() {
|
|
447
|
+
useEffect2(
|
|
448
|
+
() => {
|
|
449
|
+
void revalidateCache(true);
|
|
450
|
+
},
|
|
451
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps -- ESLint recommends against adding `revalidateCache` as a dependency, but not doing so causes the code inside `useEffect` to reference an outdated version of `revalidateCache`
|
|
452
|
+
[revalidateCache]
|
|
453
|
+
);
|
|
454
|
+
return useThreadsInternal();
|
|
455
|
+
}
|
|
456
|
+
function useThreadsSuspense() {
|
|
457
|
+
const cache = useThreadsInternal();
|
|
458
|
+
if (cache.isLoading) {
|
|
459
|
+
throw revalidateCache(true);
|
|
460
|
+
}
|
|
461
|
+
if (cache.error) {
|
|
462
|
+
throw cache.error;
|
|
463
|
+
}
|
|
464
|
+
return cache.threads;
|
|
392
465
|
}
|
|
393
466
|
return {
|
|
394
467
|
useThreads,
|
|
395
468
|
useThreadsSuspense,
|
|
396
|
-
createThread,
|
|
397
469
|
editThreadMetadata,
|
|
470
|
+
createThread,
|
|
398
471
|
createComment,
|
|
399
472
|
editComment,
|
|
400
473
|
deleteComment
|
|
@@ -641,9 +714,9 @@ function createRoomContext(client, options) {
|
|
|
641
714
|
);
|
|
642
715
|
setRoom(room2);
|
|
643
716
|
return () => {
|
|
644
|
-
const commentsRoom = commentsRooms.get(
|
|
717
|
+
const commentsRoom = commentsRooms.get(room2);
|
|
645
718
|
if (commentsRoom) {
|
|
646
|
-
commentsRooms.delete(
|
|
719
|
+
commentsRooms.delete(room2);
|
|
647
720
|
}
|
|
648
721
|
client.leave(roomId);
|
|
649
722
|
};
|
|
@@ -847,46 +920,39 @@ function createRoomContext(client, options) {
|
|
|
847
920
|
}
|
|
848
921
|
function useLegacyKey(key) {
|
|
849
922
|
const room = useRoom();
|
|
850
|
-
const
|
|
923
|
+
const rootOrNull = useMutableStorageRoot();
|
|
851
924
|
const rerender = useRerender();
|
|
852
925
|
React2.useEffect(() => {
|
|
853
|
-
if (
|
|
926
|
+
if (rootOrNull === null) {
|
|
854
927
|
return;
|
|
855
928
|
}
|
|
856
|
-
|
|
929
|
+
const root = rootOrNull;
|
|
930
|
+
let unsubCurr;
|
|
931
|
+
let curr = root.get(key);
|
|
932
|
+
function subscribeToCurr() {
|
|
933
|
+
unsubCurr = isLiveNode(curr) ? room.subscribe(curr, rerender) : void 0;
|
|
934
|
+
}
|
|
857
935
|
function onRootChange() {
|
|
858
|
-
const
|
|
859
|
-
if (
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
liveValue,
|
|
864
|
-
// TODO: This is hiding a bug! If `liveValue` happens to be the string `"event"` this actually subscribes an event handler!
|
|
865
|
-
rerender
|
|
866
|
-
);
|
|
936
|
+
const newValue = root.get(key);
|
|
937
|
+
if (newValue !== curr) {
|
|
938
|
+
unsubCurr?.();
|
|
939
|
+
curr = newValue;
|
|
940
|
+
subscribeToCurr();
|
|
867
941
|
rerender();
|
|
868
942
|
}
|
|
869
943
|
}
|
|
870
|
-
|
|
871
|
-
liveValue,
|
|
872
|
-
// TODO: This is hiding a bug! If `liveValue` happens to be the string `"event"` this actually subscribes an event handler!
|
|
873
|
-
rerender
|
|
874
|
-
);
|
|
875
|
-
const unsubscribeRoot = room.subscribe(
|
|
876
|
-
root,
|
|
877
|
-
// TODO: This is hiding a bug! If `liveValue` happens to be the string `"event"` this actually subscribes an event handler!
|
|
878
|
-
onRootChange
|
|
879
|
-
);
|
|
944
|
+
subscribeToCurr();
|
|
880
945
|
rerender();
|
|
946
|
+
const unsubscribeRoot = room.subscribe(root, onRootChange);
|
|
881
947
|
return () => {
|
|
882
948
|
unsubscribeRoot();
|
|
883
|
-
|
|
949
|
+
unsubCurr?.();
|
|
884
950
|
};
|
|
885
|
-
}, [
|
|
886
|
-
if (
|
|
951
|
+
}, [rootOrNull, room, key, rerender]);
|
|
952
|
+
if (rootOrNull === null) {
|
|
887
953
|
return null;
|
|
888
954
|
} else {
|
|
889
|
-
return
|
|
955
|
+
return rootOrNull.get(key);
|
|
890
956
|
}
|
|
891
957
|
}
|
|
892
958
|
function useStorage(selector, isEqual) {
|
|
@@ -1006,10 +1072,10 @@ function createRoomContext(client, options) {
|
|
|
1006
1072
|
const commentsErrorEventSource = makeEventSource2();
|
|
1007
1073
|
const commentsRooms = /* @__PURE__ */ new Map();
|
|
1008
1074
|
function getCommentsRoom(room) {
|
|
1009
|
-
let commentsRoom = commentsRooms.get(room
|
|
1075
|
+
let commentsRoom = commentsRooms.get(room);
|
|
1010
1076
|
if (commentsRoom === void 0) {
|
|
1011
1077
|
commentsRoom = createCommentsRoom(room, commentsErrorEventSource);
|
|
1012
|
-
commentsRooms.set(room
|
|
1078
|
+
commentsRooms.set(room, commentsRoom);
|
|
1013
1079
|
}
|
|
1014
1080
|
return commentsRoom;
|
|
1015
1081
|
}
|