@korajs/react 1.0.0-beta.11 → 1.0.0-beta.13
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/README.md +48 -40
- package/dist/index.cjs +210 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +172 -5
- package/dist/index.d.ts +172 -5
- package/dist/index.js +207 -64
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -96,11 +96,36 @@ function useKoraContext() {
|
|
|
96
96
|
|
|
97
97
|
// src/context/auth-bound-kora-provider.ts
|
|
98
98
|
import { createElement as createElement2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
99
|
+
var SENSITIVE_METADATA_KEY = /token|secret|password|authorization|cookie/i;
|
|
100
|
+
function classifyKoraInitializationError(error) {
|
|
101
|
+
const candidate = error;
|
|
102
|
+
const message = typeof candidate?.message === "string" ? candidate.message : String(error);
|
|
103
|
+
const name = typeof candidate?.name === "string" ? candidate.name : "Error";
|
|
104
|
+
const cause = new Error(message);
|
|
105
|
+
cause.name = name;
|
|
106
|
+
if (typeof candidate?.stack === "string") cause.stack = candidate.stack;
|
|
107
|
+
let code = typeof candidate?.code === "string" ? candidate.code : "INITIALIZATION_FAILED";
|
|
108
|
+
if (code === "INITIALIZATION_FAILED" && cause.name === "QuotaExceededError") {
|
|
109
|
+
code = "STORAGE_QUOTA_EXCEEDED";
|
|
110
|
+
}
|
|
111
|
+
const metadata = {};
|
|
112
|
+
if (candidate?.context && typeof candidate.context === "object") {
|
|
113
|
+
for (const [key, value] of Object.entries(candidate.context)) {
|
|
114
|
+
if (SENSITIVE_METADATA_KEY.test(key)) continue;
|
|
115
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null) {
|
|
116
|
+
metadata[key] = value;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return { code, name: cause.name, message: cause.message, metadata, cause };
|
|
121
|
+
}
|
|
99
122
|
function AuthBoundKoraProvider({
|
|
100
123
|
authClient,
|
|
101
124
|
createApp,
|
|
102
125
|
signedOut = null,
|
|
126
|
+
locked,
|
|
103
127
|
fallback = null,
|
|
128
|
+
error: renderError,
|
|
104
129
|
children
|
|
105
130
|
}) {
|
|
106
131
|
const [app, setApp] = useState2(null);
|
|
@@ -112,6 +137,8 @@ function AuthBoundKoraProvider({
|
|
|
112
137
|
const activeUserId = useRef2(null);
|
|
113
138
|
const generation = useRef2(0);
|
|
114
139
|
const transition = useRef2(Promise.resolve());
|
|
140
|
+
const reconcileRef = useRef2(() => {
|
|
141
|
+
});
|
|
115
142
|
useEffect2(() => {
|
|
116
143
|
let disposed = false;
|
|
117
144
|
const reconcile = () => {
|
|
@@ -149,10 +176,18 @@ function AuthBoundKoraProvider({
|
|
|
149
176
|
setApp(created);
|
|
150
177
|
}).catch((error) => {
|
|
151
178
|
if (!disposed && currentGeneration === generation.current) {
|
|
152
|
-
|
|
179
|
+
void authClient.resolveSyncState?.().then((failedSession) => {
|
|
180
|
+
if (!disposed && currentGeneration === generation.current && failedSession?.state === "authenticated") {
|
|
181
|
+
setInitError({
|
|
182
|
+
error: classifyKoraInitializationError(error),
|
|
183
|
+
session: { userId: failedSession.userId }
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
});
|
|
153
187
|
}
|
|
154
188
|
});
|
|
155
189
|
};
|
|
190
|
+
reconcileRef.current = reconcile;
|
|
156
191
|
reconcile();
|
|
157
192
|
const unsubscribe = authClient.subscribe?.(reconcile) ?? (() => {
|
|
158
193
|
});
|
|
@@ -167,14 +202,22 @@ function AuthBoundKoraProvider({
|
|
|
167
202
|
};
|
|
168
203
|
}, [authClient]);
|
|
169
204
|
if (initError) {
|
|
205
|
+
if (renderError) {
|
|
206
|
+
return renderError({
|
|
207
|
+
error: initError.error,
|
|
208
|
+
session: initError.session,
|
|
209
|
+
retry: () => reconcileRef.current()
|
|
210
|
+
});
|
|
211
|
+
}
|
|
170
212
|
return createElement2(
|
|
171
213
|
"div",
|
|
172
214
|
{ style: { color: "red", padding: "1rem", fontFamily: "monospace" } },
|
|
173
215
|
createElement2("strong", null, "Kora initialization error: "),
|
|
174
|
-
initError.message
|
|
216
|
+
initError.error.message
|
|
175
217
|
);
|
|
176
218
|
}
|
|
177
219
|
if (state.state === "signed-out" || state.state === "anonymous") return signedOut;
|
|
220
|
+
if (state.state === "authenticated" && state.locked) return locked ?? signedOut;
|
|
178
221
|
if (!app) return fallback;
|
|
179
222
|
return createElement2(KoraProvider, { app, fallback }, children);
|
|
180
223
|
}
|
|
@@ -191,17 +234,24 @@ function useApp() {
|
|
|
191
234
|
}
|
|
192
235
|
|
|
193
236
|
// src/hooks/use-query.ts
|
|
194
|
-
import { assertQueryReady } from "@korajs/store";
|
|
195
|
-
import { useCallback, useEffect as useEffect3, useRef as useRef3, useState as useState3, useSyncExternalStore } from "react";
|
|
237
|
+
import { assertQueryReady, queryKey } from "@korajs/store";
|
|
238
|
+
import { useCallback, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef3, useState as useState3, useSyncExternalStore } from "react";
|
|
196
239
|
var EMPTY_ARRAY = Object.freeze([]);
|
|
197
240
|
var noopSubscribe = (_onStoreChange) => {
|
|
198
241
|
return () => {
|
|
199
242
|
};
|
|
200
243
|
};
|
|
201
|
-
|
|
244
|
+
var getServerSnapshot = () => EMPTY_ARRAY;
|
|
245
|
+
var getNoError = () => null;
|
|
246
|
+
function readQueryError(queryStore) {
|
|
247
|
+
if (!queryStore) return null;
|
|
248
|
+
const channel = queryStore;
|
|
249
|
+
return typeof channel.getError === "function" ? channel.getError() : null;
|
|
250
|
+
}
|
|
251
|
+
function useQuerySubscription(query, options) {
|
|
202
252
|
const { queryStoreCache } = useKoraContext();
|
|
203
253
|
const enabled = options?.enabled !== false;
|
|
204
|
-
const descriptorKey =
|
|
254
|
+
const descriptorKey = queryKey(query.getDescriptor());
|
|
205
255
|
const queryRef = useRef3(query);
|
|
206
256
|
queryRef.current = query;
|
|
207
257
|
const lastSnapshotRef = useRef3(EMPTY_ARRAY);
|
|
@@ -219,122 +269,204 @@ function useQuery(query, options) {
|
|
|
219
269
|
queryStoreCache.release(currentQuery);
|
|
220
270
|
};
|
|
221
271
|
}, [descriptorKey, enabled, queryStoreCache]);
|
|
272
|
+
const subscribe = enabled && queryStore ? queryStore.subscribe : noopSubscribe;
|
|
222
273
|
const getSnapshot = useCallback(() => {
|
|
223
274
|
if (!enabled) {
|
|
224
275
|
lastSnapshotRef.current = EMPTY_ARRAY;
|
|
225
276
|
return lastSnapshotRef.current;
|
|
226
277
|
}
|
|
227
|
-
if (!queryStore) {
|
|
228
|
-
return lastSnapshotRef.current;
|
|
229
|
-
}
|
|
230
|
-
if (!queryStore.hasSnapshot()) {
|
|
278
|
+
if (!queryStore || !queryStore.hasSnapshot()) {
|
|
231
279
|
return lastSnapshotRef.current;
|
|
232
280
|
}
|
|
233
281
|
const snapshot = queryStore.getSnapshot();
|
|
234
282
|
lastSnapshotRef.current = snapshot;
|
|
235
283
|
return snapshot;
|
|
236
284
|
}, [enabled, queryStore]);
|
|
237
|
-
|
|
285
|
+
const getError = useCallback(
|
|
286
|
+
() => enabled ? readQueryError(queryStore) : null,
|
|
287
|
+
[enabled, queryStore]
|
|
288
|
+
);
|
|
289
|
+
const data = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
290
|
+
const error = useSyncExternalStore(subscribe, getError, getNoError);
|
|
291
|
+
const ready = enabled && queryStore !== null && queryStore.hasSnapshot();
|
|
292
|
+
return { data, error, ready };
|
|
293
|
+
}
|
|
294
|
+
function useQuery(query, options) {
|
|
295
|
+
const { data, error } = useQuerySubscription(query, options);
|
|
296
|
+
if (error && options?.throwOnError !== false) {
|
|
297
|
+
throw error;
|
|
298
|
+
}
|
|
299
|
+
return data;
|
|
300
|
+
}
|
|
301
|
+
function useQueryState(query, options) {
|
|
302
|
+
const { data, error, ready } = useQuerySubscription(query, options);
|
|
303
|
+
return useMemo2(() => ({ data, error, ready }), [data, error, ready]);
|
|
238
304
|
}
|
|
239
305
|
|
|
306
|
+
// src/hooks/create-kora-hooks.ts
|
|
307
|
+
import { useMemo as useMemo4 } from "react";
|
|
308
|
+
|
|
240
309
|
// src/hooks/use-mutation.ts
|
|
241
310
|
import { createMutationController } from "@korajs/core/bindings";
|
|
242
|
-
import { useRef as useRef5, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
311
|
+
import { useCallback as useCallback2, useMemo as useMemo3, useRef as useRef5, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
243
312
|
|
|
244
313
|
// src/hooks/use-controller.ts
|
|
245
314
|
import { useEffect as useEffect4, useReducer, useRef as useRef4 } from "react";
|
|
315
|
+
var ORPHAN_REAP_MS = 1e3;
|
|
246
316
|
function useController(create, destroy, deps) {
|
|
247
|
-
const
|
|
317
|
+
const entryRef = useRef4(null);
|
|
248
318
|
const createRef = useRef4(create);
|
|
249
319
|
createRef.current = create;
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
320
|
+
const destroyRef = useRef4(destroy);
|
|
321
|
+
destroyRef.current = destroy;
|
|
322
|
+
const [version, bumpVersion] = useReducer((count) => count + 1, 0);
|
|
323
|
+
const handle = useRef4({
|
|
324
|
+
get: () => {
|
|
325
|
+
const current = entryRef.current;
|
|
326
|
+
if (current !== null && !current.reaped) {
|
|
327
|
+
return current.controller;
|
|
328
|
+
}
|
|
329
|
+
const entry = {
|
|
330
|
+
controller: createRef.current(),
|
|
331
|
+
claimed: false,
|
|
332
|
+
reaped: false
|
|
333
|
+
};
|
|
334
|
+
entryRef.current = entry;
|
|
335
|
+
setTimeout(() => {
|
|
336
|
+
if (!entry.claimed && !entry.reaped) {
|
|
337
|
+
entry.reaped = true;
|
|
338
|
+
destroyRef.current(entry.controller);
|
|
339
|
+
}
|
|
340
|
+
}, ORPHAN_REAP_MS);
|
|
341
|
+
return entry.controller;
|
|
342
|
+
},
|
|
343
|
+
peek: () => {
|
|
344
|
+
const current = entryRef.current;
|
|
345
|
+
return current?.claimed && !current.reaped ? current.controller : null;
|
|
254
346
|
}
|
|
255
|
-
return controllerRef.current;
|
|
256
347
|
}).current;
|
|
257
348
|
useEffect4(() => {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
349
|
+
const current = entryRef.current;
|
|
350
|
+
if (current !== null && !current.reaped && !current.claimed) {
|
|
351
|
+
current.claimed = true;
|
|
352
|
+
} else if (current === null || current.reaped) {
|
|
353
|
+
entryRef.current = { controller: createRef.current(), claimed: true, reaped: false };
|
|
354
|
+
bumpVersion();
|
|
261
355
|
}
|
|
262
356
|
return () => {
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
if (
|
|
266
|
-
|
|
357
|
+
const entry = entryRef.current;
|
|
358
|
+
entryRef.current = null;
|
|
359
|
+
if (entry !== null && !entry.reaped) {
|
|
360
|
+
entry.reaped = true;
|
|
361
|
+
destroyRef.current(entry.controller);
|
|
267
362
|
}
|
|
268
363
|
};
|
|
269
364
|
}, deps);
|
|
270
|
-
return
|
|
365
|
+
return { get: handle.get, peek: handle.peek, version };
|
|
271
366
|
}
|
|
272
367
|
|
|
273
368
|
// src/hooks/use-mutation.ts
|
|
369
|
+
var IDLE = Object.freeze({ isLoading: false, error: null });
|
|
370
|
+
var getServerSnapshot2 = () => IDLE;
|
|
274
371
|
function useMutation(mutationFn, options) {
|
|
275
372
|
const fnRef = useRef5(mutationFn);
|
|
276
373
|
fnRef.current = mutationFn;
|
|
277
374
|
const optionsRef = useRef5(options);
|
|
278
375
|
optionsRef.current = options;
|
|
279
|
-
const
|
|
376
|
+
const controller = useController(
|
|
280
377
|
() => createMutationController({
|
|
281
378
|
mutationFn: (...args) => fnRef.current(...args),
|
|
282
379
|
resolveOptions: () => optionsRef.current
|
|
283
380
|
}),
|
|
284
|
-
(
|
|
381
|
+
(instance) => instance.destroy(),
|
|
285
382
|
[]
|
|
286
383
|
);
|
|
287
|
-
const
|
|
384
|
+
const getController = controller.get;
|
|
385
|
+
const subscribe = useCallback2(
|
|
288
386
|
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
289
|
-
|
|
290
|
-
|
|
387
|
+
[getController, controller.version]
|
|
388
|
+
);
|
|
389
|
+
const getSnapshot = useCallback2(() => getController().getSnapshot(), [getController]);
|
|
390
|
+
const state = useSyncExternalStore2(subscribe, getSnapshot, getServerSnapshot2);
|
|
391
|
+
const mutate = useCallback2((...args) => getController().mutate(...args), [getController]);
|
|
392
|
+
const mutateAsync = useCallback2(
|
|
393
|
+
(...args) => getController().mutateAsync(...args),
|
|
394
|
+
[getController]
|
|
395
|
+
);
|
|
396
|
+
const reset = useCallback2(() => getController().reset(), [getController]);
|
|
397
|
+
return useMemo3(
|
|
398
|
+
() => ({ mutate, mutateAsync, isLoading: state.isLoading, error: state.error, reset }),
|
|
399
|
+
[mutate, mutateAsync, reset, state.isLoading, state.error]
|
|
291
400
|
);
|
|
292
|
-
return {
|
|
293
|
-
mutate: (...args) => getController().mutate(...args),
|
|
294
|
-
mutateAsync: (...args) => getController().mutateAsync(...args),
|
|
295
|
-
isLoading: state.isLoading,
|
|
296
|
-
error: state.error,
|
|
297
|
-
reset: () => getController().reset()
|
|
298
|
-
};
|
|
299
401
|
}
|
|
300
402
|
|
|
301
403
|
// src/hooks/use-sync-status.ts
|
|
302
|
-
import { createSyncStatusController } from "@korajs/sync";
|
|
303
|
-
import { useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
404
|
+
import { OFFLINE_SYNC_STATUS, createSyncStatusController } from "@korajs/sync";
|
|
405
|
+
import { useCallback as useCallback3, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
406
|
+
var getServerSnapshot3 = () => OFFLINE_SYNC_STATUS;
|
|
304
407
|
function useSyncStatus() {
|
|
305
408
|
const { syncEngine, subscribeSyncStatus, events } = useKoraContext();
|
|
306
|
-
const
|
|
409
|
+
const controller = useController(
|
|
307
410
|
() => createSyncStatusController({
|
|
308
411
|
syncEngine,
|
|
309
412
|
subscribeSyncStatus,
|
|
310
413
|
events: subscribeSyncStatus ? null : events
|
|
311
414
|
}),
|
|
312
|
-
(
|
|
415
|
+
(instance) => instance.destroy(),
|
|
313
416
|
[syncEngine, subscribeSyncStatus, events]
|
|
314
417
|
);
|
|
315
|
-
|
|
418
|
+
const getController = controller.get;
|
|
419
|
+
const subscribe = useCallback3(
|
|
316
420
|
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
317
|
-
|
|
318
|
-
|
|
421
|
+
[getController, controller.version]
|
|
422
|
+
);
|
|
423
|
+
const peek = controller.peek;
|
|
424
|
+
const getSnapshot = useCallback3(
|
|
425
|
+
() => peek()?.getSnapshot() ?? OFFLINE_SYNC_STATUS,
|
|
426
|
+
[peek]
|
|
319
427
|
);
|
|
428
|
+
return useSyncExternalStore3(subscribe, getSnapshot, getServerSnapshot3);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// src/hooks/create-kora-hooks.ts
|
|
432
|
+
function createKoraHooks() {
|
|
433
|
+
function useTypedApp() {
|
|
434
|
+
return useApp();
|
|
435
|
+
}
|
|
436
|
+
function useTypedCollection(name) {
|
|
437
|
+
const { app, store } = useKoraContext();
|
|
438
|
+
return useMemo4(() => {
|
|
439
|
+
const collections = app?.collections;
|
|
440
|
+
const accessor = collections && name in collections ? collections[name] : store.collection(name);
|
|
441
|
+
return accessor;
|
|
442
|
+
}, [app, store, name]);
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
useApp: useTypedApp,
|
|
446
|
+
useCollection: useTypedCollection,
|
|
447
|
+
useQuery,
|
|
448
|
+
useQueryState,
|
|
449
|
+
useMutation,
|
|
450
|
+
useSyncStatus
|
|
451
|
+
};
|
|
320
452
|
}
|
|
321
453
|
|
|
322
454
|
// src/hooks/use-collection.ts
|
|
323
|
-
import { useMemo as
|
|
455
|
+
import { useMemo as useMemo5 } from "react";
|
|
324
456
|
function useCollection(name) {
|
|
325
457
|
const { store } = useKoraContext();
|
|
326
|
-
return
|
|
458
|
+
return useMemo5(() => {
|
|
327
459
|
return store.collection(name);
|
|
328
460
|
}, [store, name]);
|
|
329
461
|
}
|
|
330
462
|
|
|
331
463
|
// src/hooks/use-rich-text.ts
|
|
332
464
|
import { asRichTextSyncEngine, createRichTextController } from "@korajs/store";
|
|
333
|
-
import { useCallback as
|
|
465
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo6, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
334
466
|
function useRichText(collectionName, recordId, fieldName, options) {
|
|
335
467
|
const { store, syncEngine } = useKoraContext();
|
|
336
|
-
const collection =
|
|
337
|
-
const
|
|
468
|
+
const collection = useMemo6(() => store.collection(collectionName), [store, collectionName]);
|
|
469
|
+
const controller = useController(
|
|
338
470
|
() => createRichTextController({
|
|
339
471
|
collection,
|
|
340
472
|
collectionName,
|
|
@@ -345,29 +477,35 @@ function useRichText(collectionName, recordId, fieldName, options) {
|
|
|
345
477
|
useDocChannel: options?.useDocChannel,
|
|
346
478
|
user: options?.user
|
|
347
479
|
}),
|
|
348
|
-
(
|
|
480
|
+
(instance) => instance.destroy(),
|
|
349
481
|
[collection, collectionName, fieldName, options?.useDocChannel, recordId, store, syncEngine]
|
|
350
482
|
);
|
|
483
|
+
const getController = controller.get;
|
|
351
484
|
useEffect5(() => {
|
|
352
485
|
getController().setUser(options?.user);
|
|
353
|
-
}, [getController, options?.user]);
|
|
354
|
-
const
|
|
486
|
+
}, [getController, options?.user, controller.version]);
|
|
487
|
+
const subscribe = useCallback4(
|
|
355
488
|
(onStoreChange) => getController().subscribe(onStoreChange),
|
|
356
|
-
|
|
357
|
-
() => getController().getSnapshot()
|
|
489
|
+
[getController, controller.version]
|
|
358
490
|
);
|
|
359
|
-
const
|
|
491
|
+
const getSnapshot = useCallback4(() => getController().getSnapshot(), [getController]);
|
|
492
|
+
const snapshot = useSyncExternalStore4(subscribe, getSnapshot, getSnapshot);
|
|
493
|
+
const undo = useCallback4(() => {
|
|
360
494
|
getController().undo();
|
|
361
495
|
}, [getController]);
|
|
362
|
-
const redo =
|
|
496
|
+
const redo = useCallback4(() => {
|
|
363
497
|
getController().redo();
|
|
364
498
|
}, [getController]);
|
|
365
|
-
const setCursor =
|
|
499
|
+
const setCursor = useCallback4(
|
|
366
500
|
(anchor, head) => getController().setCursor(anchor, head),
|
|
367
501
|
[getController]
|
|
368
502
|
);
|
|
369
|
-
const clearCursor =
|
|
370
|
-
|
|
503
|
+
const clearCursor = useCallback4(() => getController().clearCursor(), [getController]);
|
|
504
|
+
const live = getController();
|
|
505
|
+
return useMemo6(
|
|
506
|
+
() => buildResult(live, snapshot, undo, redo, setCursor, clearCursor),
|
|
507
|
+
[live, snapshot, undo, redo, setCursor, clearCursor, controller.version]
|
|
508
|
+
);
|
|
371
509
|
}
|
|
372
510
|
function buildResult(controller, snapshot, undo, redo, setCursor, clearCursor) {
|
|
373
511
|
return {
|
|
@@ -406,12 +544,13 @@ function usePresence(user) {
|
|
|
406
544
|
|
|
407
545
|
// src/hooks/use-collaborators.ts
|
|
408
546
|
import { subscribeRemoteAwarenessStates } from "@korajs/sync";
|
|
409
|
-
import { useCallback as
|
|
547
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useRef as useRef6, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
410
548
|
var EMPTY_ARRAY2 = [];
|
|
549
|
+
var getServerSnapshot4 = () => EMPTY_ARRAY2;
|
|
411
550
|
function useCollaborators() {
|
|
412
551
|
const { syncEngine } = useKoraContext();
|
|
413
552
|
const snapshotRef = useRef6(EMPTY_ARRAY2);
|
|
414
|
-
const subscribe =
|
|
553
|
+
const subscribe = useCallback5(
|
|
415
554
|
(onStoreChange) => {
|
|
416
555
|
if (!syncEngine) {
|
|
417
556
|
snapshotRef.current = EMPTY_ARRAY2;
|
|
@@ -419,6 +558,7 @@ function useCollaborators() {
|
|
|
419
558
|
};
|
|
420
559
|
}
|
|
421
560
|
const awareness = syncEngine.getAwarenessManager();
|
|
561
|
+
snapshotRef.current = EMPTY_ARRAY2;
|
|
422
562
|
return subscribeRemoteAwarenessStates(awareness, (states) => {
|
|
423
563
|
snapshotRef.current = states;
|
|
424
564
|
onStoreChange();
|
|
@@ -426,23 +566,26 @@ function useCollaborators() {
|
|
|
426
566
|
},
|
|
427
567
|
[syncEngine]
|
|
428
568
|
);
|
|
429
|
-
const getSnapshot =
|
|
569
|
+
const getSnapshot = useCallback5(() => snapshotRef.current, []);
|
|
430
570
|
useEffect7(() => {
|
|
431
571
|
if (!syncEngine) {
|
|
432
572
|
snapshotRef.current = EMPTY_ARRAY2;
|
|
433
573
|
}
|
|
434
574
|
}, [syncEngine]);
|
|
435
|
-
return useSyncExternalStore5(subscribe, getSnapshot);
|
|
575
|
+
return useSyncExternalStore5(subscribe, getSnapshot, getServerSnapshot4);
|
|
436
576
|
}
|
|
437
577
|
export {
|
|
438
578
|
AuthBoundKoraProvider,
|
|
439
579
|
KoraProvider,
|
|
580
|
+
classifyKoraInitializationError,
|
|
581
|
+
createKoraHooks,
|
|
440
582
|
useApp,
|
|
441
583
|
useCollaborators,
|
|
442
584
|
useCollection,
|
|
443
585
|
useMutation,
|
|
444
586
|
usePresence,
|
|
445
587
|
useQuery,
|
|
588
|
+
useQueryState,
|
|
446
589
|
useRichText,
|
|
447
590
|
useSyncStatus
|
|
448
591
|
};
|