@semapps/activitypub-components 0.6.7 → 0.8.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 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", () => $97664763db3c0a46$export$2e2bcd8739ae039);
32
- $parcel$export(module.exports, "useNodeinfo", () => $30fd77858150739b$export$2e2bcd8739ae039);
33
- $parcel$export(module.exports, "useOutbox", () => $decfdd34cc00b80e$export$2e2bcd8739ae039);
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,400 @@ const $ebea823cebb2f44b$export$4d8d554031975581 = "https://www.w3.org/ns/activit
108
108
 
109
109
 
110
110
 
111
- const $decfdd34cc00b80e$var$useOutbox = ()=>{
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 outboxUrl = (0, $583VT$react.useMemo)(()=>{
114
- if (identity?.webIdData) return identity?.webIdData?.outbox;
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
+ const webSocketRef = (0, $583VT$react.useRef)(null);
190
+ // Get collectionUrl from webId predicate or URL.
191
+ const collectionUrl = (0, $583VT$react.useMemo)(()=>{
192
+ if (predicateOrUrl) {
193
+ if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
194
+ if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
195
+ }
196
+ return undefined;
197
+ // throw new Error(`No URL available for useCollection: ${predicateOrUrl}.`);
115
198
  }, [
116
- identity
199
+ identity,
200
+ predicateOrUrl
117
201
  ]);
118
- const sparqlEndpoint = (0, $583VT$react.useMemo)(()=>{
119
- if (identity?.webIdData) return identity?.webIdData?.endpoints?.["void:sparqlEndpoint"] || `${identity?.id}/sparql`;
202
+ // Fetch page of collection item references (if pageParam provided)
203
+ // or default to `collectionUrl` (which should give you the first page).
204
+ const fetchCollection = (0, $583VT$react.useCallback)(async ({ pageParam: nextPageUrl })=>{
205
+ // Fetch page or first page (collectionUrl)
206
+ let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
207
+ if (json.totalItems) setTotalItems(json.totalItems);
208
+ // If first page, handle this here.
209
+ if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
210
+ if (json.first?.items) {
211
+ if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
212
+ ({ json: json } = await dataProvider.fetch(json.first?.next));
213
+ else json = json.first;
214
+ } else // Fetch the first page
215
+ ({ json: json } = await dataProvider.fetch(json.first));
216
+ }
217
+ return json;
120
218
  }, [
121
- identity
219
+ dataProvider,
220
+ collectionUrl,
221
+ identity,
222
+ setTotalItems
122
223
  ]);
123
- // Post an activity to the logged user's outbox and return its URI
124
- const post = (0, $583VT$react.useCallback)(async (activity)=>{
125
- if (!outboxUrl) throw new Error("Cannot post to outbox before user identity is loaded. Please use the loaded argument of useOutbox");
126
- const token = localStorage.getItem("token");
127
- const { headers: headers } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(outboxUrl, {
128
- method: "POST",
129
- body: JSON.stringify({
130
- "@context": "https://www.w3.org/ns/activitystreams",
131
- ...activity
132
- }),
133
- headers: new Headers({
134
- "Content-Type": "application/ld+json",
135
- Authorization: `Bearer ${token}`
136
- })
224
+ // Use infiniteQuery to handle pagination, fetching, etc.
225
+ const { data: pageData, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $583VT$reactquery.useInfiniteQuery)([
226
+ "collection",
227
+ {
228
+ collectionUrl: collectionUrl
229
+ }
230
+ ], fetchCollection, {
231
+ enabled: !!(collectionUrl && identity?.id),
232
+ getNextPageParam: (lastPage)=>lastPage.next,
233
+ getPreviousPageParam: (firstPage)=>firstPage.prev
234
+ });
235
+ // Put all items together in a list (and dereference, if required).
236
+ const { loadedItems: items, isLoading: isLoadingItems, isFetching: isFetchingItems, errors: itemErrors } = $5ca5f7e9fc1c3544$var$useItemsFromPages(pageData?.pages ?? [], dereferenceItems);
237
+ const allErrors = (0, $03510abb28fd3d8a$export$e57ff0f701c44363)(collectionError).concat((0, $03510abb28fd3d8a$export$e57ff0f701c44363)(itemErrors));
238
+ const addItem = (0, $583VT$react.useCallback)((item, shouldRefetch = true)=>{
239
+ queryClient.setQueryData([
240
+ "collection",
241
+ {
242
+ collectionUrl: collectionUrl
243
+ }
244
+ ], (oldData)=>{
245
+ if (!oldData) return oldData;
246
+ setTotalItems(totalItems && totalItems + 1);
247
+ // Destructure, so react knows, it needs to re-render the pages.
248
+ const pages = [
249
+ ...oldData.pages
250
+ ];
251
+ const firstPageItems = pages?.[0]?.orderedItems || pages?.[0]?.items || [];
252
+ firstPageItems.unshift(item);
253
+ oldData.pages = pages;
254
+ return oldData;
137
255
  });
138
- return headers.get("Location");
256
+ if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
257
+ "collection",
258
+ {
259
+ collectionUrl: collectionUrl
260
+ }
261
+ ], {
262
+ active: true,
263
+ exact: true
264
+ }), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
139
265
  }, [
140
- outboxUrl
266
+ queryClient,
267
+ collectionUrl
141
268
  ]);
142
- const fetch = (0, $583VT$react.useCallback)(async ()=>{
143
- if (!sparqlEndpoint || !outboxUrl) return;
144
- const token = localStorage.getItem("token");
145
- const blankNodesQuery = (0, $583VT$semappssemanticdataprovider.buildBlankNodesQuery)([
146
- "as:object"
147
- ]);
148
- const query = `
149
- PREFIX as: <https://www.w3.org/ns/activitystreams#>
150
- CONSTRUCT {
151
- ?s1 ?p1 ?o1 .
152
- ${blankNodesQuery.construct}
153
- }
154
- WHERE {
155
- <${outboxUrl}> as:items ?s1 .
156
- ?s1 ?p1 ?o1 .
157
- ${blankNodesQuery.where}
158
- }
159
- `;
160
- const { json: json } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(sparqlEndpoint, {
161
- method: "POST",
162
- body: query,
163
- headers: new Headers({
164
- Accept: "application/ld+json",
165
- Authorization: token ? `Bearer ${token}` : undefined
166
- })
269
+ const removeItem = (0, $583VT$react.useCallback)((item, shouldRefetch = true)=>{
270
+ queryClient.setQueryData([
271
+ "collection",
272
+ {
273
+ collectionUrl: collectionUrl
274
+ }
275
+ ], (oldData)=>{
276
+ if (!oldData) return oldData;
277
+ setTotalItems(totalItems && totalItems - 1);
278
+ // Destructure, so react knows, it needs to re-render the pages array.
279
+ const pages = [
280
+ ...oldData.pages
281
+ ];
282
+ // Find the item in all pages and remove the item to be removed (either item.id or just item)
283
+ pages.forEach((page)=>{
284
+ if (page.orderedItems) page.orderedItems = page.orderedItems.filter((i)=>(i.id || i) !== (item.id || item));
285
+ else if (page.items) page.items = page.items.filter((i)=>(i.id || i) !== (item?.id || item));
286
+ });
287
+ oldData.pages = pages;
288
+ return oldData;
289
+ });
290
+ if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
291
+ "collection",
292
+ {
293
+ collectionUrl: collectionUrl
294
+ }
295
+ ], {
296
+ active: true,
297
+ exact: true
298
+ }), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
299
+ }, [
300
+ queryClient,
301
+ collectionUrl
302
+ ]);
303
+ // Live Updates
304
+ (0, $583VT$react.useEffect)(()=>{
305
+ if (liveUpdates && collectionUrl) // Create ws that listens to collectionUri changes
306
+ (0, $583VT$semappssemanticdataprovider.getOrCreateWsChannel)(dataProvider.fetch, collectionUrl).then((ws)=>{
307
+ webSocketRef.current = ws; // Keep a ref to the webSocket so that it can be used elsewhere
308
+ webSocketRef.current.addEventListener("message", (e)=>{
309
+ const data = JSON.parse(e.data);
310
+ if (data.type === "Add") addItem(data.object, true);
311
+ else if (data.type === "Remove") removeItem(data.object, true);
312
+ });
313
+ webSocketRef.current.addEventListener("error", (e)=>{
314
+ setHasLiveUpdates({
315
+ status: "error",
316
+ error: e
317
+ });
318
+ // TODO: Retry after a while
319
+ });
320
+ webSocketRef.current.addEventListener("close", (e)=>{
321
+ if (!hasLiveUpdates.error) setHasLiveUpdates({
322
+ ...hasLiveUpdates,
323
+ status: "closed"
324
+ });
325
+ });
326
+ setHasLiveUpdates({
327
+ status: "connected"
328
+ });
329
+ }).catch(()=>{}); // If it fails, we won't receive live updates. But that's okay.
330
+ }, [
331
+ collectionUrl,
332
+ liveUpdates,
333
+ dataProvider,
334
+ webSocketRef
335
+ ]);
336
+ const awaitWebSocketConnection = (0, $583VT$react.useCallback)((options = {})=>{
337
+ const { timeout: timeout = 30000 } = options;
338
+ return new Promise((resolve, reject)=>{
339
+ if (webSocketRef?.current) resolve(webSocketRef);
340
+ else {
341
+ const timeoutId = setTimeout(()=>{
342
+ reject(`No WebSocket connection found within ${Math.round(timeout / 1000)}s`);
343
+ }, timeout);
344
+ const intervalId = setInterval(()=>{
345
+ if (webSocketRef?.current) {
346
+ clearInterval(intervalId);
347
+ clearTimeout(timeoutId);
348
+ resolve(webSocketRef);
349
+ } else console.log("WebSocket is not initialized yet, waiting...");
350
+ }, 100);
351
+ }
167
352
  });
168
- if (json["@graph"]) return json["@graph"];
169
- return null;
170
353
  }, [
171
- sparqlEndpoint,
172
- outboxUrl
354
+ webSocketRef
173
355
  ]);
174
356
  return {
175
- post: post,
176
- fetch: fetch,
177
- url: outboxUrl,
178
- loaded: !!outboxUrl,
179
- owner: identity?.id
357
+ items: items,
358
+ totalItems: totalItems,
359
+ error: allErrors.length > 0 && allErrors,
360
+ refetch: refetch,
361
+ fetchNextPage: fetchNextPage,
362
+ addItem: addItem,
363
+ removeItem: removeItem,
364
+ hasNextPage: hasNextPage,
365
+ isLoading: isLoadingPage || isLoadingItems,
366
+ isFetching: isFetchingPage || isFetchingItems,
367
+ isFetchingNextPage: isFetchingNextPage,
368
+ url: collectionUrl,
369
+ hasLiveUpdates: hasLiveUpdates,
370
+ awaitWebSocketConnection: awaitWebSocketConnection,
371
+ webSocketRef: webSocketRef
180
372
  };
181
373
  };
182
- var $decfdd34cc00b80e$export$2e2bcd8739ae039 = $decfdd34cc00b80e$var$useOutbox;
374
+ var $5ca5f7e9fc1c3544$export$2e2bcd8739ae039 = $5ca5f7e9fc1c3544$var$useCollection;
183
375
 
184
376
 
185
377
 
186
378
 
187
- // Fix a bug in the current version of the mention extension
188
- // (The { id, label } object is located inside the id property)
189
- // See https://github.com/ueberdosis/tiptap/pull/1322
190
- const $9b1343b281972d72$var$CustomMention = (0, ($parcel$interopDefault($583VT$tiptapextensionmention))).extend({
191
- renderHTML ({ node: node, HTMLAttributes: HTMLAttributes }) {
192
- return [
193
- "span",
194
- (0, $583VT$tiptapcore.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes),
195
- `@${node.attrs.id.label}`
196
- ];
197
- },
198
- addAttributes () {
199
- return {
200
- label: {
201
- default: null,
202
- parseHTML: (element)=>{
203
- return {
204
- label: element.getAttribute("data-mention-label")
205
- };
206
- },
379
+ /**
380
+ * Hook used internally by useInbox and useOutbox. This is not exported.
381
+ * @param awaitWebSocketConnection Promise returning the WebSocket which allow to listen to the inbox or outbox
382
+ * @param existingActivities Partial list of activities already received in the inbox and outbox
383
+ */ const $5e70f9d0635e25dd$var$useAwaitActivity = (awaitWebSocketConnection, existingActivities)=>{
384
+ const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
385
+ // TODO Allow to pass an object, and automatically dereference it if required, like on the @semapps/activitypub matchActivity util
386
+ return (0, $583VT$react.useCallback)((matchActivity, options = {})=>{
387
+ const { timeout: timeout = 30000, checkExistingActivities: checkExistingActivities = false } = options;
388
+ return new Promise((resolve, reject)=>{
389
+ awaitWebSocketConnection().then((webSocketRef)=>{
390
+ const onMessage = (event)=>{
391
+ const data = JSON.parse(event.data);
392
+ if (data.type === "Add") dataProvider.fetch(data.object).then(({ json: json })=>{
393
+ if (matchActivity(json)) {
394
+ removeListeners();
395
+ return resolve(json);
396
+ }
397
+ });
398
+ };
399
+ const onError = (e)=>{
400
+ // TODO reconnect if connection closed
401
+ removeListeners();
402
+ reject(e);
403
+ };
404
+ const onClose = (e)=>{
405
+ removeListeners();
406
+ reject(new Error(`${e.reason} (Code: ${e.code})`));
407
+ };
408
+ const removeListeners = ()=>{
409
+ webSocketRef.current?.removeEventListener("message", onMessage);
410
+ webSocketRef.current?.removeEventListener("error", onError);
411
+ webSocketRef.current?.removeEventListener("close", onClose);
412
+ };
413
+ webSocketRef.current?.addEventListener("message", onMessage);
414
+ webSocketRef.current?.addEventListener("error", onError);
415
+ webSocketRef.current?.addEventListener("close", onClose);
416
+ // If a list of activities is already loaded, verify if there is a match
417
+ if (existingActivities && checkExistingActivities) for (const a of existingActivities){
418
+ if (typeof a !== "string") {
419
+ if (matchActivity(a)) {
420
+ removeListeners();
421
+ return resolve(a);
422
+ }
423
+ }
424
+ }
425
+ setTimeout(()=>{
426
+ removeListeners();
427
+ reject(new Error("Timeout"));
428
+ }, timeout);
429
+ }).catch((e)=>{
430
+ reject(e);
431
+ });
432
+ });
433
+ }, [
434
+ awaitWebSocketConnection,
435
+ existingActivities,
436
+ dataProvider
437
+ ]);
438
+ };
439
+ var $5e70f9d0635e25dd$export$2e2bcd8739ae039 = $5e70f9d0635e25dd$var$useAwaitActivity;
440
+
441
+
442
+ /**
443
+ * Hook to fetch and post to the outbox of the logged user.
444
+ * Returns the same data as the useCollection hooks, plus:
445
+ * - `post`: a function to post a new activity in the user's outbox
446
+ * - `awaitActivity`: a function to wait for a certain activity to be posted
447
+ * - `owner`: the WebID of the outbox's owner
448
+ * See https://semapps.org/docs/frontend/activitypub-components#useoutbox for usage
449
+ * @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
450
+ */ const $456aea3814dded7d$var$useOutbox = (options = {})=>{
451
+ const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
452
+ const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
453
+ const { url: url, items: items, awaitWebSocketConnection: awaitWebSocketConnection, ...rest } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)("outbox", options);
454
+ const awaitActivity = (0, $5e70f9d0635e25dd$export$2e2bcd8739ae039)(awaitWebSocketConnection, items);
455
+ // Post an activity to the logged user's outbox and return its URI
456
+ const post = (0, $583VT$react.useCallback)(async (activity)=>{
457
+ if (!url) throw new Error("Cannot post to outbox before user identity is loaded. Please use the isLoading argument of useOutbox");
458
+ const { headers: headers } = await dataProvider.fetch(url, {
459
+ method: "POST",
460
+ body: JSON.stringify({
461
+ "@context": "https://www.w3.org/ns/activitystreams",
462
+ ...activity
463
+ })
464
+ });
465
+ return headers.get("Location");
466
+ }, [
467
+ url,
468
+ dataProvider
469
+ ]);
470
+ return {
471
+ url: url,
472
+ items: items,
473
+ awaitWebSocketConnection: awaitWebSocketConnection,
474
+ post: post,
475
+ awaitActivity: awaitActivity,
476
+ owner: identity?.id,
477
+ ...rest
478
+ };
479
+ };
480
+ var $456aea3814dded7d$export$2e2bcd8739ae039 = $456aea3814dded7d$var$useOutbox;
481
+
482
+
483
+
484
+
485
+ // Fix a bug in the current version of the mention extension
486
+ // (The { id, label } object is located inside the id property)
487
+ // See https://github.com/ueberdosis/tiptap/pull/1322
488
+ const $9b1343b281972d72$var$CustomMention = (0, ($parcel$interopDefault($583VT$tiptapextensionmention))).extend({
489
+ renderHTML ({ node: node, HTMLAttributes: HTMLAttributes }) {
490
+ return [
491
+ "span",
492
+ (0, $583VT$tiptapcore.mergeAttributes)(this.options.HTMLAttributes, HTMLAttributes),
493
+ `@${node.attrs.id.label}`
494
+ ];
495
+ },
496
+ addAttributes () {
497
+ return {
498
+ label: {
499
+ default: null,
500
+ parseHTML: (element)=>{
501
+ return {
502
+ label: element.getAttribute("data-mention-label")
503
+ };
504
+ },
207
505
  renderHTML: (attributes)=>{
208
506
  if (!attributes.id.label) return {};
209
507
  return {
@@ -284,7 +582,7 @@ const $703eba3e46be7ee5$var$PostCommentForm = ({ context: context, placeholder:
284
582
  const userDataModel = (0, $583VT$semappssemanticdataprovider.useDataModel)(userResource);
285
583
  const classes = $703eba3e46be7ee5$var$useStyles();
286
584
  const notify = (0, $583VT$reactadmin.useNotify)();
287
- const outbox = (0, $decfdd34cc00b80e$export$2e2bcd8739ae039)();
585
+ const outbox = (0, $456aea3814dded7d$export$2e2bcd8739ae039)();
288
586
  const [expanded, setExpanded] = (0, $583VT$react.useState)(false);
289
587
  const [openAuth, setOpenAuth] = (0, $583VT$react.useState)(false);
290
588
  const onSubmit = (0, $583VT$react.useCallback)(async (values)=>{
@@ -544,186 +842,9 @@ var $d68cd57b2d06b6d5$export$2e2bcd8739ae039 = $d68cd57b2d06b6d5$var$CommentsLis
544
842
 
545
843
 
546
844
 
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
845
  const $2e5504cc4159ca8d$var$CommentsField = ({ source: source, context: context, helperText: helperText, placeholder: placeholder, userResource: userResource, mentions: mentions })=>{
725
846
  const record = (0, $583VT$reactadmin.useRecordContext)();
726
- const { items: comments, loading: loading, addItem: addItem, removeItem: removeItem } = (0, $2b75a2f49c9ef165$export$2e2bcd8739ae039)(record.replies);
847
+ const { items: comments, loading: loading, addItem: addItem, removeItem: removeItem } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)(record.replies);
727
848
  if (!userResource) throw new Error("No userResource defined for CommentsField");
728
849
  return /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsxs)((0, $583VT$reactjsxruntime.Fragment), {
729
850
  children: [
@@ -759,7 +880,7 @@ var $2e5504cc4159ca8d$export$2e2bcd8739ae039 = $2e5504cc4159ca8d$var$CommentsFie
759
880
 
760
881
  const $505d598a33288aad$var$CollectionList = ({ collectionUrl: collectionUrl, resource: resource, children: children })=>{
761
882
  if ((0, ($parcel$interopDefault($583VT$react))).Children.count(children) !== 1) throw new Error("<CollectionList> only accepts a single child");
762
- const { items: actorsUris } = (0, $2b75a2f49c9ef165$export$2e2bcd8739ae039)(collectionUrl);
883
+ const { items: actorsUris } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)(collectionUrl);
763
884
  const { data: data, isLoading: isLoading, isFetching: isFetching } = (0, $583VT$reactadmin.useGetMany)(resource, {
764
885
  ids: Array.isArray(actorsUris) ? actorsUris : [
765
886
  actorsUris
@@ -802,302 +923,49 @@ var $b0c94a9bdea99da5$export$2e2bcd8739ae039 = $b0c94a9bdea99da5$var$ReferenceCo
802
923
 
803
924
 
804
925
 
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
926
  /**
845
- * Subscribe a collection. Supports pagination.
846
- * @param predicateOrUrl The collection URI or the predicate to get the collection URI from the identity (webId).
927
+ * Hook to fetch the inbox of the logged user.
928
+ * Returns the same data as the useCollection hooks, plus:
929
+ * - `awaitActivity`: a function to wait for a certain activity to be received
930
+ * - `owner`: the WebID of the inbox's owner
931
+ * See https://semapps.org/docs/frontend/activitypub-components#useinbox for usage
847
932
  * @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
848
- */ const $5ca5f7e9fc1c3544$var$useCollection = (predicateOrUrl, options = {})=>{
849
- const { dereferenceItems: dereferenceItems = false, liveUpdates: liveUpdates = true } = options;
933
+ */ const $486f741c94cd8f74$var$useInbox = (options = {})=>{
850
934
  const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
851
- const [totalItems, setTotalItems] = (0, $583VT$react.useState)();
852
- const queryClient = (0, $583VT$reactquery.useQueryClient)();
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
- ]);
935
+ const { url: url, items: items, awaitWebSocketConnection: awaitWebSocketConnection, ...rest } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)("inbox", options);
936
+ const awaitActivity = (0, $5e70f9d0635e25dd$export$2e2bcd8739ae039)(awaitWebSocketConnection, items);
1001
937
  return {
938
+ url: url,
1002
939
  items: items,
1003
- totalItems: totalItems,
1004
- error: allErrors.length > 0 && allErrors,
1005
- refetch: refetch,
1006
- fetchNextPage: fetchNextPage,
1007
- addItem: addItem,
1008
- removeItem: removeItem,
1009
- hasNextPage: hasNextPage,
1010
- isLoading: isLoadingPage || isLoadingItems,
1011
- isFetching: isFetchingPage || isFetchingItems,
1012
- isFetchingNextPage: isFetchingNextPage,
1013
- url: collectionUrl,
1014
- hasLiveUpdates: hasLiveUpdates
940
+ awaitWebSocketConnection: awaitWebSocketConnection,
941
+ awaitActivity: awaitActivity,
942
+ owner: identity?.id,
943
+ ...rest
1015
944
  };
1016
945
  };
1017
- var $5ca5f7e9fc1c3544$export$2e2bcd8739ae039 = $5ca5f7e9fc1c3544$var$useCollection;
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;
946
+ var $486f741c94cd8f74$export$2e2bcd8739ae039 = $486f741c94cd8f74$var$useInbox;
1083
947
 
1084
948
 
1085
949
 
1086
950
 
1087
- const $30fd77858150739b$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora.software/ns/schema/2.1")=>{
951
+ const $59fc2d2cba62bd8e$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora.software/ns/schema/2.1")=>{
1088
952
  const [schema, setSchema] = (0, $583VT$react.useState)();
1089
953
  (0, $583VT$react.useEffect)(()=>{
1090
954
  (async ()=>{
1091
- const protocol = host.includes(":") ? "http" : "https"; // If the host has a port, we are likely on HTTP
1092
- const nodeinfoUrl = `${protocol}://${host}/.well-known/nodeinfo`;
1093
- try {
1094
- const { json: links } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(nodeinfoUrl);
1095
- // Accept any version of the nodeinfo protocol
1096
- const link = links?.links?.find((l)=>l.rel === rel);
1097
- const { json: json } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(link.href);
1098
- setSchema(json);
1099
- } catch (e) {
1100
- // Do nothing if nodeinfo can't be fetched
955
+ if (host && rel) {
956
+ const protocol = host.includes(":") ? "http" : "https"; // If the host has a port, we are likely on HTTP
957
+ const nodeinfoUrl = `${protocol}://${host}/.well-known/nodeinfo`;
958
+ try {
959
+ const { json: links } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(nodeinfoUrl);
960
+ // Accept any version of the nodeinfo protocol
961
+ const link = links?.links?.find((l)=>l.rel === rel);
962
+ if (link) {
963
+ const { json: json } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(link.href);
964
+ setSchema(json);
965
+ }
966
+ } catch (e) {
967
+ // Do nothing if nodeinfo can't be fetched
968
+ }
1101
969
  }
1102
970
  })();
1103
971
  }, [
@@ -1107,7 +975,7 @@ const $30fd77858150739b$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora
1107
975
  ]);
1108
976
  return schema;
1109
977
  };
1110
- var $30fd77858150739b$export$2e2bcd8739ae039 = $30fd77858150739b$var$useNodeinfo;
978
+ var $59fc2d2cba62bd8e$export$2e2bcd8739ae039 = $59fc2d2cba62bd8e$var$useNodeinfo;
1111
979
 
1112
980
 
1113
981