@semapps/activitypub-components 0.6.6 → 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 +357 -263
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +224 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +356 -262
- 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
|
|
|
@@ -27,10 +27,10 @@ function $parcel$interopDefault(a) {
|
|
|
27
27
|
$parcel$export(module.exports, "CommentsField", () => $2e5504cc4159ca8d$export$2e2bcd8739ae039);
|
|
28
28
|
$parcel$export(module.exports, "CollectionList", () => $505d598a33288aad$export$2e2bcd8739ae039);
|
|
29
29
|
$parcel$export(module.exports, "ReferenceCollectionField", () => $b0c94a9bdea99da5$export$2e2bcd8739ae039);
|
|
30
|
-
$parcel$export(module.exports, "useCollection", () => $
|
|
31
|
-
$parcel$export(module.exports, "useInbox", () => $
|
|
32
|
-
$parcel$export(module.exports, "useNodeinfo", () => $
|
|
33
|
-
$parcel$export(module.exports, "useOutbox", () => $
|
|
30
|
+
$parcel$export(module.exports, "useCollection", () => $5ca5f7e9fc1c3544$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);
|
|
@@ -76,7 +76,7 @@ const $ebea823cebb2f44b$export$1ec8e53e7d982d22 = {
|
|
|
76
76
|
REMOVE: "Remove",
|
|
77
77
|
TENTATIVE_REJECT: "TentativeReject",
|
|
78
78
|
TENTATIVE_ACCEPT: "TentativeAccept",
|
|
79
|
-
|
|
79
|
+
TRAVEL: "Travel",
|
|
80
80
|
UNDO: "Undo",
|
|
81
81
|
UPDATE: "Update",
|
|
82
82
|
VIEW: "View"
|
|
@@ -108,78 +108,341 @@ 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}.`);
|
|
197
|
+
}, [
|
|
198
|
+
identity,
|
|
199
|
+
predicateOrUrl
|
|
200
|
+
]);
|
|
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;
|
|
115
217
|
}, [
|
|
116
|
-
|
|
218
|
+
dataProvider,
|
|
219
|
+
collectionUrl,
|
|
220
|
+
identity,
|
|
221
|
+
setTotalItems
|
|
117
222
|
]);
|
|
118
|
-
|
|
119
|
-
|
|
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;
|
|
254
|
+
});
|
|
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);
|
|
264
|
+
}, [
|
|
265
|
+
queryClient,
|
|
266
|
+
collectionUrl
|
|
267
|
+
]);
|
|
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;
|
|
288
|
+
});
|
|
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.
|
|
329
|
+
}, [
|
|
330
|
+
collectionUrl,
|
|
331
|
+
liveUpdates,
|
|
332
|
+
dataProvider
|
|
333
|
+
]);
|
|
334
|
+
return {
|
|
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
|
|
348
|
+
};
|
|
349
|
+
};
|
|
350
|
+
var $5ca5f7e9fc1c3544$export$2e2bcd8739ae039 = $5ca5f7e9fc1c3544$var$useCollection;
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
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
|
+
});
|
|
120
398
|
}, [
|
|
121
|
-
|
|
399
|
+
webSocket,
|
|
400
|
+
existingActivities,
|
|
401
|
+
dataProvider
|
|
122
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);
|
|
123
420
|
// Post an activity to the logged user's outbox and return its URI
|
|
124
421
|
const post = (0, $583VT$react.useCallback)(async (activity)=>{
|
|
125
|
-
if (!
|
|
126
|
-
const
|
|
127
|
-
const { headers: headers } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(outboxUrl, {
|
|
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, {
|
|
128
424
|
method: "POST",
|
|
129
425
|
body: JSON.stringify({
|
|
130
426
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
131
427
|
...activity
|
|
132
|
-
}),
|
|
133
|
-
headers: new Headers({
|
|
134
|
-
"Content-Type": "application/ld+json",
|
|
135
|
-
Authorization: `Bearer ${token}`
|
|
136
428
|
})
|
|
137
429
|
});
|
|
138
430
|
return headers.get("Location");
|
|
139
431
|
}, [
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
})
|
|
167
|
-
});
|
|
168
|
-
if (json["@graph"]) return json["@graph"];
|
|
169
|
-
return null;
|
|
170
|
-
}, [
|
|
171
|
-
sparqlEndpoint,
|
|
172
|
-
outboxUrl
|
|
432
|
+
url,
|
|
433
|
+
dataProvider
|
|
173
434
|
]);
|
|
174
435
|
return {
|
|
436
|
+
url: url,
|
|
437
|
+
hasLiveUpdates: hasLiveUpdates,
|
|
438
|
+
items: items,
|
|
175
439
|
post: post,
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
owner: identity?.id
|
|
440
|
+
awaitActivity: awaitActivity,
|
|
441
|
+
owner: identity?.id,
|
|
442
|
+
...rest
|
|
180
443
|
};
|
|
181
444
|
};
|
|
182
|
-
var $
|
|
445
|
+
var $456aea3814dded7d$export$2e2bcd8739ae039 = $456aea3814dded7d$var$useOutbox;
|
|
183
446
|
|
|
184
447
|
|
|
185
448
|
|
|
@@ -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,143 +807,9 @@ var $d68cd57b2d06b6d5$export$2e2bcd8739ae039 = $d68cd57b2d06b6d5$var$CommentsLis
|
|
|
544
807
|
|
|
545
808
|
|
|
546
809
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const $3ff23aa25753c478$export$e57ff0f701c44363 = (value)=>{
|
|
550
|
-
// If the field is null-ish, we suppose there are no values.
|
|
551
|
-
if (value === null || value === undefined) return [];
|
|
552
|
-
// Return as is.
|
|
553
|
-
if (Array.isArray(value)) return value;
|
|
554
|
-
// Single value is made an array.
|
|
555
|
-
return [
|
|
556
|
-
value
|
|
557
|
-
];
|
|
558
|
-
};
|
|
559
|
-
var $3ff23aa25753c478$export$2e2bcd8739ae039 = {
|
|
560
|
-
arrayOf: $3ff23aa25753c478$export$e57ff0f701c44363
|
|
561
|
-
};
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
const $2b75a2f49c9ef165$var$useCollection = (predicateOrUrl, options = {})=>{
|
|
565
|
-
const { dereferenceItems: dereferenceItems = false } = options;
|
|
566
|
-
const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
|
|
567
|
-
const [items, setItems] = (0, $583VT$react.useState)();
|
|
568
|
-
const [totalItems, setTotalItems] = (0, $583VT$react.useState)();
|
|
569
|
-
const dataProvider = (0, $583VT$reactadmin.useDataProvider)();
|
|
570
|
-
const queryClient = (0, $583VT$reactquery.useQueryClient)();
|
|
571
|
-
const collectionUrl = (0, $583VT$react.useMemo)(()=>{
|
|
572
|
-
if (predicateOrUrl) {
|
|
573
|
-
if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
|
|
574
|
-
if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
|
|
575
|
-
}
|
|
576
|
-
}, [
|
|
577
|
-
identity,
|
|
578
|
-
predicateOrUrl
|
|
579
|
-
]);
|
|
580
|
-
const fetchCollection = (0, $583VT$react.useCallback)(async ({ pageParam: nextPageUrl })=>{
|
|
581
|
-
let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
|
|
582
|
-
if (json.totalItems) setTotalItems(json.totalItems);
|
|
583
|
-
if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
|
|
584
|
-
if (json.first?.items) {
|
|
585
|
-
if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
|
|
586
|
-
({ json: json } = await dataProvider.fetch(json.first?.next));
|
|
587
|
-
else json = json.first;
|
|
588
|
-
} else // Fetch the first page
|
|
589
|
-
({ json: json } = await dataProvider.fetch(json.first));
|
|
590
|
-
}
|
|
591
|
-
// Force dereference of items
|
|
592
|
-
if (dereferenceItems) {
|
|
593
|
-
const itemPredicate = json.items ? "items" : "orderedItems";
|
|
594
|
-
json[itemPredicate] = json[itemPredicate] && await Promise.all((0, $3ff23aa25753c478$export$e57ff0f701c44363)(json[itemPredicate]).map(async (item)=>{
|
|
595
|
-
if (typeof item === "string") {
|
|
596
|
-
const { json: json } = await dataProvider.fetch(item);
|
|
597
|
-
return json;
|
|
598
|
-
}
|
|
599
|
-
return item;
|
|
600
|
-
}));
|
|
601
|
-
}
|
|
602
|
-
return json;
|
|
603
|
-
}, [
|
|
604
|
-
dataProvider,
|
|
605
|
-
collectionUrl,
|
|
606
|
-
identity,
|
|
607
|
-
setTotalItems
|
|
608
|
-
]);
|
|
609
|
-
const { data: data, error: error, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoading, isFetching: isFetching, isFetchingNextPage: isFetchingNextPage, status: status } = (0, $583VT$reactquery.useInfiniteQuery)([
|
|
610
|
-
"Collection",
|
|
611
|
-
{
|
|
612
|
-
collectionUrl: collectionUrl
|
|
613
|
-
}
|
|
614
|
-
], fetchCollection, {
|
|
615
|
-
enabled: !!(collectionUrl && identity?.id),
|
|
616
|
-
getNextPageParam: (lastPage)=>lastPage.next,
|
|
617
|
-
getPreviousPageParam: (firstPage)=>firstPage.prev
|
|
618
|
-
});
|
|
619
|
-
(0, $583VT$react.useEffect)(()=>{
|
|
620
|
-
if (data?.pages) setItems([].concat(...data.pages.map((p)=>(0, $3ff23aa25753c478$export$e57ff0f701c44363)(p.orderedItems || p.items))));
|
|
621
|
-
}, [
|
|
622
|
-
data,
|
|
623
|
-
setItems
|
|
624
|
-
]);
|
|
625
|
-
const addItem = (0, $583VT$react.useCallback)((item)=>{
|
|
626
|
-
setItems((oldItems)=>[
|
|
627
|
-
...oldItems,
|
|
628
|
-
item
|
|
629
|
-
]);
|
|
630
|
-
// TODO use queryClient.setQueryData to update items directly in react-query cache
|
|
631
|
-
setTimeout(()=>queryClient.refetchQueries([
|
|
632
|
-
"Collection",
|
|
633
|
-
{
|
|
634
|
-
collectionUrl: collectionUrl
|
|
635
|
-
}
|
|
636
|
-
], {
|
|
637
|
-
active: true,
|
|
638
|
-
exact: true
|
|
639
|
-
}), 2000);
|
|
640
|
-
}, [
|
|
641
|
-
setItems,
|
|
642
|
-
queryClient,
|
|
643
|
-
collectionUrl
|
|
644
|
-
]);
|
|
645
|
-
const removeItem = (0, $583VT$react.useCallback)((itemId)=>{
|
|
646
|
-
setItems((oldItems)=>oldItems.filter((item)=>typeof item === "string" ? item !== itemId : item.id !== itemId));
|
|
647
|
-
// TODO use queryClient.setQueryData to update items directly in react-query cache
|
|
648
|
-
setTimeout(()=>queryClient.refetchQueries([
|
|
649
|
-
"Collection",
|
|
650
|
-
{
|
|
651
|
-
collectionUrl: collectionUrl
|
|
652
|
-
}
|
|
653
|
-
], {
|
|
654
|
-
active: true,
|
|
655
|
-
exact: true
|
|
656
|
-
}), 2000);
|
|
657
|
-
}, [
|
|
658
|
-
setItems,
|
|
659
|
-
queryClient,
|
|
660
|
-
collectionUrl
|
|
661
|
-
]);
|
|
662
|
-
return {
|
|
663
|
-
items: items,
|
|
664
|
-
totalItems: totalItems,
|
|
665
|
-
error: error,
|
|
666
|
-
refetch: refetch,
|
|
667
|
-
fetchNextPage: fetchNextPage,
|
|
668
|
-
hasNextPage: hasNextPage,
|
|
669
|
-
isLoading: isLoading,
|
|
670
|
-
isFetching: isFetching,
|
|
671
|
-
isFetchingNextPage: isFetchingNextPage,
|
|
672
|
-
status: status,
|
|
673
|
-
addItem: addItem,
|
|
674
|
-
removeItem: removeItem,
|
|
675
|
-
url: collectionUrl
|
|
676
|
-
};
|
|
677
|
-
};
|
|
678
|
-
var $2b75a2f49c9ef165$export$2e2bcd8739ae039 = $2b75a2f49c9ef165$var$useCollection;
|
|
679
|
-
|
|
680
|
-
|
|
681
810
|
const $2e5504cc4159ca8d$var$CommentsField = ({ source: source, context: context, helperText: helperText, placeholder: placeholder, userResource: userResource, mentions: mentions })=>{
|
|
682
811
|
const record = (0, $583VT$reactadmin.useRecordContext)();
|
|
683
|
-
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);
|
|
684
813
|
if (!userResource) throw new Error("No userResource defined for CommentsField");
|
|
685
814
|
return /*#__PURE__*/ (0, $583VT$reactjsxruntime.jsxs)((0, $583VT$reactjsxruntime.Fragment), {
|
|
686
815
|
children: [
|
|
@@ -716,7 +845,7 @@ var $2e5504cc4159ca8d$export$2e2bcd8739ae039 = $2e5504cc4159ca8d$var$CommentsFie
|
|
|
716
845
|
|
|
717
846
|
const $505d598a33288aad$var$CollectionList = ({ collectionUrl: collectionUrl, resource: resource, children: children })=>{
|
|
718
847
|
if ((0, ($parcel$interopDefault($583VT$react))).Children.count(children) !== 1) throw new Error("<CollectionList> only accepts a single child");
|
|
719
|
-
const { items: actorsUris } = (0, $
|
|
848
|
+
const { items: actorsUris } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)(collectionUrl);
|
|
720
849
|
const { data: data, isLoading: isLoading, isFetching: isFetching } = (0, $583VT$reactadmin.useGetMany)(resource, {
|
|
721
850
|
ids: Array.isArray(actorsUris) ? actorsUris : [
|
|
722
851
|
actorsUris
|
|
@@ -759,84 +888,49 @@ var $b0c94a9bdea99da5$export$2e2bcd8739ae039 = $b0c94a9bdea99da5$var$ReferenceCo
|
|
|
759
888
|
|
|
760
889
|
|
|
761
890
|
|
|
762
|
-
|
|
891
|
+
/**
|
|
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
|
|
897
|
+
* @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
|
|
898
|
+
*/ const $486f741c94cd8f74$var$useInbox = (options = {})=>{
|
|
763
899
|
const { data: identity } = (0, $583VT$reactadmin.useGetIdentity)();
|
|
764
|
-
const
|
|
765
|
-
|
|
766
|
-
}, [
|
|
767
|
-
identity
|
|
768
|
-
]);
|
|
769
|
-
const sparqlEndpoint = (0, $583VT$react.useMemo)(()=>{
|
|
770
|
-
if (identity?.webIdData) return identity?.webIdData?.endpoints?.["void:sparqlEndpoint"] || `${identity?.id}/sparql`;
|
|
771
|
-
}, [
|
|
772
|
-
identity
|
|
773
|
-
]);
|
|
774
|
-
const fetch = (0, $583VT$react.useCallback)(async ({ filters: filters })=>{
|
|
775
|
-
if (!sparqlEndpoint || !inboxUrl) return;
|
|
776
|
-
const token = localStorage.getItem("token");
|
|
777
|
-
const blankNodesQuery = (0, $583VT$semappssemanticdataprovider.buildBlankNodesQuery)([
|
|
778
|
-
"as:object"
|
|
779
|
-
]);
|
|
780
|
-
let filtersWhereQuery = "";
|
|
781
|
-
if (filters) Object.keys(filters).forEach((predicate)=>{
|
|
782
|
-
if (filters[predicate]) {
|
|
783
|
-
const object = filters[predicate].startsWith("http") ? `<${filters[predicate]}>` : filters[predicate];
|
|
784
|
-
filtersWhereQuery += `?s1 ${predicate} ${object} .`;
|
|
785
|
-
}
|
|
786
|
-
});
|
|
787
|
-
const query = `
|
|
788
|
-
PREFIX as: <https://www.w3.org/ns/activitystreams#>
|
|
789
|
-
CONSTRUCT {
|
|
790
|
-
?s1 ?p1 ?o1 .
|
|
791
|
-
${blankNodesQuery.construct}
|
|
792
|
-
}
|
|
793
|
-
WHERE {
|
|
794
|
-
<${inboxUrl}> as:items ?s1 .
|
|
795
|
-
?s1 ?p1 ?o1 .
|
|
796
|
-
FILTER( (isIRI(?s1)) ) .
|
|
797
|
-
${filtersWhereQuery}
|
|
798
|
-
${blankNodesQuery.where}
|
|
799
|
-
}
|
|
800
|
-
`;
|
|
801
|
-
const { json: json } = await (0, $583VT$reactadmin.fetchUtils).fetchJson(sparqlEndpoint, {
|
|
802
|
-
method: "POST",
|
|
803
|
-
body: query,
|
|
804
|
-
headers: new Headers({
|
|
805
|
-
Accept: "application/ld+json",
|
|
806
|
-
Authorization: token ? `Bearer ${token}` : undefined
|
|
807
|
-
})
|
|
808
|
-
});
|
|
809
|
-
if (json["@graph"]) return json["@graph"];
|
|
810
|
-
return null;
|
|
811
|
-
}, [
|
|
812
|
-
sparqlEndpoint,
|
|
813
|
-
inboxUrl
|
|
814
|
-
]);
|
|
900
|
+
const { items: items, url: url, hasLiveUpdates: hasLiveUpdates, ...rest } = (0, $5ca5f7e9fc1c3544$export$2e2bcd8739ae039)("inbox", options);
|
|
901
|
+
const awaitActivity = (0, $5e70f9d0635e25dd$export$2e2bcd8739ae039)(hasLiveUpdates.webSocket);
|
|
815
902
|
return {
|
|
816
|
-
|
|
817
|
-
url:
|
|
818
|
-
|
|
903
|
+
items: items,
|
|
904
|
+
url: url,
|
|
905
|
+
hasLiveUpdates: hasLiveUpdates,
|
|
906
|
+
awaitActivity: awaitActivity,
|
|
907
|
+
owner: identity?.id,
|
|
908
|
+
...rest
|
|
819
909
|
};
|
|
820
910
|
};
|
|
821
|
-
var $
|
|
911
|
+
var $486f741c94cd8f74$export$2e2bcd8739ae039 = $486f741c94cd8f74$var$useInbox;
|
|
822
912
|
|
|
823
913
|
|
|
824
914
|
|
|
825
915
|
|
|
826
|
-
const $
|
|
916
|
+
const $59fc2d2cba62bd8e$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora.software/ns/schema/2.1")=>{
|
|
827
917
|
const [schema, setSchema] = (0, $583VT$react.useState)();
|
|
828
918
|
(0, $583VT$react.useEffect)(()=>{
|
|
829
919
|
(async ()=>{
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
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
|
+
}
|
|
840
934
|
}
|
|
841
935
|
})();
|
|
842
936
|
}, [
|
|
@@ -846,7 +940,7 @@ const $30fd77858150739b$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora
|
|
|
846
940
|
]);
|
|
847
941
|
return schema;
|
|
848
942
|
};
|
|
849
|
-
var $
|
|
943
|
+
var $59fc2d2cba62bd8e$export$2e2bcd8739ae039 = $59fc2d2cba62bd8e$var$useNodeinfo;
|
|
850
944
|
|
|
851
945
|
|
|
852
946
|
|