@semapps/activitypub-components 0.6.7 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +378 -545
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +203 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +380 -547
- package/dist/index.es.js.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs.js
CHANGED
|
@@ -8,10 +8,10 @@ var $583VT$muistylesmakeStyles = require("@mui/styles/makeStyles");
|
|
|
8
8
|
var $583VT$muiiconsmaterialSend = require("@mui/icons-material/Send");
|
|
9
9
|
var $583VT$semappssemanticdataprovider = require("@semapps/semantic-data-provider");
|
|
10
10
|
var $583VT$semappsauthprovider = require("@semapps/auth-provider");
|
|
11
|
+
var $583VT$reactquery = require("react-query");
|
|
11
12
|
var $583VT$tiptapcore = require("@tiptap/core");
|
|
12
13
|
var $583VT$tiptapextensionmention = require("@tiptap/extension-mention");
|
|
13
14
|
var $583VT$semappsfieldcomponents = require("@semapps/field-components");
|
|
14
|
-
var $583VT$reactquery = require("react-query");
|
|
15
15
|
var $583VT$tiptapreact = require("@tiptap/react");
|
|
16
16
|
var $583VT$tippyjs = require("tippy.js");
|
|
17
17
|
|
|
@@ -28,9 +28,9 @@ $parcel$export(module.exports, "CommentsField", () => $2e5504cc4159ca8d$export$2
|
|
|
28
28
|
$parcel$export(module.exports, "CollectionList", () => $505d598a33288aad$export$2e2bcd8739ae039);
|
|
29
29
|
$parcel$export(module.exports, "ReferenceCollectionField", () => $b0c94a9bdea99da5$export$2e2bcd8739ae039);
|
|
30
30
|
$parcel$export(module.exports, "useCollection", () => $5ca5f7e9fc1c3544$export$2e2bcd8739ae039);
|
|
31
|
-
$parcel$export(module.exports, "useInbox", () => $
|
|
32
|
-
$parcel$export(module.exports, "useNodeinfo", () => $
|
|
33
|
-
$parcel$export(module.exports, "useOutbox", () => $
|
|
31
|
+
$parcel$export(module.exports, "useInbox", () => $486f741c94cd8f74$export$2e2bcd8739ae039);
|
|
32
|
+
$parcel$export(module.exports, "useNodeinfo", () => $59fc2d2cba62bd8e$export$2e2bcd8739ae039);
|
|
33
|
+
$parcel$export(module.exports, "useOutbox", () => $456aea3814dded7d$export$2e2bcd8739ae039);
|
|
34
34
|
$parcel$export(module.exports, "useWebfinger", () => $5b61553556e35016$export$2e2bcd8739ae039);
|
|
35
35
|
$parcel$export(module.exports, "useMentions", () => $968ea07fb81eda0b$export$2e2bcd8739ae039);
|
|
36
36
|
$parcel$export(module.exports, "ACTIVITY_TYPES", () => $ebea823cebb2f44b$export$1ec8e53e7d982d22);
|
|
@@ -108,102 +108,365 @@ const $ebea823cebb2f44b$export$4d8d554031975581 = "https://www.w3.org/ns/activit
|
|
|
108
108
|
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
const $03510abb28fd3d8a$export$e57ff0f701c44363 = (value)=>{
|
|
115
|
+
// If the field is null-ish, we suppose there are no values.
|
|
116
|
+
if (value === null || value === undefined) return [];
|
|
117
|
+
// Return as is.
|
|
118
|
+
if (Array.isArray(value)) return value;
|
|
119
|
+
// Single value is made an array.
|
|
120
|
+
return [
|
|
121
|
+
value
|
|
122
|
+
];
|
|
123
|
+
};
|
|
124
|
+
var $03510abb28fd3d8a$export$2e2bcd8739ae039 = {
|
|
125
|
+
arrayOf: $03510abb28fd3d8a$export$e57ff0f701c44363
|
|
126
|
+
};
|
|
127
|
+
const $03510abb28fd3d8a$export$34aed805e991a647 = (iterable, predicate)=>{
|
|
128
|
+
const seen = new Set();
|
|
129
|
+
return iterable.filter((item)=>{
|
|
130
|
+
const key = predicate(item);
|
|
131
|
+
if (seen.has(key)) return false;
|
|
132
|
+
seen.add(key);
|
|
133
|
+
return true;
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
|
|
139
|
+
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
140
|
+
const items = (0, $583VT$react.useMemo)(()=>pages.flatMap((p)=>(0, $03510abb28fd3d8a$export$e57ff0f701c44363)(p.orderedItems || p.items)), [
|
|
141
|
+
pages
|
|
142
|
+
]);
|
|
143
|
+
// We will force dereference, if some items are not URI string references.
|
|
144
|
+
const shouldDereference = (0, $583VT$react.useMemo)(()=>{
|
|
145
|
+
return dereferenceItems || items.some((item)=>typeof item !== "string");
|
|
146
|
+
}, [
|
|
147
|
+
dereferenceItems,
|
|
148
|
+
items
|
|
149
|
+
]);
|
|
150
|
+
// Dereference all items, if necessary (even if shouldDereference is false, the hook needs to be called).
|
|
151
|
+
const itemQueries = (0, $583VT$reactquery.useQueries)(!shouldDereference ? [] : items.filter((item)=>typeof item === "string").map((itemUri)=>({
|
|
152
|
+
queryKey: [
|
|
153
|
+
"resource",
|
|
154
|
+
itemUri
|
|
155
|
+
],
|
|
156
|
+
queryFn: async ()=>(await dataProvider.fetch(itemUri)).json,
|
|
157
|
+
staleTime: Infinity
|
|
158
|
+
})));
|
|
159
|
+
if (!shouldDereference) return {
|
|
160
|
+
loadedItems: items,
|
|
161
|
+
isLoading: false,
|
|
162
|
+
isFetching: false
|
|
163
|
+
};
|
|
164
|
+
// Put all loaded items together (might be dereferenced already, so concatenate).
|
|
165
|
+
const loadedItems = items.filter((item)=>typeof item !== "string").concat(itemQueries.flatMap((itemQuery)=>{
|
|
166
|
+
return itemQuery.isSuccess && itemQuery.data || [];
|
|
167
|
+
}));
|
|
168
|
+
const errors = itemQueries.filter((q)=>q.error);
|
|
169
|
+
return {
|
|
170
|
+
loadedItems: loadedItems,
|
|
171
|
+
isLoading: itemQueries.some((q)=>q.isLoading),
|
|
172
|
+
isFetching: itemQueries.some((q)=>q.isFetching),
|
|
173
|
+
errors: errors.length > 0 ? errors : undefined
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Subscribe a collection. Supports pagination.
|
|
178
|
+
* @param predicateOrUrl The collection URI or the predicate to get the collection URI from the identity (webId).
|
|
179
|
+
* @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
|
|
180
|
+
*/ const $5ca5f7e9fc1c3544$var$useCollection = (predicateOrUrl, options = {})=>{
|
|
181
|
+
const { dereferenceItems: dereferenceItems = false, liveUpdates: liveUpdates = true } = options;
|
|
112
182
|
const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
|
|
113
|
-
const
|
|
114
|
-
|
|
183
|
+
const [totalItems, setTotalItems] = (0, $583VT$react.useState)();
|
|
184
|
+
const queryClient = (0, $583VT$reactquery.useQueryClient)();
|
|
185
|
+
const [hasLiveUpdates, setHasLiveUpdates] = (0, $583VT$react.useState)({
|
|
186
|
+
status: "connecting"
|
|
187
|
+
});
|
|
188
|
+
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
189
|
+
// Get collectionUrl from webId predicate or URL.
|
|
190
|
+
const collectionUrl = (0, $583VT$react.useMemo)(()=>{
|
|
191
|
+
if (predicateOrUrl) {
|
|
192
|
+
if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
|
|
193
|
+
if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
// throw new Error(`No URL available for useCollection: ${predicateOrUrl}.`);
|
|
115
197
|
}, [
|
|
116
|
-
identity
|
|
198
|
+
identity,
|
|
199
|
+
predicateOrUrl
|
|
117
200
|
]);
|
|
118
|
-
|
|
119
|
-
|
|
201
|
+
// Fetch page of collection item references (if pageParam provided)
|
|
202
|
+
// or default to `collectionUrl` (which should give you the first page).
|
|
203
|
+
const fetchCollection = (0, $583VT$react.useCallback)(async ({ pageParam: nextPageUrl })=>{
|
|
204
|
+
// Fetch page or first page (collectionUrl)
|
|
205
|
+
let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
|
|
206
|
+
if (json.totalItems) setTotalItems(json.totalItems);
|
|
207
|
+
// If first page, handle this here.
|
|
208
|
+
if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
|
|
209
|
+
if (json.first?.items) {
|
|
210
|
+
if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
|
|
211
|
+
({ json: json } = await dataProvider.fetch(json.first?.next));
|
|
212
|
+
else json = json.first;
|
|
213
|
+
} else // Fetch the first page
|
|
214
|
+
({ json: json } = await dataProvider.fetch(json.first));
|
|
215
|
+
}
|
|
216
|
+
return json;
|
|
120
217
|
}, [
|
|
121
|
-
|
|
218
|
+
dataProvider,
|
|
219
|
+
collectionUrl,
|
|
220
|
+
identity,
|
|
221
|
+
setTotalItems
|
|
122
222
|
]);
|
|
123
|
-
//
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
223
|
+
// Use infiniteQuery to handle pagination, fetching, etc.
|
|
224
|
+
const { data: pageData, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $583VT$reactquery.useInfiniteQuery)([
|
|
225
|
+
"collection",
|
|
226
|
+
{
|
|
227
|
+
collectionUrl: collectionUrl
|
|
228
|
+
}
|
|
229
|
+
], fetchCollection, {
|
|
230
|
+
enabled: !!(collectionUrl && identity?.id),
|
|
231
|
+
getNextPageParam: (lastPage)=>lastPage.next,
|
|
232
|
+
getPreviousPageParam: (firstPage)=>firstPage.prev
|
|
233
|
+
});
|
|
234
|
+
// Put all items together in a list (and dereference, if required).
|
|
235
|
+
const { loadedItems: items, isLoading: isLoadingItems, isFetching: isFetchingItems, errors: itemErrors } = $5ca5f7e9fc1c3544$var$useItemsFromPages(pageData?.pages ?? [], dereferenceItems);
|
|
236
|
+
const allErrors = (0, $03510abb28fd3d8a$export$e57ff0f701c44363)(collectionError).concat((0, $03510abb28fd3d8a$export$e57ff0f701c44363)(itemErrors));
|
|
237
|
+
const addItem = (0, $583VT$react.useCallback)((item, shouldRefetch = true)=>{
|
|
238
|
+
queryClient.setQueryData([
|
|
239
|
+
"collection",
|
|
240
|
+
{
|
|
241
|
+
collectionUrl: collectionUrl
|
|
242
|
+
}
|
|
243
|
+
], (oldData)=>{
|
|
244
|
+
if (!oldData) return oldData;
|
|
245
|
+
setTotalItems(totalItems && totalItems + 1);
|
|
246
|
+
// Destructure, so react knows, it needs to re-render the pages.
|
|
247
|
+
const pages = [
|
|
248
|
+
...oldData.pages
|
|
249
|
+
];
|
|
250
|
+
const firstPageItems = pages?.[0]?.orderedItems || pages?.[0]?.items || [];
|
|
251
|
+
firstPageItems.unshift(item);
|
|
252
|
+
oldData.pages = pages;
|
|
253
|
+
return oldData;
|
|
137
254
|
});
|
|
138
|
-
|
|
255
|
+
if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
|
|
256
|
+
"collection",
|
|
257
|
+
{
|
|
258
|
+
collectionUrl: collectionUrl
|
|
259
|
+
}
|
|
260
|
+
], {
|
|
261
|
+
active: true,
|
|
262
|
+
exact: true
|
|
263
|
+
}), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
|
|
139
264
|
}, [
|
|
140
|
-
|
|
265
|
+
queryClient,
|
|
266
|
+
collectionUrl
|
|
141
267
|
]);
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
body: query,
|
|
163
|
-
headers: new Headers({
|
|
164
|
-
Accept: "application/ld+json",
|
|
165
|
-
Authorization: token ? `Bearer ${token}` : undefined
|
|
166
|
-
})
|
|
268
|
+
const removeItem = (0, $583VT$react.useCallback)((item, shouldRefetch = true)=>{
|
|
269
|
+
queryClient.setQueryData([
|
|
270
|
+
"collection",
|
|
271
|
+
{
|
|
272
|
+
collectionUrl: collectionUrl
|
|
273
|
+
}
|
|
274
|
+
], (oldData)=>{
|
|
275
|
+
if (!oldData) return oldData;
|
|
276
|
+
setTotalItems(totalItems && totalItems - 1);
|
|
277
|
+
// Destructure, so react knows, it needs to re-render the pages array.
|
|
278
|
+
const pages = [
|
|
279
|
+
...oldData.pages
|
|
280
|
+
];
|
|
281
|
+
// Find the item in all pages and remove the item to be removed (either item.id or just item)
|
|
282
|
+
pages.forEach((page)=>{
|
|
283
|
+
if (page.orderedItems) page.orderedItems = page.orderedItems.filter((i)=>(i.id || i) !== (item.id || item));
|
|
284
|
+
else if (page.items) page.items = page.items.filter((i)=>(i.id || i) !== (item?.id || item));
|
|
285
|
+
});
|
|
286
|
+
oldData.pages = pages;
|
|
287
|
+
return oldData;
|
|
167
288
|
});
|
|
168
|
-
if (
|
|
169
|
-
|
|
289
|
+
if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
|
|
290
|
+
"collection",
|
|
291
|
+
{
|
|
292
|
+
collectionUrl: collectionUrl
|
|
293
|
+
}
|
|
294
|
+
], {
|
|
295
|
+
active: true,
|
|
296
|
+
exact: true
|
|
297
|
+
}), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
|
|
298
|
+
}, [
|
|
299
|
+
queryClient,
|
|
300
|
+
collectionUrl
|
|
301
|
+
]);
|
|
302
|
+
// Live Updates
|
|
303
|
+
(0, $583VT$react.useEffect)(()=>{
|
|
304
|
+
if (liveUpdates && collectionUrl) // Create ws that listens to collectionUri changes
|
|
305
|
+
(0, $583VT$semappssemanticdataprovider.getOrCreateWsChannel)(dataProvider.fetch, collectionUrl).then((webSocket)=>{
|
|
306
|
+
webSocket.addEventListener("message", (e)=>{
|
|
307
|
+
const data = JSON.parse(e.data);
|
|
308
|
+
if (data.type === "Add") addItem(data.object, true);
|
|
309
|
+
else if (data.type === "Remove") removeItem(data.object, true);
|
|
310
|
+
});
|
|
311
|
+
webSocket.addEventListener("error", (e)=>{
|
|
312
|
+
setHasLiveUpdates({
|
|
313
|
+
status: "error",
|
|
314
|
+
error: e
|
|
315
|
+
});
|
|
316
|
+
// TODO: Retry after a while
|
|
317
|
+
});
|
|
318
|
+
webSocket.addEventListener("close", (e)=>{
|
|
319
|
+
if (!hasLiveUpdates.error) setHasLiveUpdates({
|
|
320
|
+
...hasLiveUpdates,
|
|
321
|
+
status: "closed"
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
setHasLiveUpdates({
|
|
325
|
+
status: "connected",
|
|
326
|
+
webSocket: webSocket
|
|
327
|
+
});
|
|
328
|
+
}).catch(()=>{}); // If it fails, we won't receive live updates. But that's okay.
|
|
170
329
|
}, [
|
|
171
|
-
|
|
172
|
-
|
|
330
|
+
collectionUrl,
|
|
331
|
+
liveUpdates,
|
|
332
|
+
dataProvider
|
|
173
333
|
]);
|
|
174
334
|
return {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
335
|
+
items: items,
|
|
336
|
+
totalItems: totalItems,
|
|
337
|
+
error: allErrors.length > 0 && allErrors,
|
|
338
|
+
refetch: refetch,
|
|
339
|
+
fetchNextPage: fetchNextPage,
|
|
340
|
+
addItem: addItem,
|
|
341
|
+
removeItem: removeItem,
|
|
342
|
+
hasNextPage: hasNextPage,
|
|
343
|
+
isLoading: isLoadingPage || isLoadingItems,
|
|
344
|
+
isFetching: isFetchingPage || isFetchingItems,
|
|
345
|
+
isFetchingNextPage: isFetchingNextPage,
|
|
346
|
+
url: collectionUrl,
|
|
347
|
+
hasLiveUpdates: hasLiveUpdates
|
|
180
348
|
};
|
|
181
349
|
};
|
|
182
|
-
var $
|
|
350
|
+
var $5ca5f7e9fc1c3544$export$2e2bcd8739ae039 = $5ca5f7e9fc1c3544$var$useCollection;
|
|
183
351
|
|
|
184
352
|
|
|
185
353
|
|
|
186
354
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
};
|
|
206
|
-
}
|
|
355
|
+
/**
|
|
356
|
+
* Hook used internally by useInbox and useOutbox. This is not exported.
|
|
357
|
+
* @param webSocket WebSocket which allow to listen to the inbox or outbox
|
|
358
|
+
* @param existingActivities Partial list of activities already received in the inbox and outbox
|
|
359
|
+
*/ const $5e70f9d0635e25dd$var$useAwaitActivity = (webSocket, existingActivities)=>{
|
|
360
|
+
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
361
|
+
// TODO Allow to pass an object, and automatically dereference it if required, like on the @semapps/activitypub matchActivity util
|
|
362
|
+
return (0, $583VT$react.useCallback)((matchActivity, options = {})=>{
|
|
363
|
+
const { timeout: timeout = 30000, checkExistingActivities: checkExistingActivities = false } = options;
|
|
364
|
+
return new Promise((resolve, reject)=>{
|
|
365
|
+
if (webSocket) {
|
|
366
|
+
const onMessage = (event)=>{
|
|
367
|
+
const data = JSON.parse(event.data);
|
|
368
|
+
if (data.type === "Add") dataProvider.fetch(data.object).then(({ json: json })=>{
|
|
369
|
+
if (matchActivity(json)) {
|
|
370
|
+
webSocket.removeEventListener("message", onMessage);
|
|
371
|
+
return resolve(json);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
};
|
|
375
|
+
webSocket.addEventListener("message", onMessage);
|
|
376
|
+
// TODO reconnect if connection closed
|
|
377
|
+
webSocket.addEventListener("error", (e)=>{
|
|
378
|
+
reject(e);
|
|
379
|
+
});
|
|
380
|
+
webSocket.addEventListener("close", (e)=>{
|
|
381
|
+
reject(new Error(`${e.reason} (Code: ${e.code})`));
|
|
382
|
+
});
|
|
383
|
+
// If a list of activities is already loaded, verify if there is a match
|
|
384
|
+
if (existingActivities && checkExistingActivities) for (const a of existingActivities){
|
|
385
|
+
if (typeof a !== "string") {
|
|
386
|
+
if (matchActivity(a)) {
|
|
387
|
+
webSocket.removeEventListener("message", onMessage);
|
|
388
|
+
return resolve(a);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
setTimeout(()=>{
|
|
393
|
+
webSocket.removeEventListener("message", onMessage);
|
|
394
|
+
reject(new Error("Timeout"));
|
|
395
|
+
}, timeout);
|
|
396
|
+
} else throw new Error("WebSocket is not initialized !");
|
|
397
|
+
});
|
|
398
|
+
}, [
|
|
399
|
+
webSocket,
|
|
400
|
+
existingActivities,
|
|
401
|
+
dataProvider
|
|
402
|
+
]);
|
|
403
|
+
};
|
|
404
|
+
var $5e70f9d0635e25dd$export$2e2bcd8739ae039 = $5e70f9d0635e25dd$var$useAwaitActivity;
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Hook to fetch and post to the outbox of the logged user.
|
|
409
|
+
* Returns the same data as the useCollection hooks, plus:
|
|
410
|
+
* - `post`: a function to post a new activity in the user's outbox
|
|
411
|
+
* - `awaitActivity`: a function to wait for a certain activity to be posted
|
|
412
|
+
* - `owner`: the WebID of the outbox's owner
|
|
413
|
+
* See https://semapps.org/docs/frontend/activitypub-components#useoutbox for usage
|
|
414
|
+
* @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
|
|
415
|
+
*/ const $456aea3814dded7d$var$useOutbox = (options = {})=>{
|
|
416
|
+
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
417
|
+
const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
|
|
418
|
+
const { url: url, hasLiveUpdates: hasLiveUpdates, items: items, ...rest } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)("outbox", options);
|
|
419
|
+
const awaitActivity = (0, $5e70f9d0635e25dd$export$2e2bcd8739ae039)(hasLiveUpdates.webSocket, items);
|
|
420
|
+
// Post an activity to the logged user's outbox and return its URI
|
|
421
|
+
const post = (0, $583VT$react.useCallback)(async (activity)=>{
|
|
422
|
+
if (!url) throw new Error("Cannot post to outbox before user identity is loaded. Please use the isLoading argument of useOutbox");
|
|
423
|
+
const { headers: headers } = await dataProvider.fetch(url, {
|
|
424
|
+
method: "POST",
|
|
425
|
+
body: JSON.stringify({
|
|
426
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
427
|
+
...activity
|
|
428
|
+
})
|
|
429
|
+
});
|
|
430
|
+
return headers.get("Location");
|
|
431
|
+
}, [
|
|
432
|
+
url,
|
|
433
|
+
dataProvider
|
|
434
|
+
]);
|
|
435
|
+
return {
|
|
436
|
+
url: url,
|
|
437
|
+
hasLiveUpdates: hasLiveUpdates,
|
|
438
|
+
items: items,
|
|
439
|
+
post: post,
|
|
440
|
+
awaitActivity: awaitActivity,
|
|
441
|
+
owner: identity?.id,
|
|
442
|
+
...rest
|
|
443
|
+
};
|
|
444
|
+
};
|
|
445
|
+
var $456aea3814dded7d$export$2e2bcd8739ae039 = $456aea3814dded7d$var$useOutbox;
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
// Fix a bug in the current version of the mention extension
|
|
451
|
+
// (The { id, label } object is located inside the id property)
|
|
452
|
+
// See https://github.com/ueberdosis/tiptap/pull/1322
|
|
453
|
+
const $9b1343b281972d72$var$CustomMention = (0, ($parcel$interopDefault($583VT$tiptapextensionmention))).extend({
|
|
454
|
+
renderHTML ({ node: node, HTMLAttributes: HTMLAttributes }) {
|
|
455
|
+
return [
|
|
456
|
+
"span",
|
|
457
|
+
(0, $583VT$tiptapcore.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes),
|
|
458
|
+
`@${node.attrs.id.label}`
|
|
459
|
+
];
|
|
460
|
+
},
|
|
461
|
+
addAttributes () {
|
|
462
|
+
return {
|
|
463
|
+
label: {
|
|
464
|
+
default: null,
|
|
465
|
+
parseHTML: (element)=>{
|
|
466
|
+
return {
|
|
467
|
+
label: element.getAttribute("data-mention-label")
|
|
468
|
+
};
|
|
469
|
+
},
|
|
207
470
|
renderHTML: (attributes)=>{
|
|
208
471
|
if (!attributes.id.label) return {};
|
|
209
472
|
return {
|
|
@@ -284,7 +547,7 @@ const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder:
|
|
|
284
547
|
const userDataModel = (0, $583VT$semappssemanticdataprovider.useDataModel)(userResource);
|
|
285
548
|
const classes = $703eba3e46be7ee5$var$useStyles();
|
|
286
549
|
const notify = (0, $583VT$reactadmin.useNotify)();
|
|
287
|
-
const outbox = (0, $
|
|
550
|
+
const outbox = (0, $456aea3814dded7d$export$2e2bcd8739ae039)();
|
|
288
551
|
const [expanded, setExpanded] = (0, $583VT$react.useState)(false);
|
|
289
552
|
const [openAuth, setOpenAuth] = (0, $583VT$react.useState)(false);
|
|
290
553
|
const onSubmit = (0, $583VT$react.useCallback)(async (values)=>{
|
|
@@ -544,186 +807,9 @@ var $d68cd57b2d06b6d5$export$2e2bcd8739ae039 = $d68cd57b2d06b6d5$var$CommentsLis
|
|
|
544
807
|
|
|
545
808
|
|
|
546
809
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
const $03510abb28fd3d8a$export$e57ff0f701c44363 = (value)=>{
|
|
551
|
-
// If the field is null-ish, we suppose there are no values.
|
|
552
|
-
if (value === null || value === undefined) return [];
|
|
553
|
-
// Return as is.
|
|
554
|
-
if (Array.isArray(value)) return value;
|
|
555
|
-
// Single value is made an array.
|
|
556
|
-
return [
|
|
557
|
-
value
|
|
558
|
-
];
|
|
559
|
-
};
|
|
560
|
-
var $03510abb28fd3d8a$export$2e2bcd8739ae039 = {
|
|
561
|
-
arrayOf: $03510abb28fd3d8a$export$e57ff0f701c44363
|
|
562
|
-
};
|
|
563
|
-
const $03510abb28fd3d8a$export$34aed805e991a647 = (iterable, predicate)=>{
|
|
564
|
-
const seen = new Set();
|
|
565
|
-
return iterable.filter((item)=>{
|
|
566
|
-
const key = predicate(item);
|
|
567
|
-
if (seen.has(key)) return false;
|
|
568
|
-
seen.add(key);
|
|
569
|
-
return true;
|
|
570
|
-
});
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
const $2b75a2f49c9ef165$var$useItemsFromPagesAndNotifications = (pages, notifications, dereferenceItems)=>{
|
|
575
|
-
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
576
|
-
// Add all items from pages and process notifications (possibly new and deleted items).
|
|
577
|
-
const items = (0, $583VT$react.useMemo)(()=>{
|
|
578
|
-
const addItems = notifications.map((n)=>n.type === "Add").map((n)=>n.object);
|
|
579
|
-
const removeItems = notifications.map((n)=>n.type === "Remove").map((n)=>n.object.id || n.object);
|
|
580
|
-
const currentItems = !pages ? [] : pages.flatMap((p)=>(0, $03510abb28fd3d8a$export$e57ff0f701c44363)(p.orderedItems || p.items));
|
|
581
|
-
const currentAndNew = currentItems.concat(addItems);
|
|
582
|
-
return currentAndNew// Filter out removed items.
|
|
583
|
-
.filter((item)=>!removeItems.some((r)=>(r.id ?? r) === (item.id ?? item)))// Filter duplicates.
|
|
584
|
-
.filter((item)=>currentAndNew.some((i2)=>(i2.id ?? i2) === (item.id ?? item)));
|
|
585
|
-
}, pages, notifications);
|
|
586
|
-
if (!dereferenceItems) return {
|
|
587
|
-
loadedItems: items,
|
|
588
|
-
isLoading: false,
|
|
589
|
-
isFetching: false
|
|
590
|
-
};
|
|
591
|
-
// Dereference all items, if they are not yet.
|
|
592
|
-
const itemQueries = (0, $583VT$reactquery.useQueries)(items.filter((item)=>typeof item === "string").map((itemUri)=>({
|
|
593
|
-
queryKey: [
|
|
594
|
-
"resource",
|
|
595
|
-
itemUri
|
|
596
|
-
],
|
|
597
|
-
queryFn: async ()=>(await dataProvider.fetch(itemUri)).json,
|
|
598
|
-
staleTime: Infinity
|
|
599
|
-
})));
|
|
600
|
-
// Put all loaded items together (might be dereferenced already, so concatenate).
|
|
601
|
-
const loadedItems = items.filter((item)=>typeof item !== "string").concat(itemQueries.flatMap((itemQuery)=>{
|
|
602
|
-
return itemQuery.isSuccess && itemQuery.data || [];
|
|
603
|
-
}));
|
|
604
|
-
console.log("loadedItems", loadedItems.length, "total", items.length);
|
|
605
|
-
const errors = itemQueries.filter((q)=>q.error);
|
|
606
|
-
return {
|
|
607
|
-
loadedItems: loadedItems,
|
|
608
|
-
isLoading: itemQueries.some((q)=>q.isLoading),
|
|
609
|
-
isFetching: itemQueries.some((q)=>q.isFetching),
|
|
610
|
-
errors: errors.length > 0 && errors
|
|
611
|
-
};
|
|
612
|
-
};
|
|
613
|
-
const $2b75a2f49c9ef165$var$useCollection = (predicateOrUrl, options = {})=>{
|
|
614
|
-
const { dereferenceItems: dereferenceItems = false, liveUpdates: liveUpdates = true } = options;
|
|
615
|
-
const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
|
|
616
|
-
const [totalItems, setTotalItems] = (0, $583VT$react.useState)();
|
|
617
|
-
const [notifications, setNotifications] = (0, $583VT$react.useState)([]);
|
|
618
|
-
const [hasLiveUpdates, setHasLiveUpdates] = (0, $583VT$react.useState)({
|
|
619
|
-
status: "disconnected",
|
|
620
|
-
error: undefined
|
|
621
|
-
});
|
|
622
|
-
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
623
|
-
// Get collectionUrl from webId predicate or URL.
|
|
624
|
-
const collectionUrl = (0, $583VT$react.useMemo)(()=>{
|
|
625
|
-
if (predicateOrUrl) {
|
|
626
|
-
if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
|
|
627
|
-
if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
|
|
628
|
-
}
|
|
629
|
-
return undefined;
|
|
630
|
-
// throw new Error(`No URL available for useCollection: ${predicateOrUrl}.`);
|
|
631
|
-
}, [
|
|
632
|
-
identity,
|
|
633
|
-
predicateOrUrl
|
|
634
|
-
]);
|
|
635
|
-
// Fetch page of collection item references (if pageParam provided)
|
|
636
|
-
// or default to `collectionUrl` (which should give you the first page).
|
|
637
|
-
const fetchCollection = (0, $583VT$react.useCallback)(async ({ pageParam: nextPageUrl })=>{
|
|
638
|
-
// Fetch page or first page (collectionUrl)
|
|
639
|
-
let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
|
|
640
|
-
if (json.totalItems) setTotalItems(json.totalItems);
|
|
641
|
-
// If first page, handle this here.
|
|
642
|
-
if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
|
|
643
|
-
if (json.first?.items) {
|
|
644
|
-
if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
|
|
645
|
-
({ json: json } = await dataProvider.fetch(json.first?.next));
|
|
646
|
-
else json = json.first;
|
|
647
|
-
} else // Fetch the first page
|
|
648
|
-
({ json: json } = await dataProvider.fetch(json.first));
|
|
649
|
-
}
|
|
650
|
-
return json;
|
|
651
|
-
}, [
|
|
652
|
-
dataProvider,
|
|
653
|
-
collectionUrl,
|
|
654
|
-
identity,
|
|
655
|
-
setTotalItems
|
|
656
|
-
]);
|
|
657
|
-
// Use infiniteQuery to handle pagination, fetching, etc.
|
|
658
|
-
const { data: data, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $583VT$reactquery.useInfiniteQuery)([
|
|
659
|
-
"collection",
|
|
660
|
-
{
|
|
661
|
-
collectionUrl: collectionUrl
|
|
662
|
-
}
|
|
663
|
-
], fetchCollection, {
|
|
664
|
-
enabled: !!(collectionUrl && identity?.id),
|
|
665
|
-
getNextPageParam: (lastPage)=>lastPage.next,
|
|
666
|
-
getPreviousPageParam: (firstPage)=>firstPage.prev
|
|
667
|
-
});
|
|
668
|
-
// Put all items together in a list.
|
|
669
|
-
const { loadedItems: items, isLoading: isLoadingItems, isFetching: isFetchingItems, errors: itemErrors } = $2b75a2f49c9ef165$var$useItemsFromPagesAndNotifications(data?.pages, notifications, dereferenceItems);
|
|
670
|
-
// Notifications have been processed after hook call, so reset.
|
|
671
|
-
// useEffect(() => {
|
|
672
|
-
// setNotifications([]);
|
|
673
|
-
// }, [notifications])
|
|
674
|
-
// Live Updates
|
|
675
|
-
(0, $583VT$react.useEffect)(()=>{
|
|
676
|
-
if (liveUpdates && collectionUrl) // Create ws that listens to collectionUri changes
|
|
677
|
-
(0, $583VT$semappssemanticdataprovider.getOrCreateWsChannel)(dataProvider.fetch, collectionUrl).then((webSocket)=>{
|
|
678
|
-
webSocket.addEventListener("message", (e)=>{
|
|
679
|
-
if (e.data && e.data.type === "Add" || e.data.type === "Remove") setNotifications([
|
|
680
|
-
...notifications,
|
|
681
|
-
e.data
|
|
682
|
-
]);
|
|
683
|
-
});
|
|
684
|
-
webSocket.addEventListener("error", (e)=>{
|
|
685
|
-
setHasLiveUpdates({
|
|
686
|
-
status: "error",
|
|
687
|
-
error: e
|
|
688
|
-
});
|
|
689
|
-
// TODO: Retry after a while
|
|
690
|
-
});
|
|
691
|
-
webSocket.addEventListener("close", (e)=>{
|
|
692
|
-
setHasLiveUpdates({
|
|
693
|
-
...hasLiveUpdates,
|
|
694
|
-
status: "disconnected"
|
|
695
|
-
});
|
|
696
|
-
});
|
|
697
|
-
setHasLiveUpdates({
|
|
698
|
-
status: "connected"
|
|
699
|
-
});
|
|
700
|
-
}).catch(()=>{}); // If it fails, we won't receive live updates. But that's okay.
|
|
701
|
-
}, [
|
|
702
|
-
collectionUrl,
|
|
703
|
-
liveUpdates,
|
|
704
|
-
dataProvider.fetch
|
|
705
|
-
]);
|
|
706
|
-
const allErrors = (0, $03510abb28fd3d8a$export$e57ff0f701c44363)(collectionError).concat((0, $03510abb28fd3d8a$export$e57ff0f701c44363)(itemErrors));
|
|
707
|
-
return {
|
|
708
|
-
items: items,
|
|
709
|
-
totalItems: totalItems,
|
|
710
|
-
error: allErrors.length > 0 && allErrors,
|
|
711
|
-
refetch: refetch,
|
|
712
|
-
fetchNextPage: fetchNextPage,
|
|
713
|
-
hasNextPage: hasNextPage,
|
|
714
|
-
isLoading: isLoadingPage || isLoadingItems,
|
|
715
|
-
isFetching: isFetchingPage || isFetchingItems,
|
|
716
|
-
isFetchingNextPage: isFetchingNextPage,
|
|
717
|
-
url: collectionUrl,
|
|
718
|
-
hasLiveUpdates: hasLiveUpdates
|
|
719
|
-
};
|
|
720
|
-
};
|
|
721
|
-
var $2b75a2f49c9ef165$export$2e2bcd8739ae039 = $2b75a2f49c9ef165$var$useCollection;
|
|
722
|
-
|
|
723
|
-
|
|
724
810
|
const $2e5504cc4159ca8d$var$CommentsField = ({ source: source, context: context, helperText: helperText, placeholder: placeholder, userResource: userResource, mentions: mentions })=>{
|
|
725
811
|
const record = (0, $583VT$reactadmin.useRecordContext)();
|
|
726
|
-
const { items: comments, loading: loading, addItem: addItem, removeItem: removeItem } = (0, $
|
|
812
|
+
const { items: comments, loading: loading, addItem: addItem, removeItem: removeItem } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)(record.replies);
|
|
727
813
|
if (!userResource) throw new Error("No userResource defined for CommentsField");
|
|
728
814
|
return /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsxs)((0, $583VT$reactjsxruntime.Fragment), {
|
|
729
815
|
children: [
|
|
@@ -759,7 +845,7 @@ var $2e5504cc4159ca8d$export$2e2bcd8739ae039 = $2e5504cc4159ca8d$var$CommentsFie
|
|
|
759
845
|
|
|
760
846
|
const $505d598a33288aad$var$CollectionList = ({ collectionUrl: collectionUrl, resource: resource, children: children })=>{
|
|
761
847
|
if ((0, ($parcel$interopDefault($583VT$react))).Children.count(children) !== 1) throw new Error("<CollectionList> only accepts a single child");
|
|
762
|
-
const { items: actorsUris } = (0, $
|
|
848
|
+
const { items: actorsUris } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)(collectionUrl);
|
|
763
849
|
const { data: data, isLoading: isLoading, isFetching: isFetching } = (0, $583VT$reactadmin.useGetMany)(resource, {
|
|
764
850
|
ids: Array.isArray(actorsUris) ? actorsUris : [
|
|
765
851
|
actorsUris
|
|
@@ -802,302 +888,49 @@ var $b0c94a9bdea99da5$export$2e2bcd8739ae039 = $b0c94a9bdea99da5$var$ReferenceCo
|
|
|
802
888
|
|
|
803
889
|
|
|
804
890
|
|
|
805
|
-
|
|
806
|
-
const $5ca5f7e9fc1c3544$var$useItemsFromPages = (pages, dereferenceItems)=>{
|
|
807
|
-
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
808
|
-
const items = (0, $583VT$react.useMemo)(()=>pages.flatMap((p)=>(0, $03510abb28fd3d8a$export$e57ff0f701c44363)(p.orderedItems || p.items)), [
|
|
809
|
-
pages
|
|
810
|
-
]);
|
|
811
|
-
// We will force dereference, if some items are not URI string references.
|
|
812
|
-
const shouldDereference = (0, $583VT$react.useMemo)(()=>{
|
|
813
|
-
return dereferenceItems || items.some((item)=>typeof item !== "string");
|
|
814
|
-
}, [
|
|
815
|
-
dereferenceItems,
|
|
816
|
-
items
|
|
817
|
-
]);
|
|
818
|
-
// Dereference all items, if necessary (even if shouldDereference is false, the hook needs to be called).
|
|
819
|
-
const itemQueries = (0, $583VT$reactquery.useQueries)(!shouldDereference ? [] : items.filter((item)=>typeof item === "string").map((itemUri)=>({
|
|
820
|
-
queryKey: [
|
|
821
|
-
"resource",
|
|
822
|
-
itemUri
|
|
823
|
-
],
|
|
824
|
-
queryFn: async ()=>(await dataProvider.fetch(itemUri)).json,
|
|
825
|
-
staleTime: Infinity
|
|
826
|
-
})));
|
|
827
|
-
if (!shouldDereference) return {
|
|
828
|
-
loadedItems: items,
|
|
829
|
-
isLoading: false,
|
|
830
|
-
isFetching: false
|
|
831
|
-
};
|
|
832
|
-
// Put all loaded items together (might be dereferenced already, so concatenate).
|
|
833
|
-
const loadedItems = items.filter((item)=>typeof item !== "string").concat(itemQueries.flatMap((itemQuery)=>{
|
|
834
|
-
return itemQuery.isSuccess && itemQuery.data || [];
|
|
835
|
-
}));
|
|
836
|
-
const errors = itemQueries.filter((q)=>q.error);
|
|
837
|
-
return {
|
|
838
|
-
loadedItems: loadedItems,
|
|
839
|
-
isLoading: itemQueries.some((q)=>q.isLoading),
|
|
840
|
-
isFetching: itemQueries.some((q)=>q.isFetching),
|
|
841
|
-
errors: errors.length > 0 ? errors : undefined
|
|
842
|
-
};
|
|
843
|
-
};
|
|
844
891
|
/**
|
|
845
|
-
*
|
|
846
|
-
*
|
|
892
|
+
* Hook to fetch the inbox of the logged user.
|
|
893
|
+
* Returns the same data as the useCollection hooks, plus:
|
|
894
|
+
* - `awaitActivity`: a function to wait for a certain activity to be received
|
|
895
|
+
* - `owner`: the WebID of the inbox's owner
|
|
896
|
+
* See https://semapps.org/docs/frontend/activitypub-components#useinbox for usage
|
|
847
897
|
* @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
|
|
848
|
-
*/ const $
|
|
849
|
-
const { dereferenceItems: dereferenceItems = false, liveUpdates: liveUpdates = true } = options;
|
|
898
|
+
*/ const $486f741c94cd8f74$var$useInbox = (options = {})=>{
|
|
850
899
|
const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
|
|
851
|
-
const
|
|
852
|
-
const
|
|
853
|
-
const [hasLiveUpdates, setHasLiveUpdates] = (0, $583VT$react.useState)({
|
|
854
|
-
status: "connecting"
|
|
855
|
-
});
|
|
856
|
-
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
857
|
-
// Get collectionUrl from webId predicate or URL.
|
|
858
|
-
const collectionUrl = (0, $583VT$react.useMemo)(()=>{
|
|
859
|
-
if (predicateOrUrl) {
|
|
860
|
-
if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
|
|
861
|
-
if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
|
|
862
|
-
}
|
|
863
|
-
return undefined;
|
|
864
|
-
// throw new Error(`No URL available for useCollection: ${predicateOrUrl}.`);
|
|
865
|
-
}, [
|
|
866
|
-
identity,
|
|
867
|
-
predicateOrUrl
|
|
868
|
-
]);
|
|
869
|
-
// Fetch page of collection item references (if pageParam provided)
|
|
870
|
-
// or default to `collectionUrl` (which should give you the first page).
|
|
871
|
-
const fetchCollection = (0, $583VT$react.useCallback)(async ({ pageParam: nextPageUrl })=>{
|
|
872
|
-
// Fetch page or first page (collectionUrl)
|
|
873
|
-
let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
|
|
874
|
-
if (json.totalItems) setTotalItems(json.totalItems);
|
|
875
|
-
// If first page, handle this here.
|
|
876
|
-
if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
|
|
877
|
-
if (json.first?.items) {
|
|
878
|
-
if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
|
|
879
|
-
({ json: json } = await dataProvider.fetch(json.first?.next));
|
|
880
|
-
else json = json.first;
|
|
881
|
-
} else // Fetch the first page
|
|
882
|
-
({ json: json } = await dataProvider.fetch(json.first));
|
|
883
|
-
}
|
|
884
|
-
return json;
|
|
885
|
-
}, [
|
|
886
|
-
dataProvider,
|
|
887
|
-
collectionUrl,
|
|
888
|
-
identity,
|
|
889
|
-
setTotalItems
|
|
890
|
-
]);
|
|
891
|
-
// Use infiniteQuery to handle pagination, fetching, etc.
|
|
892
|
-
const { data: pageData, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $583VT$reactquery.useInfiniteQuery)([
|
|
893
|
-
"collection",
|
|
894
|
-
{
|
|
895
|
-
collectionUrl: collectionUrl
|
|
896
|
-
}
|
|
897
|
-
], fetchCollection, {
|
|
898
|
-
enabled: !!(collectionUrl && identity?.id),
|
|
899
|
-
getNextPageParam: (lastPage)=>lastPage.next,
|
|
900
|
-
getPreviousPageParam: (firstPage)=>firstPage.prev
|
|
901
|
-
});
|
|
902
|
-
// Put all items together in a list (and dereference, if required).
|
|
903
|
-
const { loadedItems: items, isLoading: isLoadingItems, isFetching: isFetchingItems, errors: itemErrors } = $5ca5f7e9fc1c3544$var$useItemsFromPages(pageData?.pages ?? [], dereferenceItems);
|
|
904
|
-
const allErrors = (0, $03510abb28fd3d8a$export$e57ff0f701c44363)(collectionError).concat((0, $03510abb28fd3d8a$export$e57ff0f701c44363)(itemErrors));
|
|
905
|
-
const addItem = (0, $583VT$react.useCallback)((item, shouldRefetch = true)=>{
|
|
906
|
-
queryClient.setQueryData([
|
|
907
|
-
"collection",
|
|
908
|
-
{
|
|
909
|
-
collectionUrl: collectionUrl
|
|
910
|
-
}
|
|
911
|
-
], (oldData)=>{
|
|
912
|
-
if (!oldData) return oldData;
|
|
913
|
-
setTotalItems(totalItems && totalItems + 1);
|
|
914
|
-
// Destructure, so react knows, it needs to re-render the pages.
|
|
915
|
-
const pages = [
|
|
916
|
-
...oldData.pages
|
|
917
|
-
];
|
|
918
|
-
const firstPageItems = pages?.[0]?.orderedItems || pages?.[0]?.items || [];
|
|
919
|
-
firstPageItems.unshift(item);
|
|
920
|
-
oldData.pages = pages;
|
|
921
|
-
return oldData;
|
|
922
|
-
});
|
|
923
|
-
if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
|
|
924
|
-
"collection",
|
|
925
|
-
{
|
|
926
|
-
collectionUrl: collectionUrl
|
|
927
|
-
}
|
|
928
|
-
], {
|
|
929
|
-
active: true,
|
|
930
|
-
exact: true
|
|
931
|
-
}), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
|
|
932
|
-
}, [
|
|
933
|
-
queryClient,
|
|
934
|
-
collectionUrl
|
|
935
|
-
]);
|
|
936
|
-
const removeItem = (0, $583VT$react.useCallback)((item, shouldRefetch = true)=>{
|
|
937
|
-
queryClient.setQueryData([
|
|
938
|
-
"collection",
|
|
939
|
-
{
|
|
940
|
-
collectionUrl: collectionUrl
|
|
941
|
-
}
|
|
942
|
-
], (oldData)=>{
|
|
943
|
-
if (!oldData) return oldData;
|
|
944
|
-
setTotalItems(totalItems && totalItems - 1);
|
|
945
|
-
// Destructure, so react knows, it needs to re-render the pages array.
|
|
946
|
-
const pages = [
|
|
947
|
-
...oldData.pages
|
|
948
|
-
];
|
|
949
|
-
// Find the item in all pages and remove the item to be removed (either item.id or just item)
|
|
950
|
-
pages.forEach((page)=>{
|
|
951
|
-
if (page.orderedItems) page.orderedItems = page.orderedItems.filter((i)=>(i.id || i) !== (item.id || item));
|
|
952
|
-
else if (page.items) page.items = page.items.filter((i)=>(i.id || i) !== (item?.id || item));
|
|
953
|
-
});
|
|
954
|
-
oldData.pages = pages;
|
|
955
|
-
return oldData;
|
|
956
|
-
});
|
|
957
|
-
if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
|
|
958
|
-
"collection",
|
|
959
|
-
{
|
|
960
|
-
collectionUrl: collectionUrl
|
|
961
|
-
}
|
|
962
|
-
], {
|
|
963
|
-
active: true,
|
|
964
|
-
exact: true
|
|
965
|
-
}), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
|
|
966
|
-
}, [
|
|
967
|
-
queryClient,
|
|
968
|
-
collectionUrl
|
|
969
|
-
]);
|
|
970
|
-
// Live Updates
|
|
971
|
-
(0, $583VT$react.useEffect)(()=>{
|
|
972
|
-
if (liveUpdates && collectionUrl) // Create ws that listens to collectionUri changes
|
|
973
|
-
(0, $583VT$semappssemanticdataprovider.getOrCreateWsChannel)(dataProvider.fetch, collectionUrl).then((webSocket)=>{
|
|
974
|
-
webSocket.addEventListener("message", (e)=>{
|
|
975
|
-
const data = JSON.parse(e.data);
|
|
976
|
-
if (data && data.type === "Add") addItem(data.object, true);
|
|
977
|
-
else if (data && data.type === "Remove") removeItem(data.object, true);
|
|
978
|
-
});
|
|
979
|
-
webSocket.addEventListener("error", (e)=>{
|
|
980
|
-
setHasLiveUpdates({
|
|
981
|
-
status: "error",
|
|
982
|
-
error: e
|
|
983
|
-
});
|
|
984
|
-
// TODO: Retry after a while
|
|
985
|
-
});
|
|
986
|
-
webSocket.addEventListener("close", (e)=>{
|
|
987
|
-
if (!hasLiveUpdates.error) setHasLiveUpdates({
|
|
988
|
-
...hasLiveUpdates,
|
|
989
|
-
status: "closed"
|
|
990
|
-
});
|
|
991
|
-
});
|
|
992
|
-
setHasLiveUpdates({
|
|
993
|
-
status: "connected"
|
|
994
|
-
});
|
|
995
|
-
}).catch(()=>{}); // If it fails, we won't receive live updates. But that's okay.
|
|
996
|
-
}, [
|
|
997
|
-
collectionUrl,
|
|
998
|
-
liveUpdates,
|
|
999
|
-
dataProvider
|
|
1000
|
-
]);
|
|
900
|
+
const { items: items, url: url, hasLiveUpdates: hasLiveUpdates, ...rest } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)("inbox", options);
|
|
901
|
+
const awaitActivity = (0, $5e70f9d0635e25dd$export$2e2bcd8739ae039)(hasLiveUpdates.webSocket);
|
|
1001
902
|
return {
|
|
1002
903
|
items: items,
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
removeItem: removeItem,
|
|
1009
|
-
hasNextPage: hasNextPage,
|
|
1010
|
-
isLoading: isLoadingPage || isLoadingItems,
|
|
1011
|
-
isFetching: isFetchingPage || isFetchingItems,
|
|
1012
|
-
isFetchingNextPage: isFetchingNextPage,
|
|
1013
|
-
url: collectionUrl,
|
|
1014
|
-
hasLiveUpdates: hasLiveUpdates
|
|
904
|
+
url: url,
|
|
905
|
+
hasLiveUpdates: hasLiveUpdates,
|
|
906
|
+
awaitActivity: awaitActivity,
|
|
907
|
+
owner: identity?.id,
|
|
908
|
+
...rest
|
|
1015
909
|
};
|
|
1016
910
|
};
|
|
1017
|
-
var $
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
const $97664763db3c0a46$var$useInbox = ()=>{
|
|
1024
|
-
const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
|
|
1025
|
-
const inboxUrl = (0, $583VT$react.useMemo)(()=>{
|
|
1026
|
-
if (identity?.webIdData) return identity?.webIdData?.inbox;
|
|
1027
|
-
}, [
|
|
1028
|
-
identity
|
|
1029
|
-
]);
|
|
1030
|
-
const sparqlEndpoint = (0, $583VT$react.useMemo)(()=>{
|
|
1031
|
-
if (identity?.webIdData) return identity?.webIdData?.endpoints?.["void:sparqlEndpoint"] || `${identity?.id}/sparql`;
|
|
1032
|
-
}, [
|
|
1033
|
-
identity
|
|
1034
|
-
]);
|
|
1035
|
-
const fetch = (0, $583VT$react.useCallback)(async ({ filters: filters })=>{
|
|
1036
|
-
if (!sparqlEndpoint || !inboxUrl) return;
|
|
1037
|
-
const token = localStorage.getItem("token");
|
|
1038
|
-
const blankNodesQuery = (0, $583VT$semappssemanticdataprovider.buildBlankNodesQuery)([
|
|
1039
|
-
"as:object"
|
|
1040
|
-
]);
|
|
1041
|
-
let filtersWhereQuery = "";
|
|
1042
|
-
if (filters) Object.keys(filters).forEach((predicate)=>{
|
|
1043
|
-
if (filters[predicate]) {
|
|
1044
|
-
const object = filters[predicate].startsWith("http") ? `<${filters[predicate]}>` : filters[predicate];
|
|
1045
|
-
filtersWhereQuery += `?s1 ${predicate} ${object} .`;
|
|
1046
|
-
}
|
|
1047
|
-
});
|
|
1048
|
-
const query = `
|
|
1049
|
-
PREFIX as: <https://www.w3.org/ns/activitystreams#>
|
|
1050
|
-
CONSTRUCT {
|
|
1051
|
-
?s1 ?p1 ?o1 .
|
|
1052
|
-
${blankNodesQuery.construct}
|
|
1053
|
-
}
|
|
1054
|
-
WHERE {
|
|
1055
|
-
<${inboxUrl}> as:items ?s1 .
|
|
1056
|
-
?s1 ?p1 ?o1 .
|
|
1057
|
-
FILTER( (isIRI(?s1)) ) .
|
|
1058
|
-
${filtersWhereQuery}
|
|
1059
|
-
${blankNodesQuery.where}
|
|
1060
|
-
}
|
|
1061
|
-
`;
|
|
1062
|
-
const { json: json } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(sparqlEndpoint, {
|
|
1063
|
-
method: "POST",
|
|
1064
|
-
body: query,
|
|
1065
|
-
headers: new Headers({
|
|
1066
|
-
Accept: "application/ld+json",
|
|
1067
|
-
Authorization: token ? `Bearer ${token}` : undefined
|
|
1068
|
-
})
|
|
1069
|
-
});
|
|
1070
|
-
if (json["@graph"]) return json["@graph"];
|
|
1071
|
-
return null;
|
|
1072
|
-
}, [
|
|
1073
|
-
sparqlEndpoint,
|
|
1074
|
-
inboxUrl
|
|
1075
|
-
]);
|
|
1076
|
-
return {
|
|
1077
|
-
fetch: fetch,
|
|
1078
|
-
url: inboxUrl,
|
|
1079
|
-
owner: identity?.id
|
|
1080
|
-
};
|
|
1081
|
-
};
|
|
1082
|
-
var $97664763db3c0a46$export$2e2bcd8739ae039 = $97664763db3c0a46$var$useInbox;
|
|
911
|
+
var $486f741c94cd8f74$export$2e2bcd8739ae039 = $486f741c94cd8f74$var$useInbox;
|
|
1083
912
|
|
|
1084
913
|
|
|
1085
914
|
|
|
1086
915
|
|
|
1087
|
-
const $
|
|
916
|
+
const $59fc2d2cba62bd8e$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora.software/ns/schema/2.1")=>{
|
|
1088
917
|
const [schema, setSchema] = (0, $583VT$react.useState)();
|
|
1089
918
|
(0, $583VT$react.useEffect)(()=>{
|
|
1090
919
|
(async ()=>{
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
920
|
+
if (host && rel) {
|
|
921
|
+
const protocol = host.includes(":") ? "http" : "https"; // If the host has a port, we are likely on HTTP
|
|
922
|
+
const nodeinfoUrl = `${protocol}://${host}/.well-known/nodeinfo`;
|
|
923
|
+
try {
|
|
924
|
+
const { json: links } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(nodeinfoUrl);
|
|
925
|
+
// Accept any version of the nodeinfo protocol
|
|
926
|
+
const link = links?.links?.find((l)=>l.rel === rel);
|
|
927
|
+
if (link) {
|
|
928
|
+
const { json: json } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(link.href);
|
|
929
|
+
setSchema(json);
|
|
930
|
+
}
|
|
931
|
+
} catch (e) {
|
|
932
|
+
// Do nothing if nodeinfo can't be fetched
|
|
933
|
+
}
|
|
1101
934
|
}
|
|
1102
935
|
})();
|
|
1103
936
|
}, [
|
|
@@ -1107,7 +940,7 @@ const $30fd77858150739b$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora
|
|
|
1107
940
|
]);
|
|
1108
941
|
return schema;
|
|
1109
942
|
};
|
|
1110
|
-
var $
|
|
943
|
+
var $59fc2d2cba62bd8e$export$2e2bcd8739ae039 = $59fc2d2cba62bd8e$var$useNodeinfo;
|
|
1111
944
|
|
|
1112
945
|
|
|
1113
946
|
|