@liveblocks/react 2.8.3-tiptap1 → 2.8.3-tiptap2
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/{chunk-3DYM4PT5.js → chunk-43VHOLHH.js} +747 -697
- package/dist/chunk-43VHOLHH.js.map +1 -0
- package/dist/{chunk-464Q66DF.mjs → chunk-BNSPCUSO.mjs} +750 -700
- package/dist/chunk-BNSPCUSO.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/{suspense-DJOhRXB2.d.mts → suspense-fYGGJ3D9.d.mts} +71 -33
- package/dist/{suspense-DJOhRXB2.d.ts → suspense-fYGGJ3D9.d.ts} +71 -33
- package/dist/suspense.d.mts +1 -1
- package/dist/suspense.d.ts +1 -1
- package/dist/suspense.js +3 -3
- package/dist/suspense.mjs +1 -1
- package/package.json +3 -3
- package/dist/chunk-3DYM4PT5.js.map +0 -1
- package/dist/chunk-464Q66DF.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
2
|
var PKG_NAME = "@liveblocks/react";
|
|
3
|
-
var PKG_VERSION = "2.8.3-
|
|
3
|
+
var PKG_VERSION = "2.8.3-tiptap2";
|
|
4
4
|
var PKG_FORMAT = "esm";
|
|
5
5
|
|
|
6
6
|
// src/ClientSideSuspense.tsx
|
|
@@ -24,27 +24,37 @@ function useIsInsideRoom() {
|
|
|
24
24
|
return room !== null;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
// src/
|
|
27
|
+
// src/umbrella-store.ts
|
|
28
28
|
import {
|
|
29
|
-
assert,
|
|
30
29
|
autoRetry,
|
|
31
|
-
|
|
30
|
+
compactObject,
|
|
31
|
+
console as console2,
|
|
32
|
+
createStore,
|
|
32
33
|
kInternal,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
makeEventSource,
|
|
35
|
+
mapValues,
|
|
36
|
+
nanoid,
|
|
37
|
+
nn,
|
|
38
|
+
StopRetrying,
|
|
37
39
|
stringify
|
|
38
40
|
} from "@liveblocks/core";
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
|
|
42
|
+
// src/lib/autobind.ts
|
|
43
|
+
function autobind(self) {
|
|
44
|
+
const seen = /* @__PURE__ */ new Set();
|
|
45
|
+
seen.add("constructor");
|
|
46
|
+
let obj = self.constructor.prototype;
|
|
47
|
+
do {
|
|
48
|
+
for (const key of Reflect.ownKeys(obj)) {
|
|
49
|
+
if (seen.has(key)) continue;
|
|
50
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(obj, key);
|
|
51
|
+
if (typeof descriptor?.value === "function") {
|
|
52
|
+
seen.add(key);
|
|
53
|
+
self[key] = self[key].bind(self);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} while ((obj = Reflect.getPrototypeOf(obj)) && obj !== Object.prototype);
|
|
57
|
+
}
|
|
48
58
|
|
|
49
59
|
// src/lib/compare.ts
|
|
50
60
|
function byFirstCreated(a, b) {
|
|
@@ -54,7 +64,7 @@ function isMoreRecentlyUpdated(a, b) {
|
|
|
54
64
|
return byMostRecentlyUpdated(a, b) < 0;
|
|
55
65
|
}
|
|
56
66
|
function byMostRecentlyUpdated(a, b) {
|
|
57
|
-
return
|
|
67
|
+
return b.updatedAt.getTime() - a.updatedAt.getTime();
|
|
58
68
|
}
|
|
59
69
|
|
|
60
70
|
// src/lib/guards.ts
|
|
@@ -77,8 +87,11 @@ function matchesMetadata(thread, q) {
|
|
|
77
87
|
const metadata = thread.metadata;
|
|
78
88
|
return q.metadata === void 0 || Object.entries(q.metadata).every(
|
|
79
89
|
([key, op]) => (
|
|
80
|
-
//
|
|
81
|
-
|
|
90
|
+
// NOTE: `op` can be explicitly-`undefined` here, which ideally would not
|
|
91
|
+
// mean "filter for absence" like it does now, as this does not match the
|
|
92
|
+
// backend behavior at the moment. For an in-depth discussion, see
|
|
93
|
+
// https://liveblocks.slack.com/archives/C02PZL7QAAW/p1728546988505989
|
|
94
|
+
matchesOperator(metadata[key], op)
|
|
82
95
|
)
|
|
83
96
|
);
|
|
84
97
|
}
|
|
@@ -90,131 +103,204 @@ function matchesOperator(value, op) {
|
|
|
90
103
|
}
|
|
91
104
|
}
|
|
92
105
|
|
|
93
|
-
// src/
|
|
94
|
-
var
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (retryCount >= MAX_ERROR_RETRY_COUNT) return;
|
|
98
|
-
const timeout = Math.pow(2, retryCount) * ERROR_RETRY_INTERVAL;
|
|
99
|
-
setTimeout(() => {
|
|
100
|
-
void action();
|
|
101
|
-
}, timeout);
|
|
106
|
+
// src/umbrella-store.ts
|
|
107
|
+
var ASYNC_OK = Object.freeze({ isLoading: false, data: void 0 });
|
|
108
|
+
function makeRoomThreadsQueryKey(roomId, query) {
|
|
109
|
+
return `${roomId}-${stringify(query ?? {})}`;
|
|
102
110
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
|
|
111
|
+
function makeUserThreadsQueryKey(query) {
|
|
112
|
+
return `USER_THREADS:${stringify(query ?? {})}`;
|
|
113
|
+
}
|
|
114
|
+
function makeNotificationSettingsQueryKey(roomId) {
|
|
115
|
+
return `${roomId}:NOTIFICATION_SETTINGS`;
|
|
116
|
+
}
|
|
117
|
+
function makeVersionsQueryKey(roomId) {
|
|
118
|
+
return `${roomId}-VERSIONS`;
|
|
119
|
+
}
|
|
120
|
+
function selectThreads(state, options) {
|
|
121
|
+
let threads = state.threads;
|
|
122
|
+
if (options.roomId !== null) {
|
|
123
|
+
threads = threads.filter((thread) => thread.roomId === options.roomId);
|
|
109
124
|
}
|
|
110
|
-
const
|
|
111
|
-
if (
|
|
112
|
-
|
|
125
|
+
const query = options.query;
|
|
126
|
+
if (query) {
|
|
127
|
+
threads = threads.filter(makeThreadsFilter(query));
|
|
113
128
|
}
|
|
114
|
-
return
|
|
115
|
-
|
|
129
|
+
return threads.sort(
|
|
130
|
+
options.orderBy === "last-update" ? byMostRecentlyUpdated : byFirstCreated
|
|
116
131
|
);
|
|
117
132
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// src/lib/use-latest.ts
|
|
123
|
-
import { useEffect as useEffect2, useRef } from "react";
|
|
124
|
-
function useLatest(value) {
|
|
125
|
-
const ref = useRef(value);
|
|
126
|
-
useEffect2(() => {
|
|
127
|
-
ref.current = value;
|
|
128
|
-
}, [value]);
|
|
129
|
-
return ref;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// src/lib/use-initial.ts
|
|
133
|
-
var noop = (state) => state;
|
|
134
|
-
function useInitial(value) {
|
|
135
|
-
return useReducer(noop, value)[0];
|
|
136
|
-
}
|
|
137
|
-
function useInitialUnlessFunction(latestValue) {
|
|
138
|
-
const frozenValue = useInitial(latestValue);
|
|
139
|
-
if (typeof frozenValue === "function") {
|
|
140
|
-
const ref = useLatest(latestValue);
|
|
141
|
-
return useCallback((...args) => ref.current(...args), [
|
|
142
|
-
ref
|
|
143
|
-
]);
|
|
144
|
-
} else {
|
|
145
|
-
return frozenValue;
|
|
133
|
+
function usify(promise) {
|
|
134
|
+
if ("status" in promise) {
|
|
135
|
+
return promise;
|
|
146
136
|
}
|
|
137
|
+
const usable = promise;
|
|
138
|
+
usable.status = "pending";
|
|
139
|
+
usable.then(
|
|
140
|
+
(value) => {
|
|
141
|
+
usable.status = "fulfilled";
|
|
142
|
+
usable.value = value;
|
|
143
|
+
},
|
|
144
|
+
(err) => {
|
|
145
|
+
usable.status = "rejected";
|
|
146
|
+
usable.reason = err;
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
return usable;
|
|
147
150
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
var
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
151
|
+
var noop = Promise.resolve();
|
|
152
|
+
var ASYNC_LOADING = Object.freeze({ isLoading: true });
|
|
153
|
+
var PaginatedResource = class {
|
|
154
|
+
constructor(fetchPage) {
|
|
155
|
+
this._cachedPromise = null;
|
|
156
|
+
this._paginationState = null;
|
|
157
|
+
this._fetchPage = fetchPage;
|
|
158
|
+
this._eventSource = makeEventSource();
|
|
159
|
+
this._pendingFetchMore = null;
|
|
160
|
+
this.observable = this._eventSource.observable;
|
|
161
|
+
autobind(this);
|
|
162
|
+
}
|
|
163
|
+
patchPaginationState(patch) {
|
|
164
|
+
const state = this._paginationState;
|
|
165
|
+
if (state === null) return;
|
|
166
|
+
this._paginationState = { ...state, ...patch };
|
|
167
|
+
this._eventSource.notify();
|
|
168
|
+
}
|
|
169
|
+
async _fetchMore() {
|
|
170
|
+
const state = this._paginationState;
|
|
171
|
+
if (!state?.cursor) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
this.patchPaginationState({ isFetchingMore: true });
|
|
175
|
+
try {
|
|
176
|
+
const nextCursor = await this._fetchPage(state.cursor);
|
|
177
|
+
this.patchPaginationState({
|
|
178
|
+
cursor: nextCursor,
|
|
179
|
+
fetchMoreError: void 0,
|
|
180
|
+
isFetchingMore: false
|
|
181
|
+
});
|
|
182
|
+
} catch (err) {
|
|
183
|
+
this.patchPaginationState({
|
|
184
|
+
isFetchingMore: false,
|
|
185
|
+
fetchMoreError: err
|
|
186
|
+
});
|
|
172
187
|
}
|
|
173
188
|
}
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
189
|
+
fetchMore() {
|
|
190
|
+
const state = this._paginationState;
|
|
191
|
+
if (state?.cursor === null) {
|
|
192
|
+
return noop;
|
|
193
|
+
}
|
|
194
|
+
if (!this._pendingFetchMore) {
|
|
195
|
+
this._pendingFetchMore = this._fetchMore().finally(() => {
|
|
196
|
+
this._pendingFetchMore = null;
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return this._pendingFetchMore;
|
|
200
|
+
}
|
|
201
|
+
get() {
|
|
202
|
+
const usable = this._cachedPromise;
|
|
203
|
+
if (usable === null || usable.status === "pending") {
|
|
204
|
+
return ASYNC_LOADING;
|
|
205
|
+
}
|
|
206
|
+
if (usable.status === "rejected") {
|
|
207
|
+
return { isLoading: false, error: usable.reason };
|
|
208
|
+
}
|
|
209
|
+
const state = this._paginationState;
|
|
210
|
+
return {
|
|
211
|
+
isLoading: false,
|
|
212
|
+
data: {
|
|
213
|
+
fetchMore: this.fetchMore,
|
|
214
|
+
isFetchingMore: state.isFetchingMore,
|
|
215
|
+
fetchMoreError: state.fetchMoreError,
|
|
216
|
+
hasFetchedAll: state.cursor === null
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
waitUntilLoaded() {
|
|
221
|
+
if (this._cachedPromise) {
|
|
222
|
+
return this._cachedPromise;
|
|
223
|
+
}
|
|
224
|
+
const initialFetcher = autoRetry(
|
|
225
|
+
() => this._fetchPage(
|
|
226
|
+
/* cursor */
|
|
227
|
+
void 0
|
|
228
|
+
),
|
|
229
|
+
5,
|
|
230
|
+
[5e3, 5e3, 1e4, 15e3]
|
|
231
|
+
);
|
|
232
|
+
const promise = usify(
|
|
233
|
+
initialFetcher.then((cursor) => {
|
|
234
|
+
this._paginationState = {
|
|
235
|
+
cursor,
|
|
236
|
+
isFetchingMore: false,
|
|
237
|
+
fetchMoreError: void 0
|
|
238
|
+
};
|
|
239
|
+
})
|
|
240
|
+
);
|
|
241
|
+
promise.then(
|
|
242
|
+
() => this._eventSource.notify(),
|
|
243
|
+
() => {
|
|
244
|
+
this._eventSource.notify();
|
|
245
|
+
setTimeout(() => {
|
|
246
|
+
this._cachedPromise = null;
|
|
247
|
+
this._eventSource.notify();
|
|
248
|
+
}, 5e3);
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
this._cachedPromise = promise;
|
|
252
|
+
return promise;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
193
255
|
var UmbrellaStore = class {
|
|
194
|
-
constructor() {
|
|
256
|
+
constructor(client) {
|
|
195
257
|
this._prevState = null;
|
|
196
258
|
this._stateCached = null;
|
|
259
|
+
// Notifications
|
|
260
|
+
this._notificationsLastRequestedAt = null;
|
|
261
|
+
// Room Threads
|
|
262
|
+
this._roomThreadsLastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
263
|
+
this._roomThreads = /* @__PURE__ */ new Map();
|
|
264
|
+
// User Threads
|
|
265
|
+
this._userThreadsLastRequestedAt = null;
|
|
266
|
+
this._userThreads = /* @__PURE__ */ new Map();
|
|
267
|
+
const inboxFetcher = async (cursor) => {
|
|
268
|
+
if (client === void 0) {
|
|
269
|
+
throw new StopRetrying(
|
|
270
|
+
"Client is required in order to load threads for the room"
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
const result = await client.getInboxNotifications({ cursor });
|
|
274
|
+
this.updateThreadsAndNotifications(
|
|
275
|
+
result.threads,
|
|
276
|
+
// TODO: Figure out how to remove this casting
|
|
277
|
+
result.inboxNotifications
|
|
278
|
+
);
|
|
279
|
+
if (this._notificationsLastRequestedAt === null) {
|
|
280
|
+
this._notificationsLastRequestedAt = result.requestedAt;
|
|
281
|
+
}
|
|
282
|
+
const nextCursor = result.nextCursor;
|
|
283
|
+
return nextCursor;
|
|
284
|
+
};
|
|
285
|
+
this._client = client;
|
|
286
|
+
this._notifications = new PaginatedResource(inboxFetcher);
|
|
287
|
+
this._notifications.observable.subscribe(
|
|
288
|
+
() => (
|
|
289
|
+
// Note that the store itself does not change, but it's only vehicle at
|
|
290
|
+
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
291
|
+
this._store.set((store) => ({ ...store }))
|
|
292
|
+
)
|
|
293
|
+
);
|
|
197
294
|
this._store = createStore({
|
|
198
295
|
rawThreadsById: {},
|
|
199
|
-
// queries: {},
|
|
200
|
-
query1: void 0,
|
|
201
|
-
queries2: {},
|
|
202
296
|
queries3: {},
|
|
203
297
|
queries4: {},
|
|
204
298
|
optimisticUpdates: [],
|
|
205
|
-
|
|
206
|
-
|
|
299
|
+
notificationsById: {},
|
|
300
|
+
settingsByRoomId: {},
|
|
207
301
|
versionsByRoomId: {}
|
|
208
302
|
});
|
|
209
|
-
|
|
210
|
-
this.getInboxNotificationsAsync = this.getInboxNotificationsAsync.bind(this);
|
|
211
|
-
this.subscribeThreads = this.subscribeThreads.bind(this);
|
|
212
|
-
this.subscribeUserThreads = this.subscribeUserThreads.bind(this);
|
|
213
|
-
this.subscribeThreadsOrInboxNotifications = this.subscribeThreadsOrInboxNotifications.bind(this);
|
|
214
|
-
this.subscribeNotificationSettings = this.subscribeNotificationSettings.bind(this);
|
|
215
|
-
this.subscribeVersions = this.subscribeVersions.bind(this);
|
|
216
|
-
this._hasOptimisticUpdates = this._hasOptimisticUpdates.bind(this);
|
|
217
|
-
this._subscribeOptimisticUpdates = this._subscribeOptimisticUpdates.bind(this);
|
|
303
|
+
autobind(this);
|
|
218
304
|
}
|
|
219
305
|
get() {
|
|
220
306
|
const rawState = this._store.get();
|
|
@@ -231,45 +317,79 @@ var UmbrellaStore = class {
|
|
|
231
317
|
return this.get();
|
|
232
318
|
}
|
|
233
319
|
/**
|
|
234
|
-
* Returns the async result of the given
|
|
235
|
-
* then it will return the
|
|
320
|
+
* Returns the async result of the given query and room id. If the query is success,
|
|
321
|
+
* then it will return the threads that match that provided query and room id.
|
|
322
|
+
*
|
|
236
323
|
*/
|
|
237
|
-
//
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
if (query === void 0 || query.isLoading) {
|
|
324
|
+
// XXXX Find a better name for that doesn't associate to 'async'
|
|
325
|
+
getRoomThreadsAsync(roomId, query) {
|
|
326
|
+
const queryKey = makeRoomThreadsQueryKey(roomId, query);
|
|
327
|
+
const paginatedResource = this._roomThreads.get(queryKey);
|
|
328
|
+
if (paginatedResource === void 0) {
|
|
243
329
|
return ASYNC_LOADING;
|
|
244
330
|
}
|
|
245
|
-
|
|
246
|
-
|
|
331
|
+
const asyncResult = paginatedResource.get();
|
|
332
|
+
if (asyncResult.isLoading || asyncResult.error) {
|
|
333
|
+
return asyncResult;
|
|
247
334
|
}
|
|
248
|
-
|
|
335
|
+
const threads = selectThreads(this.getFullState(), {
|
|
336
|
+
roomId,
|
|
337
|
+
query,
|
|
338
|
+
orderBy: "age"
|
|
339
|
+
});
|
|
340
|
+
const page = asyncResult.data;
|
|
341
|
+
return {
|
|
342
|
+
isLoading: false,
|
|
343
|
+
threads,
|
|
344
|
+
hasFetchedAll: page.hasFetchedAll,
|
|
345
|
+
isFetchingMore: page.isFetchingMore,
|
|
346
|
+
fetchMoreError: page.fetchMoreError,
|
|
347
|
+
fetchMore: page.fetchMore
|
|
348
|
+
};
|
|
249
349
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
|
|
350
|
+
// XXXX - Find a better name for that doesn't associate to 'async'
|
|
351
|
+
getUserThreadsAsync(query) {
|
|
352
|
+
const queryKey = makeUserThreadsQueryKey(query);
|
|
353
|
+
const paginatedResource = this._userThreads.get(queryKey);
|
|
354
|
+
if (paginatedResource === void 0) {
|
|
254
355
|
return ASYNC_LOADING;
|
|
255
356
|
}
|
|
256
|
-
|
|
257
|
-
|
|
357
|
+
const asyncResult = paginatedResource.get();
|
|
358
|
+
if (asyncResult.isLoading || asyncResult.error) {
|
|
359
|
+
return asyncResult;
|
|
258
360
|
}
|
|
259
|
-
|
|
361
|
+
const threads = selectThreads(this.getFullState(), {
|
|
362
|
+
roomId: null,
|
|
363
|
+
// Do _not_ filter by roomId
|
|
364
|
+
query,
|
|
365
|
+
orderBy: "last-update"
|
|
366
|
+
});
|
|
367
|
+
const page = asyncResult.data;
|
|
368
|
+
return {
|
|
369
|
+
isLoading: false,
|
|
370
|
+
threads,
|
|
371
|
+
hasFetchedAll: page.hasFetchedAll,
|
|
372
|
+
isFetchingMore: page.isFetchingMore,
|
|
373
|
+
fetchMoreError: page.fetchMoreError,
|
|
374
|
+
fetchMore: page.fetchMore
|
|
375
|
+
};
|
|
260
376
|
}
|
|
261
377
|
// NOTE: This will read the async result, but WILL NOT start loading at the moment!
|
|
378
|
+
// XXXX - Find a better name for that doesn't associate to 'async'
|
|
262
379
|
getInboxNotificationsAsync() {
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return ASYNC_LOADING;
|
|
380
|
+
const asyncResult = this._notifications.get();
|
|
381
|
+
if (asyncResult.isLoading || asyncResult.error) {
|
|
382
|
+
return asyncResult;
|
|
267
383
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
384
|
+
const page = asyncResult.data;
|
|
385
|
+
return {
|
|
386
|
+
isLoading: false,
|
|
387
|
+
inboxNotifications: this.getFullState().notifications,
|
|
388
|
+
hasFetchedAll: page.hasFetchedAll,
|
|
389
|
+
isFetchingMore: page.isFetchingMore,
|
|
390
|
+
fetchMoreError: page.fetchMoreError,
|
|
391
|
+
fetchMore: page.fetchMore
|
|
392
|
+
};
|
|
273
393
|
}
|
|
274
394
|
// NOTE: This will read the async result, but WILL NOT start loading at the moment!
|
|
275
395
|
getNotificationSettingsAsync(roomId) {
|
|
@@ -283,7 +403,7 @@ var UmbrellaStore = class {
|
|
|
283
403
|
}
|
|
284
404
|
return {
|
|
285
405
|
isLoading: false,
|
|
286
|
-
settings: nn(state.
|
|
406
|
+
settings: nn(state.settingsByRoomId[roomId])
|
|
287
407
|
};
|
|
288
408
|
}
|
|
289
409
|
getVersionsAsync(roomId) {
|
|
@@ -339,15 +459,15 @@ var UmbrellaStore = class {
|
|
|
339
459
|
}
|
|
340
460
|
updateInboxNotificationsCache(mapFn) {
|
|
341
461
|
this._store.set((state) => {
|
|
342
|
-
const inboxNotifications = mapFn(state.
|
|
343
|
-
return inboxNotifications !== state.
|
|
462
|
+
const inboxNotifications = mapFn(state.notificationsById);
|
|
463
|
+
return inboxNotifications !== state.notificationsById ? { ...state, notificationsById: inboxNotifications } : state;
|
|
344
464
|
});
|
|
345
465
|
}
|
|
346
466
|
setNotificationSettings(roomId, settings) {
|
|
347
467
|
this._store.set((state) => ({
|
|
348
468
|
...state,
|
|
349
|
-
|
|
350
|
-
...state.
|
|
469
|
+
settingsByRoomId: {
|
|
470
|
+
...state.settingsByRoomId,
|
|
351
471
|
[roomId]: settings
|
|
352
472
|
}
|
|
353
473
|
}));
|
|
@@ -361,21 +481,6 @@ var UmbrellaStore = class {
|
|
|
361
481
|
}
|
|
362
482
|
}));
|
|
363
483
|
}
|
|
364
|
-
setQuery1State(queryState) {
|
|
365
|
-
this._store.set((state) => ({
|
|
366
|
-
...state,
|
|
367
|
-
query1: queryState
|
|
368
|
-
}));
|
|
369
|
-
}
|
|
370
|
-
setQuery2State(queryKey, queryState) {
|
|
371
|
-
this._store.set((state) => ({
|
|
372
|
-
...state,
|
|
373
|
-
queries2: {
|
|
374
|
-
...state.queries2,
|
|
375
|
-
[queryKey]: queryState
|
|
376
|
-
}
|
|
377
|
-
}));
|
|
378
|
-
}
|
|
379
484
|
setQuery3State(queryKey, queryState) {
|
|
380
485
|
this._store.set((state) => ({
|
|
381
486
|
...state,
|
|
@@ -493,7 +598,7 @@ var UmbrellaStore = class {
|
|
|
493
598
|
if (existing.deletedAt !== void 0) {
|
|
494
599
|
return cache;
|
|
495
600
|
}
|
|
496
|
-
if (!!updatedAt &&
|
|
601
|
+
if (!!updatedAt && existing.updatedAt > updatedAt) {
|
|
497
602
|
return cache;
|
|
498
603
|
}
|
|
499
604
|
return { ...cache, [threadId]: callback(existing) };
|
|
@@ -602,7 +707,7 @@ var UmbrellaStore = class {
|
|
|
602
707
|
}
|
|
603
708
|
});
|
|
604
709
|
}
|
|
605
|
-
updateThreadsAndNotifications(threads, inboxNotifications, deletedThreads, deletedInboxNotifications) {
|
|
710
|
+
updateThreadsAndNotifications(threads, inboxNotifications, deletedThreads = [], deletedInboxNotifications = []) {
|
|
606
711
|
this._store.batch(() => {
|
|
607
712
|
this.updateThreadsCache(
|
|
608
713
|
(cache) => applyThreadUpdates(cache, {
|
|
@@ -622,12 +727,14 @@ var UmbrellaStore = class {
|
|
|
622
727
|
* Updates existing notification setting for a room with a new value,
|
|
623
728
|
* replacing the corresponding optimistic update.
|
|
624
729
|
*/
|
|
730
|
+
// XXXX Rename this helper method
|
|
625
731
|
updateRoomInboxNotificationSettings2(roomId, optimisticUpdateId, settings) {
|
|
626
732
|
this._store.batch(() => {
|
|
627
733
|
this.removeOptimisticUpdate(optimisticUpdateId);
|
|
628
734
|
this.setNotificationSettings(roomId, settings);
|
|
629
735
|
});
|
|
630
736
|
}
|
|
737
|
+
// XXXX Rename this helper method
|
|
631
738
|
updateRoomInboxNotificationSettings(roomId, settings, queryKey) {
|
|
632
739
|
this._store.batch(() => {
|
|
633
740
|
this.setQuery3OK(queryKey);
|
|
@@ -653,29 +760,6 @@ var UmbrellaStore = class {
|
|
|
653
760
|
(cache) => cache.filter((ou) => ou.id !== optimisticUpdateId)
|
|
654
761
|
);
|
|
655
762
|
}
|
|
656
|
-
//
|
|
657
|
-
// Query State APIs
|
|
658
|
-
//
|
|
659
|
-
// Query 1
|
|
660
|
-
setQuery1Loading() {
|
|
661
|
-
this.setQuery1State(ASYNC_LOADING);
|
|
662
|
-
}
|
|
663
|
-
setQuery1OK() {
|
|
664
|
-
this.setQuery1State(ASYNC_OK);
|
|
665
|
-
}
|
|
666
|
-
setQuery1Error(error) {
|
|
667
|
-
this.setQuery1State({ isLoading: false, error });
|
|
668
|
-
}
|
|
669
|
-
// Query 2
|
|
670
|
-
setQuery2Loading(queryKey) {
|
|
671
|
-
this.setQuery2State(queryKey, ASYNC_LOADING);
|
|
672
|
-
}
|
|
673
|
-
setQuery2OK(queryKey) {
|
|
674
|
-
this.setQuery2State(queryKey, ASYNC_OK);
|
|
675
|
-
}
|
|
676
|
-
setQuery2Error(queryKey, error) {
|
|
677
|
-
this.setQuery2State(queryKey, { isLoading: false, error });
|
|
678
|
-
}
|
|
679
763
|
// Query 3
|
|
680
764
|
setQuery3Loading(queryKey) {
|
|
681
765
|
this.setQuery3State(queryKey, ASYNC_LOADING);
|
|
@@ -696,12 +780,159 @@ var UmbrellaStore = class {
|
|
|
696
780
|
setQuery4Error(queryKey, error) {
|
|
697
781
|
this.setQuery4State(queryKey, { isLoading: false, error });
|
|
698
782
|
}
|
|
783
|
+
async fetchNotificationsDeltaUpdate() {
|
|
784
|
+
const lastRequestedAt = this._notificationsLastRequestedAt;
|
|
785
|
+
if (lastRequestedAt === null) {
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
const client = nn(
|
|
789
|
+
this._client,
|
|
790
|
+
"Client is required in order to load notifications for the room"
|
|
791
|
+
);
|
|
792
|
+
const result = await client.getInboxNotificationsSince(lastRequestedAt);
|
|
793
|
+
if (lastRequestedAt < result.requestedAt) {
|
|
794
|
+
this._notificationsLastRequestedAt = result.requestedAt;
|
|
795
|
+
}
|
|
796
|
+
this.updateThreadsAndNotifications(
|
|
797
|
+
result.threads.updated,
|
|
798
|
+
result.inboxNotifications.updated,
|
|
799
|
+
result.threads.deleted,
|
|
800
|
+
result.inboxNotifications.deleted
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
waitUntilNotificationsLoaded() {
|
|
804
|
+
return this._notifications.waitUntilLoaded();
|
|
805
|
+
}
|
|
806
|
+
waitUntilRoomThreadsLoaded(roomId, query) {
|
|
807
|
+
const threadsFetcher = async (cursor) => {
|
|
808
|
+
if (this._client === void 0) {
|
|
809
|
+
throw new StopRetrying(
|
|
810
|
+
"Client is required in order to load threads for the room"
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
const room = this._client.getRoom(roomId);
|
|
814
|
+
if (room === null) {
|
|
815
|
+
throw new StopRetrying(
|
|
816
|
+
`Room with id ${roomId} is not available on client`
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
const result = await room.getThreads({ cursor, query });
|
|
820
|
+
this.updateThreadsAndNotifications(
|
|
821
|
+
result.threads,
|
|
822
|
+
// TODO: Figure out how to remove this casting
|
|
823
|
+
result.inboxNotifications
|
|
824
|
+
);
|
|
825
|
+
const lastRequestedAt = this._roomThreadsLastRequestedAtByRoom.get(roomId);
|
|
826
|
+
if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
|
|
827
|
+
this._roomThreadsLastRequestedAtByRoom.set(roomId, result.requestedAt);
|
|
828
|
+
}
|
|
829
|
+
return result.nextCursor;
|
|
830
|
+
};
|
|
831
|
+
const queryKey = makeRoomThreadsQueryKey(roomId, query);
|
|
832
|
+
let paginatedResource = this._roomThreads.get(queryKey);
|
|
833
|
+
if (paginatedResource === void 0) {
|
|
834
|
+
paginatedResource = new PaginatedResource(threadsFetcher);
|
|
835
|
+
}
|
|
836
|
+
paginatedResource.observable.subscribe(
|
|
837
|
+
() => (
|
|
838
|
+
// Note that the store itself does not change, but it's only vehicle at
|
|
839
|
+
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
840
|
+
this._store.set((store) => ({ ...store }))
|
|
841
|
+
)
|
|
842
|
+
);
|
|
843
|
+
this._roomThreads.set(queryKey, paginatedResource);
|
|
844
|
+
return paginatedResource.waitUntilLoaded();
|
|
845
|
+
}
|
|
846
|
+
async fetchRoomThreadsDeltaUpdate(roomId) {
|
|
847
|
+
const lastRequestedAt = this._roomThreadsLastRequestedAtByRoom.get(roomId);
|
|
848
|
+
if (lastRequestedAt === void 0) {
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
const client = nn(
|
|
852
|
+
this._client,
|
|
853
|
+
"Client is required in order to load notifications for the room"
|
|
854
|
+
);
|
|
855
|
+
const room = nn(
|
|
856
|
+
client.getRoom(roomId),
|
|
857
|
+
`Room with id ${roomId} is not available on client`
|
|
858
|
+
);
|
|
859
|
+
const updates = await room.getThreadsSince({
|
|
860
|
+
since: lastRequestedAt
|
|
861
|
+
});
|
|
862
|
+
this.updateThreadsAndNotifications(
|
|
863
|
+
updates.threads.updated,
|
|
864
|
+
updates.inboxNotifications.updated,
|
|
865
|
+
updates.threads.deleted,
|
|
866
|
+
updates.inboxNotifications.deleted
|
|
867
|
+
);
|
|
868
|
+
if (lastRequestedAt < updates.requestedAt) {
|
|
869
|
+
this._roomThreadsLastRequestedAtByRoom.set(roomId, updates.requestedAt);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
waitUntilUserThreadsLoaded(query) {
|
|
873
|
+
const queryKey = makeUserThreadsQueryKey(query);
|
|
874
|
+
const threadsFetcher = async (cursor) => {
|
|
875
|
+
if (this._client === void 0) {
|
|
876
|
+
throw new StopRetrying(
|
|
877
|
+
"Client is required in order to load threads for the room"
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
const result = await this._client[kInternal].getUserThreads_experimental({
|
|
881
|
+
cursor,
|
|
882
|
+
query
|
|
883
|
+
});
|
|
884
|
+
this.updateThreadsAndNotifications(
|
|
885
|
+
result.threads,
|
|
886
|
+
// TODO: Figure out how to remove this casting
|
|
887
|
+
result.inboxNotifications
|
|
888
|
+
);
|
|
889
|
+
if (this._userThreadsLastRequestedAt === null) {
|
|
890
|
+
this._userThreadsLastRequestedAt = result.requestedAt;
|
|
891
|
+
}
|
|
892
|
+
return result.nextCursor;
|
|
893
|
+
};
|
|
894
|
+
let paginatedResource = this._userThreads.get(queryKey);
|
|
895
|
+
if (paginatedResource === void 0) {
|
|
896
|
+
paginatedResource = new PaginatedResource(threadsFetcher);
|
|
897
|
+
}
|
|
898
|
+
paginatedResource.observable.subscribe(
|
|
899
|
+
() => (
|
|
900
|
+
// Note that the store itself does not change, but it's only vehicle at
|
|
901
|
+
// the moment to trigger a re-render, so we'll do a no-op update here.
|
|
902
|
+
this._store.set((store) => ({ ...store }))
|
|
903
|
+
)
|
|
904
|
+
);
|
|
905
|
+
this._userThreads.set(queryKey, paginatedResource);
|
|
906
|
+
return paginatedResource.waitUntilLoaded();
|
|
907
|
+
}
|
|
908
|
+
async fetchUserThreadsDeltaUpdate() {
|
|
909
|
+
const lastRequestedAt = this._userThreadsLastRequestedAt;
|
|
910
|
+
if (lastRequestedAt === null) {
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
const client = nn(
|
|
914
|
+
this._client,
|
|
915
|
+
"Client is required in order to load threads for the user"
|
|
916
|
+
);
|
|
917
|
+
const result = await client[kInternal].getUserThreadsSince_experimental({
|
|
918
|
+
since: lastRequestedAt
|
|
919
|
+
});
|
|
920
|
+
if (lastRequestedAt < result.requestedAt) {
|
|
921
|
+
this._notificationsLastRequestedAt = result.requestedAt;
|
|
922
|
+
}
|
|
923
|
+
this.updateThreadsAndNotifications(
|
|
924
|
+
result.threads.updated,
|
|
925
|
+
result.inboxNotifications.updated,
|
|
926
|
+
result.threads.deleted,
|
|
927
|
+
result.inboxNotifications.deleted
|
|
928
|
+
);
|
|
929
|
+
}
|
|
699
930
|
};
|
|
700
931
|
function internalToExternalState(state) {
|
|
701
932
|
const computed = {
|
|
702
933
|
threadsById: { ...state.rawThreadsById },
|
|
703
|
-
|
|
704
|
-
|
|
934
|
+
notificationsById: { ...state.notificationsById },
|
|
935
|
+
settingsByRoomId: { ...state.settingsByRoomId }
|
|
705
936
|
};
|
|
706
937
|
for (const optimisticUpdate of state.optimisticUpdates) {
|
|
707
938
|
switch (optimisticUpdate.type) {
|
|
@@ -717,7 +948,7 @@ function internalToExternalState(state) {
|
|
|
717
948
|
if (thread.deletedAt !== void 0) {
|
|
718
949
|
break;
|
|
719
950
|
}
|
|
720
|
-
if (thread.updatedAt
|
|
951
|
+
if (thread.updatedAt > optimisticUpdate.updatedAt) {
|
|
721
952
|
break;
|
|
722
953
|
}
|
|
723
954
|
computed.threadsById[thread.id] = {
|
|
@@ -768,14 +999,14 @@ function internalToExternalState(state) {
|
|
|
768
999
|
optimisticUpdate.comment
|
|
769
1000
|
);
|
|
770
1001
|
const inboxNotification = Object.values(
|
|
771
|
-
computed.
|
|
1002
|
+
computed.notificationsById
|
|
772
1003
|
).find(
|
|
773
1004
|
(notification) => notification.kind === "thread" && notification.threadId === thread.id
|
|
774
1005
|
);
|
|
775
1006
|
if (inboxNotification === void 0) {
|
|
776
1007
|
break;
|
|
777
1008
|
}
|
|
778
|
-
computed.
|
|
1009
|
+
computed.notificationsById[inboxNotification.id] = {
|
|
779
1010
|
...inboxNotification,
|
|
780
1011
|
notifiedAt: optimisticUpdate.comment.createdAt,
|
|
781
1012
|
readAt: optimisticUpdate.comment.createdAt
|
|
@@ -845,20 +1076,23 @@ function internalToExternalState(state) {
|
|
|
845
1076
|
break;
|
|
846
1077
|
}
|
|
847
1078
|
case "mark-inbox-notification-as-read": {
|
|
848
|
-
const ibn = computed.
|
|
1079
|
+
const ibn = computed.notificationsById[optimisticUpdate.inboxNotificationId];
|
|
849
1080
|
if (ibn === void 0) {
|
|
850
1081
|
break;
|
|
851
1082
|
}
|
|
852
|
-
computed.
|
|
1083
|
+
computed.notificationsById[optimisticUpdate.inboxNotificationId] = {
|
|
1084
|
+
...ibn,
|
|
1085
|
+
readAt: optimisticUpdate.readAt
|
|
1086
|
+
};
|
|
853
1087
|
break;
|
|
854
1088
|
}
|
|
855
1089
|
case "mark-all-inbox-notifications-as-read": {
|
|
856
|
-
for (const id in computed.
|
|
857
|
-
const ibn = computed.
|
|
1090
|
+
for (const id in computed.notificationsById) {
|
|
1091
|
+
const ibn = computed.notificationsById[id];
|
|
858
1092
|
if (ibn === void 0) {
|
|
859
1093
|
break;
|
|
860
1094
|
}
|
|
861
|
-
computed.
|
|
1095
|
+
computed.notificationsById[id] = {
|
|
862
1096
|
...ibn,
|
|
863
1097
|
readAt: optimisticUpdate.readAt
|
|
864
1098
|
};
|
|
@@ -866,19 +1100,19 @@ function internalToExternalState(state) {
|
|
|
866
1100
|
break;
|
|
867
1101
|
}
|
|
868
1102
|
case "delete-inbox-notification": {
|
|
869
|
-
delete computed.
|
|
1103
|
+
delete computed.notificationsById[optimisticUpdate.inboxNotificationId];
|
|
870
1104
|
break;
|
|
871
1105
|
}
|
|
872
1106
|
case "delete-all-inbox-notifications": {
|
|
873
|
-
computed.
|
|
1107
|
+
computed.notificationsById = {};
|
|
874
1108
|
break;
|
|
875
1109
|
}
|
|
876
1110
|
case "update-notification-settings": {
|
|
877
|
-
const settings = computed.
|
|
1111
|
+
const settings = computed.settingsByRoomId[optimisticUpdate.roomId];
|
|
878
1112
|
if (settings === void 0) {
|
|
879
1113
|
break;
|
|
880
1114
|
}
|
|
881
|
-
computed.
|
|
1115
|
+
computed.settingsByRoomId[optimisticUpdate.roomId] = {
|
|
882
1116
|
...settings,
|
|
883
1117
|
...optimisticUpdate.settings
|
|
884
1118
|
};
|
|
@@ -896,15 +1130,14 @@ function internalToExternalState(state) {
|
|
|
896
1130
|
);
|
|
897
1131
|
const cleanedNotifications = (
|
|
898
1132
|
// Sort so that the most recent notifications are first
|
|
899
|
-
Object.values(computed.
|
|
1133
|
+
Object.values(computed.notificationsById).filter(
|
|
900
1134
|
(ibn) => ibn.kind === "thread" ? computed.threadsById[ibn.threadId] && computed.threadsById[ibn.threadId]?.deletedAt === void 0 : true
|
|
901
1135
|
).sort((a, b) => b.notifiedAt.getTime() - a.notifiedAt.getTime())
|
|
902
1136
|
);
|
|
903
1137
|
return {
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
queries2: state.queries2,
|
|
1138
|
+
notifications: cleanedNotifications,
|
|
1139
|
+
notificationsById: computed.notificationsById,
|
|
1140
|
+
settingsByRoomId: computed.settingsByRoomId,
|
|
908
1141
|
queries3: state.queries3,
|
|
909
1142
|
queries4: state.queries4,
|
|
910
1143
|
threads: cleanedThreads,
|
|
@@ -978,7 +1211,7 @@ function applyUpsertComment(thread, comment) {
|
|
|
978
1211
|
);
|
|
979
1212
|
if (existingComment === void 0) {
|
|
980
1213
|
const updatedAt = new Date(
|
|
981
|
-
Math.max(thread.updatedAt
|
|
1214
|
+
Math.max(thread.updatedAt.getTime(), comment.createdAt.getTime())
|
|
982
1215
|
);
|
|
983
1216
|
const updatedThread = {
|
|
984
1217
|
...thread,
|
|
@@ -998,7 +1231,7 @@ function applyUpsertComment(thread, comment) {
|
|
|
998
1231
|
...thread,
|
|
999
1232
|
updatedAt: new Date(
|
|
1000
1233
|
Math.max(
|
|
1001
|
-
thread.updatedAt
|
|
1234
|
+
thread.updatedAt.getTime(),
|
|
1002
1235
|
comment.editedAt?.getTime() || comment.createdAt.getTime()
|
|
1003
1236
|
)
|
|
1004
1237
|
),
|
|
@@ -1065,7 +1298,7 @@ function applyAddReaction(thread, commentId, reaction) {
|
|
|
1065
1298
|
return {
|
|
1066
1299
|
...thread,
|
|
1067
1300
|
updatedAt: new Date(
|
|
1068
|
-
Math.max(reaction.createdAt.getTime(), thread.updatedAt
|
|
1301
|
+
Math.max(reaction.createdAt.getTime(), thread.updatedAt.getTime())
|
|
1069
1302
|
),
|
|
1070
1303
|
comments: updatedComments
|
|
1071
1304
|
};
|
|
@@ -1098,7 +1331,7 @@ function applyRemoveReaction(thread, commentId, emoji, userId, removedAt) {
|
|
|
1098
1331
|
return {
|
|
1099
1332
|
...thread,
|
|
1100
1333
|
updatedAt: new Date(
|
|
1101
|
-
Math.max(removedAt.getTime(), thread.updatedAt
|
|
1334
|
+
Math.max(removedAt.getTime(), thread.updatedAt.getTime())
|
|
1102
1335
|
),
|
|
1103
1336
|
comments: updatedComments
|
|
1104
1337
|
};
|
|
@@ -1125,9 +1358,100 @@ function upsertReaction(reactions, reaction) {
|
|
|
1125
1358
|
} : existingReaction2
|
|
1126
1359
|
);
|
|
1127
1360
|
}
|
|
1128
|
-
return reactions;
|
|
1361
|
+
return reactions;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
// src/liveblocks.tsx
|
|
1365
|
+
import {
|
|
1366
|
+
assert,
|
|
1367
|
+
createClient,
|
|
1368
|
+
kInternal as kInternal2,
|
|
1369
|
+
makePoller,
|
|
1370
|
+
raise,
|
|
1371
|
+
shallow as shallow3
|
|
1372
|
+
} from "@liveblocks/core";
|
|
1373
|
+
import React3, {
|
|
1374
|
+
createContext as createContext2,
|
|
1375
|
+
useCallback as useCallback2,
|
|
1376
|
+
useContext as useContext2,
|
|
1377
|
+
useEffect as useEffect3,
|
|
1378
|
+
useMemo
|
|
1379
|
+
} from "react";
|
|
1380
|
+
import { useSyncExternalStore } from "use-sync-external-store/shim/index.js";
|
|
1381
|
+
import { useSyncExternalStoreWithSelector } from "use-sync-external-store/shim/with-selector.js";
|
|
1382
|
+
|
|
1383
|
+
// src/lib/shallow2.ts
|
|
1384
|
+
import { isPlainObject as isPlainObject2, shallow } from "@liveblocks/core";
|
|
1385
|
+
function shallow2(a, b) {
|
|
1386
|
+
if (!isPlainObject2(a) || !isPlainObject2(b)) {
|
|
1387
|
+
return shallow(a, b);
|
|
1388
|
+
}
|
|
1389
|
+
const keysA = Object.keys(a);
|
|
1390
|
+
if (keysA.length !== Object.keys(b).length) {
|
|
1391
|
+
return false;
|
|
1392
|
+
}
|
|
1393
|
+
return keysA.every(
|
|
1394
|
+
(key) => Object.prototype.hasOwnProperty.call(b, key) && shallow(a[key], b[key])
|
|
1395
|
+
);
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
// src/lib/use-initial.ts
|
|
1399
|
+
import { useCallback, useReducer } from "react";
|
|
1400
|
+
|
|
1401
|
+
// src/lib/use-latest.ts
|
|
1402
|
+
import { useEffect as useEffect2, useRef } from "react";
|
|
1403
|
+
function useLatest(value) {
|
|
1404
|
+
const ref = useRef(value);
|
|
1405
|
+
useEffect2(() => {
|
|
1406
|
+
ref.current = value;
|
|
1407
|
+
}, [value]);
|
|
1408
|
+
return ref;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// src/lib/use-initial.ts
|
|
1412
|
+
var noop2 = (state) => state;
|
|
1413
|
+
function useInitial(value) {
|
|
1414
|
+
return useReducer(noop2, value)[0];
|
|
1415
|
+
}
|
|
1416
|
+
function useInitialUnlessFunction(latestValue) {
|
|
1417
|
+
const frozenValue = useInitial(latestValue);
|
|
1418
|
+
if (typeof frozenValue === "function") {
|
|
1419
|
+
const ref = useLatest(latestValue);
|
|
1420
|
+
return useCallback((...args) => ref.current(...args), [
|
|
1421
|
+
ref
|
|
1422
|
+
]);
|
|
1423
|
+
} else {
|
|
1424
|
+
return frozenValue;
|
|
1425
|
+
}
|
|
1129
1426
|
}
|
|
1130
1427
|
|
|
1428
|
+
// src/lib/use-polyfill.ts
|
|
1429
|
+
var use = (
|
|
1430
|
+
// React.use ||
|
|
1431
|
+
(promise) => {
|
|
1432
|
+
if (promise.status === "pending") {
|
|
1433
|
+
throw promise;
|
|
1434
|
+
} else if (promise.status === "fulfilled") {
|
|
1435
|
+
return promise.value;
|
|
1436
|
+
} else if (promise.status === "rejected") {
|
|
1437
|
+
throw promise.reason;
|
|
1438
|
+
} else {
|
|
1439
|
+
promise.status = "pending";
|
|
1440
|
+
promise.then(
|
|
1441
|
+
(v) => {
|
|
1442
|
+
promise.status = "fulfilled";
|
|
1443
|
+
promise.value = v;
|
|
1444
|
+
},
|
|
1445
|
+
(e) => {
|
|
1446
|
+
promise.status = "rejected";
|
|
1447
|
+
promise.reason = e;
|
|
1448
|
+
}
|
|
1449
|
+
);
|
|
1450
|
+
throw promise;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
);
|
|
1454
|
+
|
|
1131
1455
|
// src/liveblocks.tsx
|
|
1132
1456
|
var ClientContext = createContext2(null);
|
|
1133
1457
|
function missingUserError(userId) {
|
|
@@ -1145,7 +1469,6 @@ var _umbrellaStores = /* @__PURE__ */ new WeakMap();
|
|
|
1145
1469
|
var _extras = /* @__PURE__ */ new WeakMap();
|
|
1146
1470
|
var _bundles = /* @__PURE__ */ new WeakMap();
|
|
1147
1471
|
var POLLING_INTERVAL = 60 * 1e3;
|
|
1148
|
-
var USER_THREADS_QUERY = "USER_THREADS";
|
|
1149
1472
|
function selectUnreadInboxNotificationsCount(inboxNotifications) {
|
|
1150
1473
|
let count = 0;
|
|
1151
1474
|
for (const notification of inboxNotifications) {
|
|
@@ -1200,19 +1523,6 @@ function selectorFor_useRoomInfo(state, roomId) {
|
|
|
1200
1523
|
info: state.data
|
|
1201
1524
|
};
|
|
1202
1525
|
}
|
|
1203
|
-
function selectThreads(state, options) {
|
|
1204
|
-
let threads = state.threads;
|
|
1205
|
-
if (options.roomId !== null) {
|
|
1206
|
-
threads = threads.filter((thread) => thread.roomId === options.roomId);
|
|
1207
|
-
}
|
|
1208
|
-
const query = options.query;
|
|
1209
|
-
if (query) {
|
|
1210
|
-
threads = threads.filter(makeThreadsFilter(query));
|
|
1211
|
-
}
|
|
1212
|
-
return threads.sort(
|
|
1213
|
-
options.orderBy === "last-update" ? byMostRecentlyUpdated : byFirstCreated
|
|
1214
|
-
);
|
|
1215
|
-
}
|
|
1216
1526
|
function getOrCreateContextBundle(client) {
|
|
1217
1527
|
let bundle = _bundles.get(client);
|
|
1218
1528
|
if (!bundle) {
|
|
@@ -1224,187 +1534,74 @@ function getOrCreateContextBundle(client) {
|
|
|
1224
1534
|
function getUmbrellaStoreForClient(client) {
|
|
1225
1535
|
let store = _umbrellaStores.get(client);
|
|
1226
1536
|
if (!store) {
|
|
1227
|
-
store = new UmbrellaStore();
|
|
1537
|
+
store = new UmbrellaStore(client);
|
|
1228
1538
|
_umbrellaStores.set(client, store);
|
|
1229
1539
|
}
|
|
1230
1540
|
return store;
|
|
1231
1541
|
}
|
|
1232
|
-
function
|
|
1542
|
+
function getLiveblocksExtrasForClient(client) {
|
|
1233
1543
|
let extras = _extras.get(client);
|
|
1234
1544
|
if (!extras) {
|
|
1235
|
-
extras =
|
|
1545
|
+
extras = makeLiveblocksExtrasForClient(client);
|
|
1236
1546
|
_extras.set(client, extras);
|
|
1237
1547
|
}
|
|
1238
1548
|
return extras;
|
|
1239
1549
|
}
|
|
1240
|
-
function
|
|
1241
|
-
const store = getUmbrellaStoreForClient(client);
|
|
1242
|
-
let lastRequestedAt;
|
|
1243
|
-
async function fetchInboxNotifications() {
|
|
1244
|
-
if (lastRequestedAt === void 0) {
|
|
1245
|
-
const result = await client.getInboxNotifications();
|
|
1246
|
-
store.batch(() => {
|
|
1247
|
-
store.updateThreadsAndNotifications(
|
|
1248
|
-
result.threads,
|
|
1249
|
-
result.inboxNotifications,
|
|
1250
|
-
[],
|
|
1251
|
-
[]
|
|
1252
|
-
);
|
|
1253
|
-
store.setQuery1OK();
|
|
1254
|
-
});
|
|
1255
|
-
lastRequestedAt = result.requestedAt;
|
|
1256
|
-
} else {
|
|
1257
|
-
const result = await client.getInboxNotificationsSince({
|
|
1258
|
-
since: lastRequestedAt
|
|
1259
|
-
});
|
|
1260
|
-
store.batch(() => {
|
|
1261
|
-
store.updateThreadsAndNotifications(
|
|
1262
|
-
result.threads.updated,
|
|
1263
|
-
result.inboxNotifications.updated,
|
|
1264
|
-
result.threads.deleted,
|
|
1265
|
-
result.inboxNotifications.deleted
|
|
1266
|
-
);
|
|
1267
|
-
store.setQuery1OK();
|
|
1268
|
-
});
|
|
1269
|
-
if (lastRequestedAt < result.requestedAt) {
|
|
1270
|
-
lastRequestedAt = result.requestedAt;
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
let pollerSubscribers = 0;
|
|
1550
|
+
function makeDeltaPoller_Notifications(store) {
|
|
1275
1551
|
const poller = makePoller(async () => {
|
|
1276
1552
|
try {
|
|
1277
|
-
await
|
|
1278
|
-
await
|
|
1553
|
+
await store.waitUntilNotificationsLoaded();
|
|
1554
|
+
await store.fetchNotificationsDeltaUpdate();
|
|
1279
1555
|
} catch (err) {
|
|
1280
1556
|
console.warn(`Polling new inbox notifications failed: ${String(err)}`);
|
|
1281
1557
|
}
|
|
1282
|
-
});
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
try {
|
|
1286
|
-
await autoRetry(
|
|
1287
|
-
() => fetchInboxNotifications(),
|
|
1288
|
-
5,
|
|
1289
|
-
[5e3, 5e3, 1e4, 15e3]
|
|
1290
|
-
);
|
|
1291
|
-
} catch (err) {
|
|
1292
|
-
store.setQuery1Error(err);
|
|
1293
|
-
throw err;
|
|
1294
|
-
}
|
|
1295
|
-
});
|
|
1296
|
-
function loadInboxNotifications() {
|
|
1297
|
-
void waitUntilInboxNotificationsLoaded().catch(() => {
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
|
-
function startPolling() {
|
|
1558
|
+
}, POLLING_INTERVAL);
|
|
1559
|
+
let pollerSubscribers = 0;
|
|
1560
|
+
return () => {
|
|
1301
1561
|
pollerSubscribers++;
|
|
1302
|
-
poller.
|
|
1562
|
+
poller.enable(pollerSubscribers > 0);
|
|
1303
1563
|
return () => {
|
|
1304
|
-
if (pollerSubscribers <= 0) {
|
|
1305
|
-
console.warn(
|
|
1306
|
-
"Unexpected internal error: cannot decrease subscriber count for inbox notifications."
|
|
1307
|
-
);
|
|
1308
|
-
return;
|
|
1309
|
-
}
|
|
1310
1564
|
pollerSubscribers--;
|
|
1311
|
-
|
|
1312
|
-
poller.stop();
|
|
1313
|
-
}
|
|
1565
|
+
poller.enable(pollerSubscribers > 0);
|
|
1314
1566
|
};
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
const since = userThreadslastRequestedAt;
|
|
1320
|
-
if (since === void 0 || isFetchingUserThreadsUpdates) {
|
|
1321
|
-
return;
|
|
1322
|
-
}
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
function makeDeltaPoller_UserThreads(store) {
|
|
1570
|
+
const poller = makePoller(async () => {
|
|
1323
1571
|
try {
|
|
1324
|
-
|
|
1325
|
-
const updates = await client[kInternal].getThreadsSince({
|
|
1326
|
-
since
|
|
1327
|
-
});
|
|
1328
|
-
isFetchingUserThreadsUpdates = false;
|
|
1329
|
-
store.batch(() => {
|
|
1330
|
-
store.updateThreadsAndNotifications(
|
|
1331
|
-
updates.threads.updated,
|
|
1332
|
-
[],
|
|
1333
|
-
updates.threads.deleted,
|
|
1334
|
-
[]
|
|
1335
|
-
);
|
|
1336
|
-
store.setQuery2OK(USER_THREADS_QUERY);
|
|
1337
|
-
});
|
|
1338
|
-
userThreadslastRequestedAt = updates.requestedAt;
|
|
1572
|
+
await store.fetchUserThreadsDeltaUpdate();
|
|
1339
1573
|
} catch (err) {
|
|
1340
|
-
|
|
1341
|
-
return;
|
|
1574
|
+
console.warn(`Polling new user threads failed: ${String(err)}`);
|
|
1342
1575
|
}
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
userThreadsSubscribersByQuery.set(queryKey, subscribers + 1);
|
|
1349
|
-
userThreadsPoller.start(POLLING_INTERVAL);
|
|
1576
|
+
}, POLLING_INTERVAL);
|
|
1577
|
+
let pollerSubscribers = 0;
|
|
1578
|
+
return () => {
|
|
1579
|
+
pollerSubscribers++;
|
|
1580
|
+
poller.enable(pollerSubscribers > 0);
|
|
1350
1581
|
return () => {
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
console.warn(
|
|
1354
|
-
`Internal unexpected behavior. Cannot decrease subscriber count for query "${queryKey}"`
|
|
1355
|
-
);
|
|
1356
|
-
return;
|
|
1357
|
-
}
|
|
1358
|
-
userThreadsSubscribersByQuery.set(queryKey, subscribers2 - 1);
|
|
1359
|
-
let totalSubscribers = 0;
|
|
1360
|
-
for (const subscribers3 of userThreadsSubscribersByQuery.values()) {
|
|
1361
|
-
totalSubscribers += subscribers3;
|
|
1362
|
-
}
|
|
1363
|
-
if (totalSubscribers <= 0) {
|
|
1364
|
-
userThreadsPoller.stop();
|
|
1365
|
-
}
|
|
1582
|
+
pollerSubscribers--;
|
|
1583
|
+
poller.enable(pollerSubscribers > 0);
|
|
1366
1584
|
};
|
|
1367
|
-
}
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
if (existingRequest !== void 0) return existingRequest;
|
|
1372
|
-
const request = client[kInternal].getThreads(options);
|
|
1373
|
-
userThreadsRequestsByQuery.set(queryKey, request);
|
|
1374
|
-
store.setQuery2Loading(queryKey);
|
|
1375
|
-
try {
|
|
1376
|
-
const result = await request;
|
|
1377
|
-
store.batch(() => {
|
|
1378
|
-
store.updateThreadsAndNotifications(
|
|
1379
|
-
result.threads,
|
|
1380
|
-
result.inboxNotifications,
|
|
1381
|
-
[],
|
|
1382
|
-
[]
|
|
1383
|
-
);
|
|
1384
|
-
store.setQuery2OK(queryKey);
|
|
1385
|
-
});
|
|
1386
|
-
if (userThreadslastRequestedAt === void 0 || userThreadslastRequestedAt < result.requestedAt) {
|
|
1387
|
-
userThreadslastRequestedAt = result.requestedAt;
|
|
1388
|
-
}
|
|
1389
|
-
userThreadsPoller.start(POLLING_INTERVAL);
|
|
1390
|
-
} catch (err) {
|
|
1391
|
-
userThreadsRequestsByQuery.delete(queryKey);
|
|
1392
|
-
retryError(() => {
|
|
1393
|
-
void getUserThreads(queryKey, options, {
|
|
1394
|
-
retryCount: retryCount + 1
|
|
1395
|
-
});
|
|
1396
|
-
}, retryCount);
|
|
1397
|
-
store.setQuery2Error(queryKey, err);
|
|
1398
|
-
}
|
|
1399
|
-
return;
|
|
1400
|
-
}
|
|
1585
|
+
};
|
|
1586
|
+
}
|
|
1587
|
+
function makeLiveblocksExtrasForClient(client) {
|
|
1588
|
+
const store = getUmbrellaStoreForClient(client);
|
|
1401
1589
|
return {
|
|
1402
1590
|
store,
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1591
|
+
/**
|
|
1592
|
+
* Sub/unsub pair to start the process of watching for new incoming inbox
|
|
1593
|
+
* notifications through a stream of delta updates. Call the unsub function
|
|
1594
|
+
* returned to stop this subscription when unmounting. Currently
|
|
1595
|
+
* implemented by a periodic poller.
|
|
1596
|
+
*/
|
|
1597
|
+
subscribeToNotificationsDeltaUpdates: makeDeltaPoller_Notifications(store),
|
|
1598
|
+
/**
|
|
1599
|
+
* Sub/unsub pair to start the process of watching for new user threads
|
|
1600
|
+
* through a stream of delta updates. Call the unsub function returned to
|
|
1601
|
+
* stop this subscription when unmounting. Currently implemented by
|
|
1602
|
+
* a periodic poller.
|
|
1603
|
+
*/
|
|
1604
|
+
subscribeToUserThreadsDeltaUpdates: makeDeltaPoller_UserThreads(store)
|
|
1408
1605
|
};
|
|
1409
1606
|
}
|
|
1410
1607
|
function makeLiveblocksContextBundle(client) {
|
|
@@ -1420,7 +1617,7 @@ function makeLiveblocksContextBundle(client) {
|
|
|
1420
1617
|
const shared = createSharedContext(client);
|
|
1421
1618
|
const bundle = {
|
|
1422
1619
|
LiveblocksProvider: LiveblocksProvider2,
|
|
1423
|
-
useInboxNotifications: () => useInboxNotifications_withClient(client),
|
|
1620
|
+
useInboxNotifications: () => useInboxNotifications_withClient(client, identity, shallow3),
|
|
1424
1621
|
useUnreadInboxNotificationsCount: () => useUnreadInboxNotificationsCount_withClient(client),
|
|
1425
1622
|
useMarkInboxNotificationAsRead: useMarkInboxNotificationAsRead2,
|
|
1426
1623
|
useMarkAllInboxNotificationsAsRead: useMarkAllInboxNotificationsAsRead2,
|
|
@@ -1444,41 +1641,42 @@ function makeLiveblocksContextBundle(client) {
|
|
|
1444
1641
|
};
|
|
1445
1642
|
return bundle;
|
|
1446
1643
|
}
|
|
1447
|
-
function useInboxNotifications_withClient(client) {
|
|
1448
|
-
const {
|
|
1449
|
-
|
|
1450
|
-
|
|
1644
|
+
function useInboxNotifications_withClient(client, selector, isEqual) {
|
|
1645
|
+
const {
|
|
1646
|
+
store,
|
|
1647
|
+
subscribeToNotificationsDeltaUpdates: subscribeToDeltaUpdates
|
|
1648
|
+
} = getLiveblocksExtrasForClient(client);
|
|
1649
|
+
useEffect3(() => {
|
|
1650
|
+
void store.waitUntilNotificationsLoaded().catch(() => {
|
|
1651
|
+
});
|
|
1652
|
+
});
|
|
1653
|
+
useEffect3(subscribeToDeltaUpdates, [subscribeToDeltaUpdates]);
|
|
1451
1654
|
return useSyncExternalStoreWithSelector(
|
|
1452
1655
|
store.subscribeThreadsOrInboxNotifications,
|
|
1453
1656
|
store.getInboxNotificationsAsync,
|
|
1454
1657
|
store.getInboxNotificationsAsync,
|
|
1455
|
-
|
|
1456
|
-
|
|
1658
|
+
selector,
|
|
1659
|
+
isEqual
|
|
1457
1660
|
);
|
|
1458
1661
|
}
|
|
1459
1662
|
function useInboxNotificationsSuspense_withClient(client) {
|
|
1460
|
-
const
|
|
1461
|
-
use(
|
|
1462
|
-
const result = useInboxNotifications_withClient(client);
|
|
1663
|
+
const store = getLiveblocksExtrasForClient(client).store;
|
|
1664
|
+
use(store.waitUntilNotificationsLoaded());
|
|
1665
|
+
const result = useInboxNotifications_withClient(client, identity, shallow3);
|
|
1463
1666
|
assert(!result.error, "Did not expect error");
|
|
1464
1667
|
assert(!result.isLoading, "Did not expect loading");
|
|
1465
1668
|
return result;
|
|
1466
1669
|
}
|
|
1467
1670
|
function useUnreadInboxNotificationsCount_withClient(client) {
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
useEffect3(startPolling, [startPolling]);
|
|
1471
|
-
return useSyncExternalStoreWithSelector(
|
|
1472
|
-
store.subscribeThreadsOrInboxNotifications,
|
|
1473
|
-
store.getInboxNotificationsAsync,
|
|
1474
|
-
store.getInboxNotificationsAsync,
|
|
1671
|
+
return useInboxNotifications_withClient(
|
|
1672
|
+
client,
|
|
1475
1673
|
selectorFor_useUnreadInboxNotificationsCount,
|
|
1476
1674
|
shallow3
|
|
1477
1675
|
);
|
|
1478
1676
|
}
|
|
1479
1677
|
function useUnreadInboxNotificationsCountSuspense_withClient(client) {
|
|
1480
|
-
const
|
|
1481
|
-
use(
|
|
1678
|
+
const store = getLiveblocksExtrasForClient(client).store;
|
|
1679
|
+
use(store.waitUntilNotificationsLoaded());
|
|
1482
1680
|
const result = useUnreadInboxNotificationsCount_withClient(client);
|
|
1483
1681
|
assert(!result.isLoading, "Did not expect loading");
|
|
1484
1682
|
assert(!result.error, "Did not expect error");
|
|
@@ -1487,7 +1685,7 @@ function useUnreadInboxNotificationsCountSuspense_withClient(client) {
|
|
|
1487
1685
|
function useMarkInboxNotificationAsRead_withClient(client) {
|
|
1488
1686
|
return useCallback2(
|
|
1489
1687
|
(inboxNotificationId) => {
|
|
1490
|
-
const { store } =
|
|
1688
|
+
const { store } = getLiveblocksExtrasForClient(client);
|
|
1491
1689
|
const readAt = /* @__PURE__ */ new Date();
|
|
1492
1690
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
1493
1691
|
type: "mark-inbox-notification-as-read",
|
|
@@ -1512,7 +1710,7 @@ function useMarkInboxNotificationAsRead_withClient(client) {
|
|
|
1512
1710
|
}
|
|
1513
1711
|
function useMarkAllInboxNotificationsAsRead_withClient(client) {
|
|
1514
1712
|
return useCallback2(() => {
|
|
1515
|
-
const { store } =
|
|
1713
|
+
const { store } = getLiveblocksExtrasForClient(client);
|
|
1516
1714
|
const readAt = /* @__PURE__ */ new Date();
|
|
1517
1715
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
1518
1716
|
type: "mark-all-inbox-notifications-as-read",
|
|
@@ -1534,7 +1732,7 @@ function useMarkAllInboxNotificationsAsRead_withClient(client) {
|
|
|
1534
1732
|
function useDeleteInboxNotification_withClient(client) {
|
|
1535
1733
|
return useCallback2(
|
|
1536
1734
|
(inboxNotificationId) => {
|
|
1537
|
-
const { store } =
|
|
1735
|
+
const { store } = getLiveblocksExtrasForClient(client);
|
|
1538
1736
|
const deletedAt = /* @__PURE__ */ new Date();
|
|
1539
1737
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
1540
1738
|
type: "delete-inbox-notification",
|
|
@@ -1558,7 +1756,7 @@ function useDeleteInboxNotification_withClient(client) {
|
|
|
1558
1756
|
}
|
|
1559
1757
|
function useDeleteAllInboxNotifications_withClient(client) {
|
|
1560
1758
|
return useCallback2(() => {
|
|
1561
|
-
const { store } =
|
|
1759
|
+
const { store } = getLiveblocksExtrasForClient(client);
|
|
1562
1760
|
const deletedAt = /* @__PURE__ */ new Date();
|
|
1563
1761
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
1564
1762
|
type: "delete-all-inbox-notifications",
|
|
@@ -1575,11 +1773,11 @@ function useDeleteAllInboxNotifications_withClient(client) {
|
|
|
1575
1773
|
}, [client]);
|
|
1576
1774
|
}
|
|
1577
1775
|
function useInboxNotificationThread_withClient(client, inboxNotificationId) {
|
|
1578
|
-
const { store } =
|
|
1776
|
+
const { store } = getLiveblocksExtrasForClient(client);
|
|
1579
1777
|
const getter = store.getFullState;
|
|
1580
1778
|
const selector = useCallback2(
|
|
1581
1779
|
(state) => {
|
|
1582
|
-
const inboxNotification = state.
|
|
1780
|
+
const inboxNotification = state.notificationsById[inboxNotificationId] ?? raise(`Inbox notification with ID "${inboxNotificationId}" not found`);
|
|
1583
1781
|
if (inboxNotification.kind !== "thread") {
|
|
1584
1782
|
raise(
|
|
1585
1783
|
`Inbox notification with ID "${inboxNotificationId}" is not of kind "thread"`
|
|
@@ -1601,7 +1799,7 @@ function useInboxNotificationThread_withClient(client, inboxNotificationId) {
|
|
|
1601
1799
|
);
|
|
1602
1800
|
}
|
|
1603
1801
|
function useUser_withClient(client, userId) {
|
|
1604
|
-
const usersStore = client[
|
|
1802
|
+
const usersStore = client[kInternal2].usersStore;
|
|
1605
1803
|
const getUserState = useCallback2(
|
|
1606
1804
|
() => usersStore.getState(userId),
|
|
1607
1805
|
[usersStore, userId]
|
|
@@ -1622,7 +1820,7 @@ function useUser_withClient(client, userId) {
|
|
|
1622
1820
|
);
|
|
1623
1821
|
}
|
|
1624
1822
|
function useUserSuspense_withClient(client, userId) {
|
|
1625
|
-
const usersStore = client[
|
|
1823
|
+
const usersStore = client[kInternal2].usersStore;
|
|
1626
1824
|
const getUserState = useCallback2(
|
|
1627
1825
|
() => usersStore.getState(userId),
|
|
1628
1826
|
[usersStore, userId]
|
|
@@ -1652,7 +1850,7 @@ function useUserSuspense_withClient(client, userId) {
|
|
|
1652
1850
|
};
|
|
1653
1851
|
}
|
|
1654
1852
|
function useRoomInfo_withClient(client, roomId) {
|
|
1655
|
-
const roomsInfoStore = client[
|
|
1853
|
+
const roomsInfoStore = client[kInternal2].roomsInfoStore;
|
|
1656
1854
|
const getRoomInfoState = useCallback2(
|
|
1657
1855
|
() => roomsInfoStore.getState(roomId),
|
|
1658
1856
|
[roomsInfoStore, roomId]
|
|
@@ -1673,7 +1871,7 @@ function useRoomInfo_withClient(client, roomId) {
|
|
|
1673
1871
|
);
|
|
1674
1872
|
}
|
|
1675
1873
|
function useRoomInfoSuspense_withClient(client, roomId) {
|
|
1676
|
-
const roomsInfoStore = client[
|
|
1874
|
+
const roomsInfoStore = client[kInternal2].roomsInfoStore;
|
|
1677
1875
|
const getRoomInfoState = useCallback2(
|
|
1678
1876
|
() => roomsInfoStore.getState(roomId),
|
|
1679
1877
|
[roomsInfoStore, roomId]
|
|
@@ -1774,40 +1972,32 @@ function useUserThreads_experimental(options = {
|
|
|
1774
1972
|
metadata: {}
|
|
1775
1973
|
}
|
|
1776
1974
|
}) {
|
|
1777
|
-
const queryKey = React3.useMemo(
|
|
1778
|
-
() => makeUserThreadsQueryKey(options.query),
|
|
1779
|
-
[options]
|
|
1780
|
-
);
|
|
1781
1975
|
const client = useClient();
|
|
1782
|
-
const { store,
|
|
1783
|
-
useEffect3(
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
}, [queryKey, incrementUserThreadsQuerySubscribers, getUserThreads, options]);
|
|
1787
|
-
const getter = useCallback2(
|
|
1788
|
-
() => store.getUserThreadsAsync(queryKey),
|
|
1789
|
-
[store, queryKey]
|
|
1790
|
-
);
|
|
1791
|
-
const selector = useCallback2(
|
|
1792
|
-
(result) => {
|
|
1793
|
-
if (!result.fullState) {
|
|
1794
|
-
return result;
|
|
1795
|
-
}
|
|
1796
|
-
const threads = selectThreads(result.fullState, {
|
|
1797
|
-
roomId: null,
|
|
1798
|
-
// Do _not_ filter by roomId
|
|
1799
|
-
query: options.query,
|
|
1800
|
-
orderBy: "last-update"
|
|
1976
|
+
const { store, subscribeToUserThreadsDeltaUpdates: subscribeToDeltaUpdates } = getLiveblocksExtrasForClient(client);
|
|
1977
|
+
useEffect3(
|
|
1978
|
+
() => {
|
|
1979
|
+
void store.waitUntilUserThreadsLoaded(options.query).catch(() => {
|
|
1801
1980
|
});
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1981
|
+
}
|
|
1982
|
+
// NOTE: Deliberately *not* using a dependency array here!
|
|
1983
|
+
//
|
|
1984
|
+
// It is important to call waitUntil on *every* render.
|
|
1985
|
+
// This is harmless though, on most renders, except:
|
|
1986
|
+
// 1. The very first render, in which case we'll want to trigger the initial page fetch.
|
|
1987
|
+
// 2. All other subsequent renders now "just" return the same promise (a quick operation).
|
|
1988
|
+
// 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
|
|
1989
|
+
// *next* render after that, a *new* fetch/promise will get created.
|
|
1990
|
+
);
|
|
1991
|
+
useEffect3(subscribeToDeltaUpdates, [subscribeToDeltaUpdates]);
|
|
1992
|
+
const getter = useCallback2(
|
|
1993
|
+
() => store.getUserThreadsAsync(options.query),
|
|
1994
|
+
[store, options.query]
|
|
1805
1995
|
);
|
|
1806
1996
|
return useSyncExternalStoreWithSelector(
|
|
1807
1997
|
store.subscribeUserThreads,
|
|
1808
1998
|
getter,
|
|
1809
1999
|
getter,
|
|
1810
|
-
|
|
2000
|
+
identity,
|
|
1811
2001
|
shallow2
|
|
1812
2002
|
// NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
|
|
1813
2003
|
);
|
|
@@ -1817,49 +2007,16 @@ function useUserThreadsSuspense_experimental(options = {
|
|
|
1817
2007
|
metadata: {}
|
|
1818
2008
|
}
|
|
1819
2009
|
}) {
|
|
1820
|
-
const queryKey = React3.useMemo(
|
|
1821
|
-
() => makeUserThreadsQueryKey(options.query),
|
|
1822
|
-
[options]
|
|
1823
|
-
);
|
|
1824
2010
|
const client = useClient();
|
|
1825
|
-
const { store
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
if (query === void 0 || query.isLoading) {
|
|
1832
|
-
throw getUserThreads(queryKey, options);
|
|
1833
|
-
}
|
|
1834
|
-
if (query.error) {
|
|
1835
|
-
throw query.error;
|
|
1836
|
-
}
|
|
1837
|
-
const getter = store.getFullState;
|
|
1838
|
-
const selector = useCallback2(
|
|
1839
|
-
(state) => {
|
|
1840
|
-
return {
|
|
1841
|
-
threads: selectThreads(state, {
|
|
1842
|
-
roomId: null,
|
|
1843
|
-
// Do _not_ filter by roomId
|
|
1844
|
-
query: options.query,
|
|
1845
|
-
orderBy: "last-update"
|
|
1846
|
-
}),
|
|
1847
|
-
isLoading: false
|
|
1848
|
-
};
|
|
1849
|
-
},
|
|
1850
|
-
[options]
|
|
1851
|
-
);
|
|
1852
|
-
return useSyncExternalStoreWithSelector(
|
|
1853
|
-
store.subscribeUserThreads,
|
|
1854
|
-
getter,
|
|
1855
|
-
getter,
|
|
1856
|
-
selector,
|
|
1857
|
-
shallow2
|
|
1858
|
-
// NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
|
|
1859
|
-
);
|
|
2011
|
+
const { store } = getLiveblocksExtrasForClient(client);
|
|
2012
|
+
use(store.waitUntilUserThreadsLoaded(options.query));
|
|
2013
|
+
const result = useUserThreads_experimental(options);
|
|
2014
|
+
assert(!result.error, "Did not expect error");
|
|
2015
|
+
assert(!result.isLoading, "Did not expect loading");
|
|
2016
|
+
return result;
|
|
1860
2017
|
}
|
|
1861
2018
|
function useInboxNotifications() {
|
|
1862
|
-
return useInboxNotifications_withClient(useClient());
|
|
2019
|
+
return useInboxNotifications_withClient(useClient(), identity, shallow3);
|
|
1863
2020
|
}
|
|
1864
2021
|
function useInboxNotificationsSuspense() {
|
|
1865
2022
|
return useInboxNotificationsSuspense_withClient(useClient());
|
|
@@ -1907,7 +2064,6 @@ var _useUser = useUser;
|
|
|
1907
2064
|
var _useUserSuspense = useUserSuspense;
|
|
1908
2065
|
var _useUserThreads_experimental = useUserThreads_experimental;
|
|
1909
2066
|
var _useUserThreadsSuspense_experimental = useUserThreadsSuspense_experimental;
|
|
1910
|
-
var makeUserThreadsQueryKey = (options) => `${USER_THREADS_QUERY}:${stringify(options)}`;
|
|
1911
2067
|
|
|
1912
2068
|
// src/types/errors.ts
|
|
1913
2069
|
var CreateThreadError = class extends Error {
|
|
@@ -2017,16 +2173,26 @@ import {
|
|
|
2017
2173
|
createThreadId,
|
|
2018
2174
|
deprecateIf,
|
|
2019
2175
|
errorIf,
|
|
2020
|
-
kInternal as
|
|
2021
|
-
makeEventSource,
|
|
2176
|
+
kInternal as kInternal3,
|
|
2177
|
+
makeEventSource as makeEventSource2,
|
|
2022
2178
|
makePoller as makePoller2,
|
|
2023
2179
|
NotificationsApiError,
|
|
2024
|
-
ServerMsgCode
|
|
2025
|
-
stringify as stringify2
|
|
2180
|
+
ServerMsgCode
|
|
2026
2181
|
} from "@liveblocks/core";
|
|
2027
2182
|
import * as React5 from "react";
|
|
2028
2183
|
import { useSyncExternalStoreWithSelector as useSyncExternalStoreWithSelector2 } from "use-sync-external-store/shim/with-selector.js";
|
|
2029
2184
|
|
|
2185
|
+
// src/lib/retry-error.ts
|
|
2186
|
+
var MAX_ERROR_RETRY_COUNT = 5;
|
|
2187
|
+
var ERROR_RETRY_INTERVAL = 5e3;
|
|
2188
|
+
function retryError(action, retryCount) {
|
|
2189
|
+
if (retryCount >= MAX_ERROR_RETRY_COUNT) return;
|
|
2190
|
+
const timeout = Math.pow(2, retryCount) * ERROR_RETRY_INTERVAL;
|
|
2191
|
+
setTimeout(() => {
|
|
2192
|
+
void action();
|
|
2193
|
+
}, timeout);
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2030
2196
|
// src/use-scroll-to-comment-on-load-effect.ts
|
|
2031
2197
|
import * as React4 from "react";
|
|
2032
2198
|
function handleScrollToCommentOnLoad(shouldScrollOnLoad, state) {
|
|
@@ -2058,7 +2224,7 @@ function useScrollToCommentOnLoadEffect(shouldScrollOnLoad, state) {
|
|
|
2058
2224
|
|
|
2059
2225
|
// src/room.tsx
|
|
2060
2226
|
var SMOOTH_DELAY = 1e3;
|
|
2061
|
-
var
|
|
2227
|
+
var noop3 = () => {
|
|
2062
2228
|
};
|
|
2063
2229
|
var identity2 = (x) => x;
|
|
2064
2230
|
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:
|
|
@@ -2132,6 +2298,28 @@ function handleApiError(err) {
|
|
|
2132
2298
|
}
|
|
2133
2299
|
return new Error(message);
|
|
2134
2300
|
}
|
|
2301
|
+
function makeDeltaPoller_RoomThreads(client) {
|
|
2302
|
+
const store = getUmbrellaStoreForClient(client);
|
|
2303
|
+
const poller = makePoller2(async () => {
|
|
2304
|
+
const roomIds = client[kInternal3].getRoomIds();
|
|
2305
|
+
await Promise.allSettled(
|
|
2306
|
+
roomIds.map((roomId) => {
|
|
2307
|
+
const room = client.getRoom(roomId);
|
|
2308
|
+
if (room === null) return;
|
|
2309
|
+
return store.fetchRoomThreadsDeltaUpdate(room.id);
|
|
2310
|
+
})
|
|
2311
|
+
);
|
|
2312
|
+
}, POLLING_INTERVAL2);
|
|
2313
|
+
let pollerSubscribers = 0;
|
|
2314
|
+
return () => {
|
|
2315
|
+
pollerSubscribers++;
|
|
2316
|
+
poller.enable(pollerSubscribers > 0);
|
|
2317
|
+
return () => {
|
|
2318
|
+
pollerSubscribers--;
|
|
2319
|
+
poller.enable(pollerSubscribers > 0);
|
|
2320
|
+
};
|
|
2321
|
+
};
|
|
2322
|
+
}
|
|
2135
2323
|
var _extras2 = /* @__PURE__ */ new WeakMap();
|
|
2136
2324
|
var _bundles2 = /* @__PURE__ */ new WeakMap();
|
|
2137
2325
|
function getOrCreateRoomContextBundle(client) {
|
|
@@ -2142,83 +2330,22 @@ function getOrCreateRoomContextBundle(client) {
|
|
|
2142
2330
|
}
|
|
2143
2331
|
return bundle;
|
|
2144
2332
|
}
|
|
2145
|
-
function
|
|
2333
|
+
function getRoomExtrasForClient(client) {
|
|
2146
2334
|
let extras = _extras2.get(client);
|
|
2147
2335
|
if (!extras) {
|
|
2148
|
-
extras =
|
|
2336
|
+
extras = makeRoomExtrasForClient(client);
|
|
2149
2337
|
_extras2.set(client, extras);
|
|
2150
2338
|
}
|
|
2151
2339
|
return extras;
|
|
2152
2340
|
}
|
|
2153
|
-
function
|
|
2341
|
+
function makeRoomExtrasForClient(client) {
|
|
2154
2342
|
const store = getUmbrellaStoreForClient(client);
|
|
2155
|
-
const DEFAULT_DEDUPING_INTERVAL = 2e3;
|
|
2156
|
-
const lastRequestedAtByRoom = /* @__PURE__ */ new Map();
|
|
2157
2343
|
const requestsByQuery = /* @__PURE__ */ new Map();
|
|
2158
|
-
const requestStatusByRoom = /* @__PURE__ */ new Map();
|
|
2159
|
-
const subscribersByQuery = /* @__PURE__ */ new Map();
|
|
2160
|
-
const poller = makePoller2(refreshThreadsAndNotifications);
|
|
2161
|
-
async function refreshThreadsAndNotifications() {
|
|
2162
|
-
const requests = [];
|
|
2163
|
-
client[kInternal2].getRoomIds().map((roomId) => {
|
|
2164
|
-
const room = client.getRoom(roomId);
|
|
2165
|
-
if (room === null) return;
|
|
2166
|
-
requests.push(getThreadsUpdates(room.id));
|
|
2167
|
-
});
|
|
2168
|
-
await Promise.allSettled(requests);
|
|
2169
|
-
}
|
|
2170
|
-
function incrementQuerySubscribers(queryKey) {
|
|
2171
|
-
const subscribers = subscribersByQuery.get(queryKey) ?? 0;
|
|
2172
|
-
subscribersByQuery.set(queryKey, subscribers + 1);
|
|
2173
|
-
poller.start(POLLING_INTERVAL2);
|
|
2174
|
-
return () => {
|
|
2175
|
-
const subscribers2 = subscribersByQuery.get(queryKey);
|
|
2176
|
-
if (subscribers2 === void 0 || subscribers2 <= 0) {
|
|
2177
|
-
console3.warn(
|
|
2178
|
-
`Internal unexpected behavior. Cannot decrease subscriber count for query "${queryKey}"`
|
|
2179
|
-
);
|
|
2180
|
-
return;
|
|
2181
|
-
}
|
|
2182
|
-
subscribersByQuery.set(queryKey, subscribers2 - 1);
|
|
2183
|
-
let totalSubscribers = 0;
|
|
2184
|
-
for (const subscribers3 of subscribersByQuery.values()) {
|
|
2185
|
-
totalSubscribers += subscribers3;
|
|
2186
|
-
}
|
|
2187
|
-
if (totalSubscribers <= 0) {
|
|
2188
|
-
poller.stop();
|
|
2189
|
-
}
|
|
2190
|
-
};
|
|
2191
|
-
}
|
|
2192
|
-
async function getThreadsUpdates(roomId) {
|
|
2193
|
-
const room = client.getRoom(roomId);
|
|
2194
|
-
if (room === null) return;
|
|
2195
|
-
const since = lastRequestedAtByRoom.get(room.id);
|
|
2196
|
-
if (since === void 0) return;
|
|
2197
|
-
const isFetchingThreadsUpdates = requestStatusByRoom.get(room.id) ?? false;
|
|
2198
|
-
if (isFetchingThreadsUpdates === true) return;
|
|
2199
|
-
try {
|
|
2200
|
-
requestStatusByRoom.set(room.id, true);
|
|
2201
|
-
const updates = await room.getThreadsSince({ since });
|
|
2202
|
-
setTimeout(() => {
|
|
2203
|
-
requestStatusByRoom.set(room.id, false);
|
|
2204
|
-
}, DEFAULT_DEDUPING_INTERVAL);
|
|
2205
|
-
store.updateThreadsAndNotifications(
|
|
2206
|
-
updates.threads.updated,
|
|
2207
|
-
updates.inboxNotifications.updated,
|
|
2208
|
-
updates.threads.deleted,
|
|
2209
|
-
updates.inboxNotifications.deleted
|
|
2210
|
-
);
|
|
2211
|
-
lastRequestedAtByRoom.set(room.id, updates.requestedAt);
|
|
2212
|
-
} catch (err) {
|
|
2213
|
-
requestStatusByRoom.set(room.id, false);
|
|
2214
|
-
return;
|
|
2215
|
-
}
|
|
2216
|
-
}
|
|
2217
2344
|
async function getRoomVersions(room, { retryCount } = { retryCount: 0 }) {
|
|
2218
2345
|
const queryKey = makeVersionsQueryKey(room.id);
|
|
2219
2346
|
const existingRequest = requestsByQuery.get(queryKey);
|
|
2220
2347
|
if (existingRequest !== void 0) return existingRequest;
|
|
2221
|
-
const request = room[
|
|
2348
|
+
const request = room[kInternal3].listTextVersions();
|
|
2222
2349
|
requestsByQuery.set(queryKey, request);
|
|
2223
2350
|
store.setQuery4Loading(queryKey);
|
|
2224
2351
|
try {
|
|
@@ -2243,40 +2370,6 @@ function makeExtrasForClient2(client) {
|
|
|
2243
2370
|
}
|
|
2244
2371
|
return;
|
|
2245
2372
|
}
|
|
2246
|
-
async function getThreadsAndInboxNotifications(room, queryKey, options, { retryCount } = { retryCount: 0 }) {
|
|
2247
|
-
const existingRequest = requestsByQuery.get(queryKey);
|
|
2248
|
-
if (existingRequest !== void 0) return existingRequest;
|
|
2249
|
-
const request = room.getThreads(options);
|
|
2250
|
-
requestsByQuery.set(queryKey, request);
|
|
2251
|
-
store.setQuery2Loading(queryKey);
|
|
2252
|
-
try {
|
|
2253
|
-
const result = await request;
|
|
2254
|
-
store.batch(() => {
|
|
2255
|
-
store.updateThreadsAndNotifications(
|
|
2256
|
-
result.threads,
|
|
2257
|
-
// TODO: Figure out how to remove this casting
|
|
2258
|
-
result.inboxNotifications,
|
|
2259
|
-
[],
|
|
2260
|
-
[]
|
|
2261
|
-
);
|
|
2262
|
-
store.setQuery2OK(queryKey);
|
|
2263
|
-
});
|
|
2264
|
-
const lastRequestedAt = lastRequestedAtByRoom.get(room.id);
|
|
2265
|
-
if (lastRequestedAt === void 0 || lastRequestedAt > result.requestedAt) {
|
|
2266
|
-
lastRequestedAtByRoom.set(room.id, result.requestedAt);
|
|
2267
|
-
}
|
|
2268
|
-
poller.start(POLLING_INTERVAL2);
|
|
2269
|
-
} catch (err) {
|
|
2270
|
-
requestsByQuery.delete(queryKey);
|
|
2271
|
-
retryError(() => {
|
|
2272
|
-
void getThreadsAndInboxNotifications(room, queryKey, options, {
|
|
2273
|
-
retryCount: retryCount + 1
|
|
2274
|
-
});
|
|
2275
|
-
}, retryCount);
|
|
2276
|
-
store.setQuery2Error(queryKey, err);
|
|
2277
|
-
}
|
|
2278
|
-
return;
|
|
2279
|
-
}
|
|
2280
2373
|
async function getInboxNotificationSettings(room, { retryCount } = { retryCount: 0 }) {
|
|
2281
2374
|
const queryKey = makeNotificationSettingsQueryKey(room.id);
|
|
2282
2375
|
const existingRequest = requestsByQuery.get(queryKey);
|
|
@@ -2298,7 +2391,7 @@ function makeExtrasForClient2(client) {
|
|
|
2298
2391
|
}
|
|
2299
2392
|
return;
|
|
2300
2393
|
}
|
|
2301
|
-
const commentsErrorEventSource =
|
|
2394
|
+
const commentsErrorEventSource = makeEventSource2();
|
|
2302
2395
|
function onMutationFailure(innerError, optimisticUpdateId, createPublicError) {
|
|
2303
2396
|
store.removeOptimisticUpdate(optimisticUpdateId);
|
|
2304
2397
|
if (innerError instanceof CommentsApiError) {
|
|
@@ -2314,10 +2407,8 @@ function makeExtrasForClient2(client) {
|
|
|
2314
2407
|
}
|
|
2315
2408
|
return {
|
|
2316
2409
|
store,
|
|
2317
|
-
|
|
2410
|
+
subscribeToRoomThreadsDeltaUpdates: makeDeltaPoller_RoomThreads(client),
|
|
2318
2411
|
commentsErrorEventSource,
|
|
2319
|
-
getThreadsUpdates,
|
|
2320
|
-
getThreadsAndInboxNotifications,
|
|
2321
2412
|
getInboxNotificationSettings,
|
|
2322
2413
|
getRoomVersions,
|
|
2323
2414
|
onMutationFailure
|
|
@@ -2423,7 +2514,7 @@ function makeRoomContextBundle(client) {
|
|
|
2423
2514
|
},
|
|
2424
2515
|
useCommentsErrorListener
|
|
2425
2516
|
};
|
|
2426
|
-
return Object.defineProperty(bundle,
|
|
2517
|
+
return Object.defineProperty(bundle, kInternal3, {
|
|
2427
2518
|
enumerable: false
|
|
2428
2519
|
});
|
|
2429
2520
|
}
|
|
@@ -2492,7 +2583,7 @@ function RoomProviderInner(props) {
|
|
|
2492
2583
|
})
|
|
2493
2584
|
);
|
|
2494
2585
|
React5.useEffect(() => {
|
|
2495
|
-
const { store } =
|
|
2586
|
+
const { store } = getRoomExtrasForClient(client);
|
|
2496
2587
|
async function handleCommentEvent(message) {
|
|
2497
2588
|
if (message.type === ServerMsgCode.THREAD_DELETED) {
|
|
2498
2589
|
store.deleteThread(message.threadId, null);
|
|
@@ -2527,13 +2618,15 @@ function RoomProviderInner(props) {
|
|
|
2527
2618
|
);
|
|
2528
2619
|
}, [client, room]);
|
|
2529
2620
|
React5.useEffect(() => {
|
|
2530
|
-
const
|
|
2531
|
-
void
|
|
2621
|
+
const store = getRoomExtrasForClient(client).store;
|
|
2622
|
+
void store.fetchRoomThreadsDeltaUpdate(room.id).catch(() => {
|
|
2623
|
+
});
|
|
2532
2624
|
}, [client, room.id]);
|
|
2533
2625
|
React5.useEffect(() => {
|
|
2534
2626
|
function handleIsOnline() {
|
|
2535
|
-
const
|
|
2536
|
-
void
|
|
2627
|
+
const store = getRoomExtrasForClient(client).store;
|
|
2628
|
+
void store.fetchRoomThreadsDeltaUpdate(room.id).catch(() => {
|
|
2629
|
+
});
|
|
2537
2630
|
}
|
|
2538
2631
|
window.addEventListener("online", handleIsOnline);
|
|
2539
2632
|
return () => {
|
|
@@ -2779,7 +2872,7 @@ function useStorage(selector, isEqual) {
|
|
|
2779
2872
|
[selector]
|
|
2780
2873
|
);
|
|
2781
2874
|
const subscribe = React5.useCallback(
|
|
2782
|
-
(onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) :
|
|
2875
|
+
(onStoreChange) => rootOrNull !== null ? room.subscribe(rootOrNull, onStoreChange, { isDeep: true }) : noop3,
|
|
2783
2876
|
[room, rootOrNull]
|
|
2784
2877
|
);
|
|
2785
2878
|
const getSnapshot = React5.useCallback(() => {
|
|
@@ -2827,40 +2920,33 @@ function useThreads(options = {
|
|
|
2827
2920
|
const { scrollOnLoad = true } = options;
|
|
2828
2921
|
const client = useClient();
|
|
2829
2922
|
const room = useRoom();
|
|
2830
|
-
const
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
const { store, getThreadsAndInboxNotifications, incrementQuerySubscribers } = getExtrasForClient2(client);
|
|
2835
|
-
React5.useEffect(() => {
|
|
2836
|
-
void getThreadsAndInboxNotifications(room, queryKey, options);
|
|
2837
|
-
return incrementQuerySubscribers(queryKey);
|
|
2838
|
-
}, [room, queryKey]);
|
|
2839
|
-
const getter = React5.useCallback(
|
|
2840
|
-
() => store.getThreadsAsync(queryKey),
|
|
2841
|
-
[store, queryKey]
|
|
2842
|
-
);
|
|
2843
|
-
const selector = React5.useCallback(
|
|
2844
|
-
(result) => {
|
|
2845
|
-
if (!result.fullState) {
|
|
2846
|
-
return result;
|
|
2847
|
-
}
|
|
2848
|
-
const threads = selectThreads(result.fullState, {
|
|
2849
|
-
roomId: room.id,
|
|
2850
|
-
query: options.query,
|
|
2851
|
-
orderBy: "age"
|
|
2923
|
+
const { store, subscribeToRoomThreadsDeltaUpdates: subscribeToDeltaUpdates } = getRoomExtrasForClient(client);
|
|
2924
|
+
React5.useEffect(
|
|
2925
|
+
() => {
|
|
2926
|
+
void store.waitUntilRoomThreadsLoaded(room.id, options.query).catch(() => {
|
|
2852
2927
|
});
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
//
|
|
2928
|
+
}
|
|
2929
|
+
// NOTE: Deliberately *not* using a dependency array here!
|
|
2930
|
+
//
|
|
2931
|
+
// It is important to call waitUntil on *every* render.
|
|
2932
|
+
// This is harmless though, on most renders, except:
|
|
2933
|
+
// 1. The very first render, in which case we'll want to trigger the initial page fetch.
|
|
2934
|
+
// 2. All other subsequent renders now "just" return the same promise (a quick operation).
|
|
2935
|
+
// 3. If ever the promise would fail, then after 5 seconds it would reset, and on the very
|
|
2936
|
+
// *next* render after that, a *new* fetch/promise will get created.
|
|
2937
|
+
);
|
|
2938
|
+
React5.useEffect(subscribeToDeltaUpdates, [subscribeToDeltaUpdates]);
|
|
2939
|
+
const getter = React5.useCallback(
|
|
2940
|
+
() => store.getRoomThreadsAsync(room.id, options.query),
|
|
2941
|
+
[store, room.id, options.query]
|
|
2857
2942
|
);
|
|
2858
2943
|
const state = useSyncExternalStoreWithSelector2(
|
|
2859
2944
|
store.subscribeThreads,
|
|
2860
2945
|
getter,
|
|
2861
2946
|
getter,
|
|
2862
|
-
|
|
2947
|
+
identity2,
|
|
2863
2948
|
shallow2
|
|
2949
|
+
// NOTE: Using 2-level-deep shallow check here, because the result of selectThreads() is not stable!
|
|
2864
2950
|
);
|
|
2865
2951
|
useScrollToCommentOnLoadEffect(scrollOnLoad, state);
|
|
2866
2952
|
return state;
|
|
@@ -2868,7 +2954,7 @@ function useThreads(options = {
|
|
|
2868
2954
|
function useCommentsErrorListener(callback) {
|
|
2869
2955
|
const client = useClient();
|
|
2870
2956
|
const savedCallback = useLatest(callback);
|
|
2871
|
-
const { commentsErrorEventSource } =
|
|
2957
|
+
const { commentsErrorEventSource } = getRoomExtrasForClient(client);
|
|
2872
2958
|
React5.useEffect(() => {
|
|
2873
2959
|
return commentsErrorEventSource.subscribe(savedCallback.current);
|
|
2874
2960
|
}, [savedCallback, commentsErrorEventSource]);
|
|
@@ -2905,7 +2991,7 @@ function useCreateThread() {
|
|
|
2905
2991
|
comments: [newComment],
|
|
2906
2992
|
resolved: false
|
|
2907
2993
|
};
|
|
2908
|
-
const { store, onMutationFailure } =
|
|
2994
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
2909
2995
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2910
2996
|
type: "create-thread",
|
|
2911
2997
|
thread: newThread,
|
|
@@ -2938,7 +3024,7 @@ function useDeleteThread() {
|
|
|
2938
3024
|
const room = useRoom();
|
|
2939
3025
|
return React5.useCallback(
|
|
2940
3026
|
(threadId) => {
|
|
2941
|
-
const { store, onMutationFailure } =
|
|
3027
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
2942
3028
|
const thread = store.getFullState().threadsById[threadId];
|
|
2943
3029
|
const userId = getCurrentUserId(room);
|
|
2944
3030
|
if (thread?.comments?.[0]?.userId !== userId) {
|
|
@@ -2975,7 +3061,7 @@ function useEditThreadMetadata() {
|
|
|
2975
3061
|
const threadId = options.threadId;
|
|
2976
3062
|
const metadata = options.metadata;
|
|
2977
3063
|
const updatedAt = /* @__PURE__ */ new Date();
|
|
2978
|
-
const { store, onMutationFailure } =
|
|
3064
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
2979
3065
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
2980
3066
|
type: "edit-thread-metadata",
|
|
2981
3067
|
metadata,
|
|
@@ -3024,7 +3110,7 @@ function useCreateComment() {
|
|
|
3024
3110
|
reactions: [],
|
|
3025
3111
|
attachments: attachments ?? []
|
|
3026
3112
|
};
|
|
3027
|
-
const { store, onMutationFailure } =
|
|
3113
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3028
3114
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
3029
3115
|
type: "create-comment",
|
|
3030
3116
|
comment
|
|
@@ -3056,7 +3142,7 @@ function useEditComment() {
|
|
|
3056
3142
|
return React5.useCallback(
|
|
3057
3143
|
({ threadId, commentId, body, attachments }) => {
|
|
3058
3144
|
const editedAt = /* @__PURE__ */ new Date();
|
|
3059
|
-
const { store, onMutationFailure } =
|
|
3145
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3060
3146
|
const thread = store.getFullState().threadsById[threadId];
|
|
3061
3147
|
if (thread === void 0) {
|
|
3062
3148
|
console3.warn(
|
|
@@ -3108,7 +3194,7 @@ function useDeleteComment() {
|
|
|
3108
3194
|
return React5.useCallback(
|
|
3109
3195
|
({ threadId, commentId }) => {
|
|
3110
3196
|
const deletedAt = /* @__PURE__ */ new Date();
|
|
3111
|
-
const { store, onMutationFailure } =
|
|
3197
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3112
3198
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
3113
3199
|
type: "delete-comment",
|
|
3114
3200
|
threadId,
|
|
@@ -3146,7 +3232,7 @@ function useAddReaction() {
|
|
|
3146
3232
|
({ threadId, commentId, emoji }) => {
|
|
3147
3233
|
const createdAt = /* @__PURE__ */ new Date();
|
|
3148
3234
|
const userId = getCurrentUserId(room);
|
|
3149
|
-
const { store, onMutationFailure } =
|
|
3235
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3150
3236
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
3151
3237
|
type: "add-reaction",
|
|
3152
3238
|
threadId,
|
|
@@ -3189,7 +3275,7 @@ function useRemoveReaction() {
|
|
|
3189
3275
|
({ threadId, commentId, emoji }) => {
|
|
3190
3276
|
const userId = getCurrentUserId(room);
|
|
3191
3277
|
const removedAt = /* @__PURE__ */ new Date();
|
|
3192
|
-
const { store, onMutationFailure } =
|
|
3278
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3193
3279
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
3194
3280
|
type: "remove-reaction",
|
|
3195
3281
|
threadId,
|
|
@@ -3229,9 +3315,9 @@ function useMarkThreadAsRead() {
|
|
|
3229
3315
|
const room = useRoom();
|
|
3230
3316
|
return React5.useCallback(
|
|
3231
3317
|
(threadId) => {
|
|
3232
|
-
const { store, onMutationFailure } =
|
|
3318
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3233
3319
|
const inboxNotification = Object.values(
|
|
3234
|
-
store.getFullState().
|
|
3320
|
+
store.getFullState().notificationsById
|
|
3235
3321
|
).find(
|
|
3236
3322
|
(inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
|
|
3237
3323
|
);
|
|
@@ -3271,7 +3357,7 @@ function useMarkThreadAsResolved() {
|
|
|
3271
3357
|
return React5.useCallback(
|
|
3272
3358
|
(threadId) => {
|
|
3273
3359
|
const updatedAt = /* @__PURE__ */ new Date();
|
|
3274
|
-
const { store, onMutationFailure } =
|
|
3360
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3275
3361
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
3276
3362
|
type: "mark-thread-as-resolved",
|
|
3277
3363
|
threadId,
|
|
@@ -3305,7 +3391,7 @@ function useMarkThreadAsUnresolved() {
|
|
|
3305
3391
|
return React5.useCallback(
|
|
3306
3392
|
(threadId) => {
|
|
3307
3393
|
const updatedAt = /* @__PURE__ */ new Date();
|
|
3308
|
-
const { store, onMutationFailure } =
|
|
3394
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3309
3395
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
3310
3396
|
type: "mark-thread-as-unresolved",
|
|
3311
3397
|
threadId,
|
|
@@ -3335,10 +3421,10 @@ function useMarkThreadAsUnresolved() {
|
|
|
3335
3421
|
}
|
|
3336
3422
|
function useThreadSubscription(threadId) {
|
|
3337
3423
|
const client = useClient();
|
|
3338
|
-
const { store } =
|
|
3424
|
+
const { store } = getRoomExtrasForClient(client);
|
|
3339
3425
|
const selector = React5.useCallback(
|
|
3340
3426
|
(state) => {
|
|
3341
|
-
const inboxNotification = state.
|
|
3427
|
+
const inboxNotification = state.notifications.find(
|
|
3342
3428
|
(inboxNotification2) => inboxNotification2.kind === "thread" && inboxNotification2.threadId === threadId
|
|
3343
3429
|
);
|
|
3344
3430
|
const thread = state.threadsById[threadId];
|
|
@@ -3365,13 +3451,13 @@ function useRoomNotificationSettings() {
|
|
|
3365
3451
|
const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
|
|
3366
3452
|
const client = useClient();
|
|
3367
3453
|
const room = useRoom();
|
|
3368
|
-
const { store } =
|
|
3454
|
+
const { store } = getRoomExtrasForClient(client);
|
|
3369
3455
|
const getter = React5.useCallback(
|
|
3370
3456
|
() => store.getNotificationSettingsAsync(room.id),
|
|
3371
3457
|
[store, room.id]
|
|
3372
3458
|
);
|
|
3373
3459
|
React5.useEffect(() => {
|
|
3374
|
-
const { getInboxNotificationSettings } =
|
|
3460
|
+
const { getInboxNotificationSettings } = getRoomExtrasForClient(client);
|
|
3375
3461
|
void getInboxNotificationSettings(room);
|
|
3376
3462
|
}, [client, room]);
|
|
3377
3463
|
const settings = useSyncExternalStoreWithSelector2(
|
|
@@ -3389,7 +3475,7 @@ function useRoomNotificationSettingsSuspense() {
|
|
|
3389
3475
|
const updateRoomNotificationSettings = useUpdateRoomNotificationSettings();
|
|
3390
3476
|
const client = useClient();
|
|
3391
3477
|
const room = useRoom();
|
|
3392
|
-
const { store } =
|
|
3478
|
+
const { store } = getRoomExtrasForClient(client);
|
|
3393
3479
|
const getter = React5.useCallback(
|
|
3394
3480
|
() => store.getNotificationSettingsAsync(room.id),
|
|
3395
3481
|
[store, room.id]
|
|
@@ -3402,7 +3488,7 @@ function useRoomNotificationSettingsSuspense() {
|
|
|
3402
3488
|
shallow4
|
|
3403
3489
|
);
|
|
3404
3490
|
if (settings.isLoading) {
|
|
3405
|
-
const { getInboxNotificationSettings } =
|
|
3491
|
+
const { getInboxNotificationSettings } = getRoomExtrasForClient(client);
|
|
3406
3492
|
throw getInboxNotificationSettings(room);
|
|
3407
3493
|
} else if (settings.error) {
|
|
3408
3494
|
throw settings.error;
|
|
@@ -3420,7 +3506,7 @@ function useHistoryVersionData(versionId) {
|
|
|
3420
3506
|
setState({ isLoading: true });
|
|
3421
3507
|
const load = async () => {
|
|
3422
3508
|
try {
|
|
3423
|
-
const response = await room[
|
|
3509
|
+
const response = await room[kInternal3].getTextVersion(versionId);
|
|
3424
3510
|
const buffer = await response.arrayBuffer();
|
|
3425
3511
|
const data = new Uint8Array(buffer);
|
|
3426
3512
|
setState({
|
|
@@ -3443,7 +3529,7 @@ function useHistoryVersionData(versionId) {
|
|
|
3443
3529
|
function useHistoryVersions() {
|
|
3444
3530
|
const client = useClient();
|
|
3445
3531
|
const room = useRoom();
|
|
3446
|
-
const { store, getRoomVersions } =
|
|
3532
|
+
const { store, getRoomVersions } = getRoomExtrasForClient(client);
|
|
3447
3533
|
const getter = React5.useCallback(
|
|
3448
3534
|
() => store.getVersionsAsync(room.id),
|
|
3449
3535
|
[store, room.id]
|
|
@@ -3463,7 +3549,7 @@ function useHistoryVersions() {
|
|
|
3463
3549
|
function useHistoryVersionsSuspense() {
|
|
3464
3550
|
const client = useClient();
|
|
3465
3551
|
const room = useRoom();
|
|
3466
|
-
const { store } =
|
|
3552
|
+
const { store } = getRoomExtrasForClient(client);
|
|
3467
3553
|
const getter = React5.useCallback(
|
|
3468
3554
|
() => store.getVersionsAsync(room.id),
|
|
3469
3555
|
[store, room.id]
|
|
@@ -3476,7 +3562,7 @@ function useHistoryVersionsSuspense() {
|
|
|
3476
3562
|
shallow4
|
|
3477
3563
|
);
|
|
3478
3564
|
if (state.isLoading) {
|
|
3479
|
-
const { getRoomVersions } =
|
|
3565
|
+
const { getRoomVersions } = getRoomExtrasForClient(client);
|
|
3480
3566
|
throw getRoomVersions(room);
|
|
3481
3567
|
} else if (state.error) {
|
|
3482
3568
|
throw state.error;
|
|
@@ -3488,7 +3574,7 @@ function useUpdateRoomNotificationSettings() {
|
|
|
3488
3574
|
const room = useRoom();
|
|
3489
3575
|
return React5.useCallback(
|
|
3490
3576
|
(settings) => {
|
|
3491
|
-
const { store, onMutationFailure } =
|
|
3577
|
+
const { store, onMutationFailure } = getRoomExtrasForClient(client);
|
|
3492
3578
|
const optimisticUpdateId = store.addOptimisticUpdate({
|
|
3493
3579
|
type: "update-notification-settings",
|
|
3494
3580
|
roomId: room.id,
|
|
@@ -3571,47 +3657,14 @@ function useStorageStatusSuspense(options) {
|
|
|
3571
3657
|
function useThreadsSuspense(options = {
|
|
3572
3658
|
query: { metadata: {} }
|
|
3573
3659
|
}) {
|
|
3574
|
-
const { scrollOnLoad = true } = options;
|
|
3575
3660
|
const client = useClient();
|
|
3576
3661
|
const room = useRoom();
|
|
3577
|
-
const
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
);
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
if (query === void 0 || query.isLoading) {
|
|
3584
|
-
throw getThreadsAndInboxNotifications(room, queryKey, options);
|
|
3585
|
-
}
|
|
3586
|
-
if (query.error) {
|
|
3587
|
-
throw query.error;
|
|
3588
|
-
}
|
|
3589
|
-
const selector = React5.useCallback(
|
|
3590
|
-
(state2) => {
|
|
3591
|
-
return {
|
|
3592
|
-
threads: selectThreads(state2, {
|
|
3593
|
-
roomId: room.id,
|
|
3594
|
-
query: options.query,
|
|
3595
|
-
orderBy: "age"
|
|
3596
|
-
}),
|
|
3597
|
-
isLoading: false
|
|
3598
|
-
};
|
|
3599
|
-
},
|
|
3600
|
-
[room, queryKey]
|
|
3601
|
-
// eslint-disable-line react-hooks/exhaustive-deps
|
|
3602
|
-
);
|
|
3603
|
-
React5.useEffect(() => {
|
|
3604
|
-
const { incrementQuerySubscribers } = getExtrasForClient2(client);
|
|
3605
|
-
return incrementQuerySubscribers(queryKey);
|
|
3606
|
-
}, [client, queryKey]);
|
|
3607
|
-
const state = useSyncExternalStoreWithSelector2(
|
|
3608
|
-
store.subscribeThreads,
|
|
3609
|
-
store.getFullState,
|
|
3610
|
-
store.getFullState,
|
|
3611
|
-
selector
|
|
3612
|
-
);
|
|
3613
|
-
useScrollToCommentOnLoadEffect(scrollOnLoad, state);
|
|
3614
|
-
return state;
|
|
3662
|
+
const { store } = getRoomExtrasForClient(client);
|
|
3663
|
+
use(store.waitUntilRoomThreadsLoaded(room.id, options.query));
|
|
3664
|
+
const result = useThreads(options);
|
|
3665
|
+
assert2(!result.error, "Did not expect error");
|
|
3666
|
+
assert2(!result.isLoading, "Did not expect loading");
|
|
3667
|
+
return result;
|
|
3615
3668
|
}
|
|
3616
3669
|
function selectorFor_useAttachmentUrl(state) {
|
|
3617
3670
|
if (state === void 0 || state?.isLoading) {
|
|
@@ -3628,7 +3681,7 @@ function selectorFor_useAttachmentUrl(state) {
|
|
|
3628
3681
|
}
|
|
3629
3682
|
function useAttachmentUrl(attachmentId) {
|
|
3630
3683
|
const room = useRoom();
|
|
3631
|
-
const { attachmentUrlsStore } = room[
|
|
3684
|
+
const { attachmentUrlsStore } = room[kInternal3];
|
|
3632
3685
|
const getAttachmentUrlState = React5.useCallback(
|
|
3633
3686
|
() => attachmentUrlsStore.getState(attachmentId),
|
|
3634
3687
|
[attachmentUrlsStore, attachmentId]
|
|
@@ -3646,7 +3699,7 @@ function useAttachmentUrl(attachmentId) {
|
|
|
3646
3699
|
}
|
|
3647
3700
|
function useAttachmentUrlSuspense(attachmentId) {
|
|
3648
3701
|
const room = useRoom();
|
|
3649
|
-
const { attachmentUrlsStore } = room[
|
|
3702
|
+
const { attachmentUrlsStore } = room[kInternal3];
|
|
3650
3703
|
const getAttachmentUrlState = React5.useCallback(
|
|
3651
3704
|
() => attachmentUrlsStore.getState(attachmentId),
|
|
3652
3705
|
[attachmentUrlsStore, attachmentId]
|
|
@@ -3675,9 +3728,6 @@ function useAttachmentUrlSuspense(attachmentId) {
|
|
|
3675
3728
|
function createRoomContext(client) {
|
|
3676
3729
|
return getOrCreateRoomContextBundle(client);
|
|
3677
3730
|
}
|
|
3678
|
-
function generateQueryKey(roomId, options) {
|
|
3679
|
-
return `${roomId}-${stringify2(options ?? {})}`;
|
|
3680
|
-
}
|
|
3681
3731
|
var _RoomProvider = RoomProvider;
|
|
3682
3732
|
var _useBroadcastEvent = useBroadcastEvent;
|
|
3683
3733
|
var _useOthersListener = useOthersListener;
|
|
@@ -3721,8 +3771,8 @@ export {
|
|
|
3721
3771
|
PKG_FORMAT,
|
|
3722
3772
|
ClientSideSuspense,
|
|
3723
3773
|
RoomContext,
|
|
3724
|
-
ClientContext,
|
|
3725
3774
|
selectThreads,
|
|
3775
|
+
ClientContext,
|
|
3726
3776
|
getUmbrellaStoreForClient,
|
|
3727
3777
|
useClient,
|
|
3728
3778
|
LiveblocksProvider,
|
|
@@ -3800,4 +3850,4 @@ export {
|
|
|
3800
3850
|
_useStorageRoot,
|
|
3801
3851
|
_useUpdateMyPresence
|
|
3802
3852
|
};
|
|
3803
|
-
//# sourceMappingURL=chunk-
|
|
3853
|
+
//# sourceMappingURL=chunk-BNSPCUSO.mjs.map
|