@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.es.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {jsxs as $85cNH$jsxs, Fragment as $85cNH$Fragment, jsx as $85cNH$jsx} from "react/jsx-runtime";
|
|
2
2
|
import $85cNH$react, {useState as $85cNH$useState, useCallback as $85cNH$useCallback, useMemo as $85cNH$useMemo, useEffect as $85cNH$useEffect, forwardRef as $85cNH$forwardRef, useImperativeHandle as $85cNH$useImperativeHandle} from "react";
|
|
3
|
-
import {useRecordContext as $85cNH$useRecordContext, useGetIdentity as $85cNH$useGetIdentity, useNotify as $85cNH$useNotify, Form as $85cNH$Form,
|
|
3
|
+
import {useRecordContext as $85cNH$useRecordContext, useGetIdentity as $85cNH$useGetIdentity, useNotify as $85cNH$useNotify, Form as $85cNH$Form, useDataProvider as $85cNH$useDataProvider, TextField as $85cNH$TextField, DateField as $85cNH$DateField, RichTextField as $85cNH$RichTextField, useGetMany as $85cNH$useGetMany, useList as $85cNH$useList, ListContextProvider as $85cNH$ListContextProvider, fetchUtils as $85cNH$fetchUtils, useGetList as $85cNH$useGetList} from "react-admin";
|
|
4
4
|
import {RichTextInput as $85cNH$RichTextInput, DefaultEditorOptions as $85cNH$DefaultEditorOptions} from "ra-input-rich-text";
|
|
5
5
|
import $85cNH$tiptapextensionplaceholder from "@tiptap/extension-placeholder";
|
|
6
6
|
import {Box as $85cNH$Box, Avatar as $85cNH$Avatar, Button as $85cNH$Button, Typography as $85cNH$Typography, CircularProgress as $85cNH$CircularProgress} from "@mui/material";
|
|
7
7
|
import $85cNH$muistylesmakeStyles from "@mui/styles/makeStyles";
|
|
8
8
|
import $85cNH$muiiconsmaterialSend from "@mui/icons-material/Send";
|
|
9
|
-
import {useDataModel as $85cNH$useDataModel,
|
|
9
|
+
import {useDataModel as $85cNH$useDataModel, getOrCreateWsChannel as $85cNH$getOrCreateWsChannel} from "@semapps/semantic-data-provider";
|
|
10
10
|
import {AuthDialog as $85cNH$AuthDialog} from "@semapps/auth-provider";
|
|
11
|
+
import {useQueries as $85cNH$useQueries, useQueryClient as $85cNH$useQueryClient, useInfiniteQuery as $85cNH$useInfiniteQuery} from "react-query";
|
|
11
12
|
import {mergeAttributes as $85cNH$mergeAttributes} from "@tiptap/core";
|
|
12
13
|
import $85cNH$tiptapextensionmention from "@tiptap/extension-mention";
|
|
13
14
|
import {ReferenceField as $85cNH$ReferenceField, AvatarWithLabelField as $85cNH$AvatarWithLabelField} from "@semapps/field-components";
|
|
14
|
-
import {useQueryClient as $85cNH$useQueryClient, useInfiniteQuery as $85cNH$useInfiniteQuery} from "react-query";
|
|
15
15
|
import {ReactRenderer as $85cNH$ReactRenderer} from "@tiptap/react";
|
|
16
16
|
import $85cNH$tippyjs from "tippy.js";
|
|
17
17
|
|
|
@@ -54,7 +54,7 @@ const $338f387df48a40d7$export$1ec8e53e7d982d22 = {
|
|
|
54
54
|
REMOVE: "Remove",
|
|
55
55
|
TENTATIVE_REJECT: "TentativeReject",
|
|
56
56
|
TENTATIVE_ACCEPT: "TentativeAccept",
|
|
57
|
-
|
|
57
|
+
TRAVEL: "Travel",
|
|
58
58
|
UNDO: "Undo",
|
|
59
59
|
UPDATE: "Update",
|
|
60
60
|
VIEW: "View"
|
|
@@ -86,78 +86,341 @@ const $338f387df48a40d7$export$4d8d554031975581 = "https://www.w3.org/ns/activit
|
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
const $577f4953dfa5de4f$export$e57ff0f701c44363 = (value)=>{
|
|
93
|
+
// If the field is null-ish, we suppose there are no values.
|
|
94
|
+
if (value === null || value === undefined) return [];
|
|
95
|
+
// Return as is.
|
|
96
|
+
if (Array.isArray(value)) return value;
|
|
97
|
+
// Single value is made an array.
|
|
98
|
+
return [
|
|
99
|
+
value
|
|
100
|
+
];
|
|
101
|
+
};
|
|
102
|
+
var $577f4953dfa5de4f$export$2e2bcd8739ae039 = {
|
|
103
|
+
arrayOf: $577f4953dfa5de4f$export$e57ff0f701c44363
|
|
104
|
+
};
|
|
105
|
+
const $577f4953dfa5de4f$export$34aed805e991a647 = (iterable, predicate)=>{
|
|
106
|
+
const seen = new Set();
|
|
107
|
+
return iterable.filter((item)=>{
|
|
108
|
+
const key = predicate(item);
|
|
109
|
+
if (seen.has(key)) return false;
|
|
110
|
+
seen.add(key);
|
|
111
|
+
return true;
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
const $8281f3ce3b9d6123$var$useItemsFromPages = (pages, dereferenceItems)=>{
|
|
117
|
+
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
118
|
+
const items = (0, $85cNH$useMemo)(()=>pages.flatMap((p)=>(0, $577f4953dfa5de4f$export$e57ff0f701c44363)(p.orderedItems || p.items)), [
|
|
119
|
+
pages
|
|
120
|
+
]);
|
|
121
|
+
// We will force dereference, if some items are not URI string references.
|
|
122
|
+
const shouldDereference = (0, $85cNH$useMemo)(()=>{
|
|
123
|
+
return dereferenceItems || items.some((item)=>typeof item !== "string");
|
|
124
|
+
}, [
|
|
125
|
+
dereferenceItems,
|
|
126
|
+
items
|
|
127
|
+
]);
|
|
128
|
+
// Dereference all items, if necessary (even if shouldDereference is false, the hook needs to be called).
|
|
129
|
+
const itemQueries = (0, $85cNH$useQueries)(!shouldDereference ? [] : items.filter((item)=>typeof item === "string").map((itemUri)=>({
|
|
130
|
+
queryKey: [
|
|
131
|
+
"resource",
|
|
132
|
+
itemUri
|
|
133
|
+
],
|
|
134
|
+
queryFn: async ()=>(await dataProvider.fetch(itemUri)).json,
|
|
135
|
+
staleTime: Infinity
|
|
136
|
+
})));
|
|
137
|
+
if (!shouldDereference) return {
|
|
138
|
+
loadedItems: items,
|
|
139
|
+
isLoading: false,
|
|
140
|
+
isFetching: false
|
|
141
|
+
};
|
|
142
|
+
// Put all loaded items together (might be dereferenced already, so concatenate).
|
|
143
|
+
const loadedItems = items.filter((item)=>typeof item !== "string").concat(itemQueries.flatMap((itemQuery)=>{
|
|
144
|
+
return itemQuery.isSuccess && itemQuery.data || [];
|
|
145
|
+
}));
|
|
146
|
+
const errors = itemQueries.filter((q)=>q.error);
|
|
147
|
+
return {
|
|
148
|
+
loadedItems: loadedItems,
|
|
149
|
+
isLoading: itemQueries.some((q)=>q.isLoading),
|
|
150
|
+
isFetching: itemQueries.some((q)=>q.isFetching),
|
|
151
|
+
errors: errors.length > 0 ? errors : undefined
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Subscribe a collection. Supports pagination.
|
|
156
|
+
* @param predicateOrUrl The collection URI or the predicate to get the collection URI from the identity (webId).
|
|
157
|
+
* @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
|
|
158
|
+
*/ const $8281f3ce3b9d6123$var$useCollection = (predicateOrUrl, options = {})=>{
|
|
159
|
+
const { dereferenceItems: dereferenceItems = false, liveUpdates: liveUpdates = true } = options;
|
|
90
160
|
const { data: identity } = (0, $85cNH$useGetIdentity)();
|
|
91
|
-
const
|
|
92
|
-
|
|
161
|
+
const [totalItems, setTotalItems] = (0, $85cNH$useState)();
|
|
162
|
+
const queryClient = (0, $85cNH$useQueryClient)();
|
|
163
|
+
const [hasLiveUpdates, setHasLiveUpdates] = (0, $85cNH$useState)({
|
|
164
|
+
status: "connecting"
|
|
165
|
+
});
|
|
166
|
+
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
167
|
+
// Get collectionUrl from webId predicate or URL.
|
|
168
|
+
const collectionUrl = (0, $85cNH$useMemo)(()=>{
|
|
169
|
+
if (predicateOrUrl) {
|
|
170
|
+
if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
|
|
171
|
+
if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
|
|
172
|
+
}
|
|
173
|
+
return undefined;
|
|
174
|
+
// throw new Error(`No URL available for useCollection: ${predicateOrUrl}.`);
|
|
175
|
+
}, [
|
|
176
|
+
identity,
|
|
177
|
+
predicateOrUrl
|
|
178
|
+
]);
|
|
179
|
+
// Fetch page of collection item references (if pageParam provided)
|
|
180
|
+
// or default to `collectionUrl` (which should give you the first page).
|
|
181
|
+
const fetchCollection = (0, $85cNH$useCallback)(async ({ pageParam: nextPageUrl })=>{
|
|
182
|
+
// Fetch page or first page (collectionUrl)
|
|
183
|
+
let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
|
|
184
|
+
if (json.totalItems) setTotalItems(json.totalItems);
|
|
185
|
+
// If first page, handle this here.
|
|
186
|
+
if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
|
|
187
|
+
if (json.first?.items) {
|
|
188
|
+
if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
|
|
189
|
+
({ json: json } = await dataProvider.fetch(json.first?.next));
|
|
190
|
+
else json = json.first;
|
|
191
|
+
} else // Fetch the first page
|
|
192
|
+
({ json: json } = await dataProvider.fetch(json.first));
|
|
193
|
+
}
|
|
194
|
+
return json;
|
|
195
|
+
}, [
|
|
196
|
+
dataProvider,
|
|
197
|
+
collectionUrl,
|
|
198
|
+
identity,
|
|
199
|
+
setTotalItems
|
|
200
|
+
]);
|
|
201
|
+
// Use infiniteQuery to handle pagination, fetching, etc.
|
|
202
|
+
const { data: pageData, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $85cNH$useInfiniteQuery)([
|
|
203
|
+
"collection",
|
|
204
|
+
{
|
|
205
|
+
collectionUrl: collectionUrl
|
|
206
|
+
}
|
|
207
|
+
], fetchCollection, {
|
|
208
|
+
enabled: !!(collectionUrl && identity?.id),
|
|
209
|
+
getNextPageParam: (lastPage)=>lastPage.next,
|
|
210
|
+
getPreviousPageParam: (firstPage)=>firstPage.prev
|
|
211
|
+
});
|
|
212
|
+
// Put all items together in a list (and dereference, if required).
|
|
213
|
+
const { loadedItems: items, isLoading: isLoadingItems, isFetching: isFetchingItems, errors: itemErrors } = $8281f3ce3b9d6123$var$useItemsFromPages(pageData?.pages ?? [], dereferenceItems);
|
|
214
|
+
const allErrors = (0, $577f4953dfa5de4f$export$e57ff0f701c44363)(collectionError).concat((0, $577f4953dfa5de4f$export$e57ff0f701c44363)(itemErrors));
|
|
215
|
+
const addItem = (0, $85cNH$useCallback)((item, shouldRefetch = true)=>{
|
|
216
|
+
queryClient.setQueryData([
|
|
217
|
+
"collection",
|
|
218
|
+
{
|
|
219
|
+
collectionUrl: collectionUrl
|
|
220
|
+
}
|
|
221
|
+
], (oldData)=>{
|
|
222
|
+
if (!oldData) return oldData;
|
|
223
|
+
setTotalItems(totalItems && totalItems + 1);
|
|
224
|
+
// Destructure, so react knows, it needs to re-render the pages.
|
|
225
|
+
const pages = [
|
|
226
|
+
...oldData.pages
|
|
227
|
+
];
|
|
228
|
+
const firstPageItems = pages?.[0]?.orderedItems || pages?.[0]?.items || [];
|
|
229
|
+
firstPageItems.unshift(item);
|
|
230
|
+
oldData.pages = pages;
|
|
231
|
+
return oldData;
|
|
232
|
+
});
|
|
233
|
+
if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
|
|
234
|
+
"collection",
|
|
235
|
+
{
|
|
236
|
+
collectionUrl: collectionUrl
|
|
237
|
+
}
|
|
238
|
+
], {
|
|
239
|
+
active: true,
|
|
240
|
+
exact: true
|
|
241
|
+
}), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
|
|
242
|
+
}, [
|
|
243
|
+
queryClient,
|
|
244
|
+
collectionUrl
|
|
245
|
+
]);
|
|
246
|
+
const removeItem = (0, $85cNH$useCallback)((item, shouldRefetch = true)=>{
|
|
247
|
+
queryClient.setQueryData([
|
|
248
|
+
"collection",
|
|
249
|
+
{
|
|
250
|
+
collectionUrl: collectionUrl
|
|
251
|
+
}
|
|
252
|
+
], (oldData)=>{
|
|
253
|
+
if (!oldData) return oldData;
|
|
254
|
+
setTotalItems(totalItems && totalItems - 1);
|
|
255
|
+
// Destructure, so react knows, it needs to re-render the pages array.
|
|
256
|
+
const pages = [
|
|
257
|
+
...oldData.pages
|
|
258
|
+
];
|
|
259
|
+
// Find the item in all pages and remove the item to be removed (either item.id or just item)
|
|
260
|
+
pages.forEach((page)=>{
|
|
261
|
+
if (page.orderedItems) page.orderedItems = page.orderedItems.filter((i)=>(i.id || i) !== (item.id || item));
|
|
262
|
+
else if (page.items) page.items = page.items.filter((i)=>(i.id || i) !== (item?.id || item));
|
|
263
|
+
});
|
|
264
|
+
oldData.pages = pages;
|
|
265
|
+
return oldData;
|
|
266
|
+
});
|
|
267
|
+
if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
|
|
268
|
+
"collection",
|
|
269
|
+
{
|
|
270
|
+
collectionUrl: collectionUrl
|
|
271
|
+
}
|
|
272
|
+
], {
|
|
273
|
+
active: true,
|
|
274
|
+
exact: true
|
|
275
|
+
}), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
|
|
276
|
+
}, [
|
|
277
|
+
queryClient,
|
|
278
|
+
collectionUrl
|
|
279
|
+
]);
|
|
280
|
+
// Live Updates
|
|
281
|
+
(0, $85cNH$useEffect)(()=>{
|
|
282
|
+
if (liveUpdates && collectionUrl) // Create ws that listens to collectionUri changes
|
|
283
|
+
(0, $85cNH$getOrCreateWsChannel)(dataProvider.fetch, collectionUrl).then((webSocket)=>{
|
|
284
|
+
webSocket.addEventListener("message", (e)=>{
|
|
285
|
+
const data = JSON.parse(e.data);
|
|
286
|
+
if (data.type === "Add") addItem(data.object, true);
|
|
287
|
+
else if (data.type === "Remove") removeItem(data.object, true);
|
|
288
|
+
});
|
|
289
|
+
webSocket.addEventListener("error", (e)=>{
|
|
290
|
+
setHasLiveUpdates({
|
|
291
|
+
status: "error",
|
|
292
|
+
error: e
|
|
293
|
+
});
|
|
294
|
+
// TODO: Retry after a while
|
|
295
|
+
});
|
|
296
|
+
webSocket.addEventListener("close", (e)=>{
|
|
297
|
+
if (!hasLiveUpdates.error) setHasLiveUpdates({
|
|
298
|
+
...hasLiveUpdates,
|
|
299
|
+
status: "closed"
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
setHasLiveUpdates({
|
|
303
|
+
status: "connected",
|
|
304
|
+
webSocket: webSocket
|
|
305
|
+
});
|
|
306
|
+
}).catch(()=>{}); // If it fails, we won't receive live updates. But that's okay.
|
|
93
307
|
}, [
|
|
94
|
-
|
|
308
|
+
collectionUrl,
|
|
309
|
+
liveUpdates,
|
|
310
|
+
dataProvider
|
|
95
311
|
]);
|
|
96
|
-
|
|
97
|
-
|
|
312
|
+
return {
|
|
313
|
+
items: items,
|
|
314
|
+
totalItems: totalItems,
|
|
315
|
+
error: allErrors.length > 0 && allErrors,
|
|
316
|
+
refetch: refetch,
|
|
317
|
+
fetchNextPage: fetchNextPage,
|
|
318
|
+
addItem: addItem,
|
|
319
|
+
removeItem: removeItem,
|
|
320
|
+
hasNextPage: hasNextPage,
|
|
321
|
+
isLoading: isLoadingPage || isLoadingItems,
|
|
322
|
+
isFetching: isFetchingPage || isFetchingItems,
|
|
323
|
+
isFetchingNextPage: isFetchingNextPage,
|
|
324
|
+
url: collectionUrl,
|
|
325
|
+
hasLiveUpdates: hasLiveUpdates
|
|
326
|
+
};
|
|
327
|
+
};
|
|
328
|
+
var $8281f3ce3b9d6123$export$2e2bcd8739ae039 = $8281f3ce3b9d6123$var$useCollection;
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Hook used internally by useInbox and useOutbox. This is not exported.
|
|
335
|
+
* @param webSocket WebSocket which allow to listen to the inbox or outbox
|
|
336
|
+
* @param existingActivities Partial list of activities already received in the inbox and outbox
|
|
337
|
+
*/ const $600ca419166a1ded$var$useAwaitActivity = (webSocket, existingActivities)=>{
|
|
338
|
+
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
339
|
+
// TODO Allow to pass an object, and automatically dereference it if required, like on the @semapps/activitypub matchActivity util
|
|
340
|
+
return (0, $85cNH$useCallback)((matchActivity, options = {})=>{
|
|
341
|
+
const { timeout: timeout = 30000, checkExistingActivities: checkExistingActivities = false } = options;
|
|
342
|
+
return new Promise((resolve, reject)=>{
|
|
343
|
+
if (webSocket) {
|
|
344
|
+
const onMessage = (event)=>{
|
|
345
|
+
const data = JSON.parse(event.data);
|
|
346
|
+
if (data.type === "Add") dataProvider.fetch(data.object).then(({ json: json })=>{
|
|
347
|
+
if (matchActivity(json)) {
|
|
348
|
+
webSocket.removeEventListener("message", onMessage);
|
|
349
|
+
return resolve(json);
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
};
|
|
353
|
+
webSocket.addEventListener("message", onMessage);
|
|
354
|
+
// TODO reconnect if connection closed
|
|
355
|
+
webSocket.addEventListener("error", (e)=>{
|
|
356
|
+
reject(e);
|
|
357
|
+
});
|
|
358
|
+
webSocket.addEventListener("close", (e)=>{
|
|
359
|
+
reject(new Error(`${e.reason} (Code: ${e.code})`));
|
|
360
|
+
});
|
|
361
|
+
// If a list of activities is already loaded, verify if there is a match
|
|
362
|
+
if (existingActivities && checkExistingActivities) for (const a of existingActivities){
|
|
363
|
+
if (typeof a !== "string") {
|
|
364
|
+
if (matchActivity(a)) {
|
|
365
|
+
webSocket.removeEventListener("message", onMessage);
|
|
366
|
+
return resolve(a);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
setTimeout(()=>{
|
|
371
|
+
webSocket.removeEventListener("message", onMessage);
|
|
372
|
+
reject(new Error("Timeout"));
|
|
373
|
+
}, timeout);
|
|
374
|
+
} else throw new Error("WebSocket is not initialized !");
|
|
375
|
+
});
|
|
98
376
|
}, [
|
|
99
|
-
|
|
377
|
+
webSocket,
|
|
378
|
+
existingActivities,
|
|
379
|
+
dataProvider
|
|
100
380
|
]);
|
|
381
|
+
};
|
|
382
|
+
var $600ca419166a1ded$export$2e2bcd8739ae039 = $600ca419166a1ded$var$useAwaitActivity;
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Hook to fetch and post to the outbox of the logged user.
|
|
387
|
+
* Returns the same data as the useCollection hooks, plus:
|
|
388
|
+
* - `post`: a function to post a new activity in the user's outbox
|
|
389
|
+
* - `awaitActivity`: a function to wait for a certain activity to be posted
|
|
390
|
+
* - `owner`: the WebID of the outbox's owner
|
|
391
|
+
* See https://semapps.org/docs/frontend/activitypub-components#useoutbox for usage
|
|
392
|
+
* @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
|
|
393
|
+
*/ const $4d1d40fdbcd30589$var$useOutbox = (options = {})=>{
|
|
394
|
+
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
395
|
+
const { data: identity } = (0, $85cNH$useGetIdentity)();
|
|
396
|
+
const { url: url, hasLiveUpdates: hasLiveUpdates, items: items, ...rest } = (0, $8281f3ce3b9d6123$export$2e2bcd8739ae039)("outbox", options);
|
|
397
|
+
const awaitActivity = (0, $600ca419166a1ded$export$2e2bcd8739ae039)(hasLiveUpdates.webSocket, items);
|
|
101
398
|
// Post an activity to the logged user's outbox and return its URI
|
|
102
399
|
const post = (0, $85cNH$useCallback)(async (activity)=>{
|
|
103
|
-
if (!
|
|
104
|
-
const
|
|
105
|
-
const { headers: headers } = await (0, $85cNH$fetchUtils).fetchJson(outboxUrl, {
|
|
400
|
+
if (!url) throw new Error("Cannot post to outbox before user identity is loaded. Please use the isLoading argument of useOutbox");
|
|
401
|
+
const { headers: headers } = await dataProvider.fetch(url, {
|
|
106
402
|
method: "POST",
|
|
107
403
|
body: JSON.stringify({
|
|
108
404
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
109
405
|
...activity
|
|
110
|
-
}),
|
|
111
|
-
headers: new Headers({
|
|
112
|
-
"Content-Type": "application/ld+json",
|
|
113
|
-
Authorization: `Bearer ${token}`
|
|
114
406
|
})
|
|
115
407
|
});
|
|
116
408
|
return headers.get("Location");
|
|
117
409
|
}, [
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const fetch = (0, $85cNH$useCallback)(async ()=>{
|
|
121
|
-
if (!sparqlEndpoint || !outboxUrl) return;
|
|
122
|
-
const token = localStorage.getItem("token");
|
|
123
|
-
const blankNodesQuery = (0, $85cNH$buildBlankNodesQuery)([
|
|
124
|
-
"as:object"
|
|
125
|
-
]);
|
|
126
|
-
const query = `
|
|
127
|
-
PREFIX as: <https://www.w3.org/ns/activitystreams#>
|
|
128
|
-
CONSTRUCT {
|
|
129
|
-
?s1 ?p1 ?o1 .
|
|
130
|
-
${blankNodesQuery.construct}
|
|
131
|
-
}
|
|
132
|
-
WHERE {
|
|
133
|
-
<${outboxUrl}> as:items ?s1 .
|
|
134
|
-
?s1 ?p1 ?o1 .
|
|
135
|
-
${blankNodesQuery.where}
|
|
136
|
-
}
|
|
137
|
-
`;
|
|
138
|
-
const { json: json } = await (0, $85cNH$fetchUtils).fetchJson(sparqlEndpoint, {
|
|
139
|
-
method: "POST",
|
|
140
|
-
body: query,
|
|
141
|
-
headers: new Headers({
|
|
142
|
-
Accept: "application/ld+json",
|
|
143
|
-
Authorization: token ? `Bearer ${token}` : undefined
|
|
144
|
-
})
|
|
145
|
-
});
|
|
146
|
-
if (json["@graph"]) return json["@graph"];
|
|
147
|
-
return null;
|
|
148
|
-
}, [
|
|
149
|
-
sparqlEndpoint,
|
|
150
|
-
outboxUrl
|
|
410
|
+
url,
|
|
411
|
+
dataProvider
|
|
151
412
|
]);
|
|
152
413
|
return {
|
|
414
|
+
url: url,
|
|
415
|
+
hasLiveUpdates: hasLiveUpdates,
|
|
416
|
+
items: items,
|
|
153
417
|
post: post,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
owner: identity?.id
|
|
418
|
+
awaitActivity: awaitActivity,
|
|
419
|
+
owner: identity?.id,
|
|
420
|
+
...rest
|
|
158
421
|
};
|
|
159
422
|
};
|
|
160
|
-
var $
|
|
423
|
+
var $4d1d40fdbcd30589$export$2e2bcd8739ae039 = $4d1d40fdbcd30589$var$useOutbox;
|
|
161
424
|
|
|
162
425
|
|
|
163
426
|
|
|
@@ -262,7 +525,7 @@ const $3c17312a40ebf1ed$var$PostCommentForm = ({ context: context, placeholder:
|
|
|
262
525
|
const userDataModel = (0, $85cNH$useDataModel)(userResource);
|
|
263
526
|
const classes = $3c17312a40ebf1ed$var$useStyles();
|
|
264
527
|
const notify = (0, $85cNH$useNotify)();
|
|
265
|
-
const outbox = (0, $
|
|
528
|
+
const outbox = (0, $4d1d40fdbcd30589$export$2e2bcd8739ae039)();
|
|
266
529
|
const [expanded, setExpanded] = (0, $85cNH$useState)(false);
|
|
267
530
|
const [openAuth, setOpenAuth] = (0, $85cNH$useState)(false);
|
|
268
531
|
const onSubmit = (0, $85cNH$useCallback)(async (values)=>{
|
|
@@ -522,143 +785,9 @@ var $be88b298220210d1$export$2e2bcd8739ae039 = $be88b298220210d1$var$CommentsLis
|
|
|
522
785
|
|
|
523
786
|
|
|
524
787
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
const $e4e1b14e0441184d$export$e57ff0f701c44363 = (value)=>{
|
|
528
|
-
// If the field is null-ish, we suppose there are no values.
|
|
529
|
-
if (value === null || value === undefined) return [];
|
|
530
|
-
// Return as is.
|
|
531
|
-
if (Array.isArray(value)) return value;
|
|
532
|
-
// Single value is made an array.
|
|
533
|
-
return [
|
|
534
|
-
value
|
|
535
|
-
];
|
|
536
|
-
};
|
|
537
|
-
var $e4e1b14e0441184d$export$2e2bcd8739ae039 = {
|
|
538
|
-
arrayOf: $e4e1b14e0441184d$export$e57ff0f701c44363
|
|
539
|
-
};
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
const $c1e897431d8c5742$var$useCollection = (predicateOrUrl, options = {})=>{
|
|
543
|
-
const { dereferenceItems: dereferenceItems = false } = options;
|
|
544
|
-
const { data: identity } = (0, $85cNH$useGetIdentity)();
|
|
545
|
-
const [items, setItems] = (0, $85cNH$useState)();
|
|
546
|
-
const [totalItems, setTotalItems] = (0, $85cNH$useState)();
|
|
547
|
-
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
548
|
-
const queryClient = (0, $85cNH$useQueryClient)();
|
|
549
|
-
const collectionUrl = (0, $85cNH$useMemo)(()=>{
|
|
550
|
-
if (predicateOrUrl) {
|
|
551
|
-
if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
|
|
552
|
-
if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
|
|
553
|
-
}
|
|
554
|
-
}, [
|
|
555
|
-
identity,
|
|
556
|
-
predicateOrUrl
|
|
557
|
-
]);
|
|
558
|
-
const fetchCollection = (0, $85cNH$useCallback)(async ({ pageParam: nextPageUrl })=>{
|
|
559
|
-
let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
|
|
560
|
-
if (json.totalItems) setTotalItems(json.totalItems);
|
|
561
|
-
if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
|
|
562
|
-
if (json.first?.items) {
|
|
563
|
-
if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
|
|
564
|
-
({ json: json } = await dataProvider.fetch(json.first?.next));
|
|
565
|
-
else json = json.first;
|
|
566
|
-
} else // Fetch the first page
|
|
567
|
-
({ json: json } = await dataProvider.fetch(json.first));
|
|
568
|
-
}
|
|
569
|
-
// Force dereference of items
|
|
570
|
-
if (dereferenceItems) {
|
|
571
|
-
const itemPredicate = json.items ? "items" : "orderedItems";
|
|
572
|
-
json[itemPredicate] = json[itemPredicate] && await Promise.all((0, $e4e1b14e0441184d$export$e57ff0f701c44363)(json[itemPredicate]).map(async (item)=>{
|
|
573
|
-
if (typeof item === "string") {
|
|
574
|
-
const { json: json } = await dataProvider.fetch(item);
|
|
575
|
-
return json;
|
|
576
|
-
}
|
|
577
|
-
return item;
|
|
578
|
-
}));
|
|
579
|
-
}
|
|
580
|
-
return json;
|
|
581
|
-
}, [
|
|
582
|
-
dataProvider,
|
|
583
|
-
collectionUrl,
|
|
584
|
-
identity,
|
|
585
|
-
setTotalItems
|
|
586
|
-
]);
|
|
587
|
-
const { data: data, error: error, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoading, isFetching: isFetching, isFetchingNextPage: isFetchingNextPage, status: status } = (0, $85cNH$useInfiniteQuery)([
|
|
588
|
-
"Collection",
|
|
589
|
-
{
|
|
590
|
-
collectionUrl: collectionUrl
|
|
591
|
-
}
|
|
592
|
-
], fetchCollection, {
|
|
593
|
-
enabled: !!(collectionUrl && identity?.id),
|
|
594
|
-
getNextPageParam: (lastPage)=>lastPage.next,
|
|
595
|
-
getPreviousPageParam: (firstPage)=>firstPage.prev
|
|
596
|
-
});
|
|
597
|
-
(0, $85cNH$useEffect)(()=>{
|
|
598
|
-
if (data?.pages) setItems([].concat(...data.pages.map((p)=>(0, $e4e1b14e0441184d$export$e57ff0f701c44363)(p.orderedItems || p.items))));
|
|
599
|
-
}, [
|
|
600
|
-
data,
|
|
601
|
-
setItems
|
|
602
|
-
]);
|
|
603
|
-
const addItem = (0, $85cNH$useCallback)((item)=>{
|
|
604
|
-
setItems((oldItems)=>[
|
|
605
|
-
...oldItems,
|
|
606
|
-
item
|
|
607
|
-
]);
|
|
608
|
-
// TODO use queryClient.setQueryData to update items directly in react-query cache
|
|
609
|
-
setTimeout(()=>queryClient.refetchQueries([
|
|
610
|
-
"Collection",
|
|
611
|
-
{
|
|
612
|
-
collectionUrl: collectionUrl
|
|
613
|
-
}
|
|
614
|
-
], {
|
|
615
|
-
active: true,
|
|
616
|
-
exact: true
|
|
617
|
-
}), 2000);
|
|
618
|
-
}, [
|
|
619
|
-
setItems,
|
|
620
|
-
queryClient,
|
|
621
|
-
collectionUrl
|
|
622
|
-
]);
|
|
623
|
-
const removeItem = (0, $85cNH$useCallback)((itemId)=>{
|
|
624
|
-
setItems((oldItems)=>oldItems.filter((item)=>typeof item === "string" ? item !== itemId : item.id !== itemId));
|
|
625
|
-
// TODO use queryClient.setQueryData to update items directly in react-query cache
|
|
626
|
-
setTimeout(()=>queryClient.refetchQueries([
|
|
627
|
-
"Collection",
|
|
628
|
-
{
|
|
629
|
-
collectionUrl: collectionUrl
|
|
630
|
-
}
|
|
631
|
-
], {
|
|
632
|
-
active: true,
|
|
633
|
-
exact: true
|
|
634
|
-
}), 2000);
|
|
635
|
-
}, [
|
|
636
|
-
setItems,
|
|
637
|
-
queryClient,
|
|
638
|
-
collectionUrl
|
|
639
|
-
]);
|
|
640
|
-
return {
|
|
641
|
-
items: items,
|
|
642
|
-
totalItems: totalItems,
|
|
643
|
-
error: error,
|
|
644
|
-
refetch: refetch,
|
|
645
|
-
fetchNextPage: fetchNextPage,
|
|
646
|
-
hasNextPage: hasNextPage,
|
|
647
|
-
isLoading: isLoading,
|
|
648
|
-
isFetching: isFetching,
|
|
649
|
-
isFetchingNextPage: isFetchingNextPage,
|
|
650
|
-
status: status,
|
|
651
|
-
addItem: addItem,
|
|
652
|
-
removeItem: removeItem,
|
|
653
|
-
url: collectionUrl
|
|
654
|
-
};
|
|
655
|
-
};
|
|
656
|
-
var $c1e897431d8c5742$export$2e2bcd8739ae039 = $c1e897431d8c5742$var$useCollection;
|
|
657
|
-
|
|
658
|
-
|
|
659
788
|
const $7ce737d4a1c88e63$var$CommentsField = ({ source: source, context: context, helperText: helperText, placeholder: placeholder, userResource: userResource, mentions: mentions })=>{
|
|
660
789
|
const record = (0, $85cNH$useRecordContext)();
|
|
661
|
-
const { items: comments, loading: loading, addItem: addItem, removeItem: removeItem } = (0, $
|
|
790
|
+
const { items: comments, loading: loading, addItem: addItem, removeItem: removeItem } = (0, $8281f3ce3b9d6123$export$2e2bcd8739ae039)(record.replies);
|
|
662
791
|
if (!userResource) throw new Error("No userResource defined for CommentsField");
|
|
663
792
|
return /*#__PURE__*/ (0, $85cNH$jsxs)((0, $85cNH$Fragment), {
|
|
664
793
|
children: [
|
|
@@ -694,7 +823,7 @@ var $7ce737d4a1c88e63$export$2e2bcd8739ae039 = $7ce737d4a1c88e63$var$CommentsFie
|
|
|
694
823
|
|
|
695
824
|
const $d3be168cd1e7aaae$var$CollectionList = ({ collectionUrl: collectionUrl, resource: resource, children: children })=>{
|
|
696
825
|
if ((0, $85cNH$react).Children.count(children) !== 1) throw new Error("<CollectionList> only accepts a single child");
|
|
697
|
-
const { items: actorsUris } = (0, $
|
|
826
|
+
const { items: actorsUris } = (0, $8281f3ce3b9d6123$export$2e2bcd8739ae039)(collectionUrl);
|
|
698
827
|
const { data: data, isLoading: isLoading, isFetching: isFetching } = (0, $85cNH$useGetMany)(resource, {
|
|
699
828
|
ids: Array.isArray(actorsUris) ? actorsUris : [
|
|
700
829
|
actorsUris
|
|
@@ -737,84 +866,49 @@ var $ea214512ab1a2e8f$export$2e2bcd8739ae039 = $ea214512ab1a2e8f$var$ReferenceCo
|
|
|
737
866
|
|
|
738
867
|
|
|
739
868
|
|
|
740
|
-
|
|
869
|
+
/**
|
|
870
|
+
* Hook to fetch the inbox of the logged user.
|
|
871
|
+
* Returns the same data as the useCollection hooks, plus:
|
|
872
|
+
* - `awaitActivity`: a function to wait for a certain activity to be received
|
|
873
|
+
* - `owner`: the WebID of the inbox's owner
|
|
874
|
+
* See https://semapps.org/docs/frontend/activitypub-components#useinbox for usage
|
|
875
|
+
* @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
|
|
876
|
+
*/ const $cc1d1cd0e97c63a2$var$useInbox = (options = {})=>{
|
|
741
877
|
const { data: identity } = (0, $85cNH$useGetIdentity)();
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
}, [
|
|
745
|
-
identity
|
|
746
|
-
]);
|
|
747
|
-
const sparqlEndpoint = (0, $85cNH$useMemo)(()=>{
|
|
748
|
-
if (identity?.webIdData) return identity?.webIdData?.endpoints?.["void:sparqlEndpoint"] || `${identity?.id}/sparql`;
|
|
749
|
-
}, [
|
|
750
|
-
identity
|
|
751
|
-
]);
|
|
752
|
-
const fetch = (0, $85cNH$useCallback)(async ({ filters: filters })=>{
|
|
753
|
-
if (!sparqlEndpoint || !inboxUrl) return;
|
|
754
|
-
const token = localStorage.getItem("token");
|
|
755
|
-
const blankNodesQuery = (0, $85cNH$buildBlankNodesQuery)([
|
|
756
|
-
"as:object"
|
|
757
|
-
]);
|
|
758
|
-
let filtersWhereQuery = "";
|
|
759
|
-
if (filters) Object.keys(filters).forEach((predicate)=>{
|
|
760
|
-
if (filters[predicate]) {
|
|
761
|
-
const object = filters[predicate].startsWith("http") ? `<${filters[predicate]}>` : filters[predicate];
|
|
762
|
-
filtersWhereQuery += `?s1 ${predicate} ${object} .`;
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
const query = `
|
|
766
|
-
PREFIX as: <https://www.w3.org/ns/activitystreams#>
|
|
767
|
-
CONSTRUCT {
|
|
768
|
-
?s1 ?p1 ?o1 .
|
|
769
|
-
${blankNodesQuery.construct}
|
|
770
|
-
}
|
|
771
|
-
WHERE {
|
|
772
|
-
<${inboxUrl}> as:items ?s1 .
|
|
773
|
-
?s1 ?p1 ?o1 .
|
|
774
|
-
FILTER( (isIRI(?s1)) ) .
|
|
775
|
-
${filtersWhereQuery}
|
|
776
|
-
${blankNodesQuery.where}
|
|
777
|
-
}
|
|
778
|
-
`;
|
|
779
|
-
const { json: json } = await (0, $85cNH$fetchUtils).fetchJson(sparqlEndpoint, {
|
|
780
|
-
method: "POST",
|
|
781
|
-
body: query,
|
|
782
|
-
headers: new Headers({
|
|
783
|
-
Accept: "application/ld+json",
|
|
784
|
-
Authorization: token ? `Bearer ${token}` : undefined
|
|
785
|
-
})
|
|
786
|
-
});
|
|
787
|
-
if (json["@graph"]) return json["@graph"];
|
|
788
|
-
return null;
|
|
789
|
-
}, [
|
|
790
|
-
sparqlEndpoint,
|
|
791
|
-
inboxUrl
|
|
792
|
-
]);
|
|
878
|
+
const { items: items, url: url, hasLiveUpdates: hasLiveUpdates, ...rest } = (0, $8281f3ce3b9d6123$export$2e2bcd8739ae039)("inbox", options);
|
|
879
|
+
const awaitActivity = (0, $600ca419166a1ded$export$2e2bcd8739ae039)(hasLiveUpdates.webSocket);
|
|
793
880
|
return {
|
|
794
|
-
|
|
795
|
-
url:
|
|
796
|
-
|
|
881
|
+
items: items,
|
|
882
|
+
url: url,
|
|
883
|
+
hasLiveUpdates: hasLiveUpdates,
|
|
884
|
+
awaitActivity: awaitActivity,
|
|
885
|
+
owner: identity?.id,
|
|
886
|
+
...rest
|
|
797
887
|
};
|
|
798
888
|
};
|
|
799
|
-
var $
|
|
889
|
+
var $cc1d1cd0e97c63a2$export$2e2bcd8739ae039 = $cc1d1cd0e97c63a2$var$useInbox;
|
|
800
890
|
|
|
801
891
|
|
|
802
892
|
|
|
803
893
|
|
|
804
|
-
const $
|
|
894
|
+
const $6a227ddc2fd92a7a$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora.software/ns/schema/2.1")=>{
|
|
805
895
|
const [schema, setSchema] = (0, $85cNH$useState)();
|
|
806
896
|
(0, $85cNH$useEffect)(()=>{
|
|
807
897
|
(async ()=>{
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
898
|
+
if (host && rel) {
|
|
899
|
+
const protocol = host.includes(":") ? "http" : "https"; // If the host has a port, we are likely on HTTP
|
|
900
|
+
const nodeinfoUrl = `${protocol}://${host}/.well-known/nodeinfo`;
|
|
901
|
+
try {
|
|
902
|
+
const { json: links } = await (0, $85cNH$fetchUtils).fetchJson(nodeinfoUrl);
|
|
903
|
+
// Accept any version of the nodeinfo protocol
|
|
904
|
+
const link = links?.links?.find((l)=>l.rel === rel);
|
|
905
|
+
if (link) {
|
|
906
|
+
const { json: json } = await (0, $85cNH$fetchUtils).fetchJson(link.href);
|
|
907
|
+
setSchema(json);
|
|
908
|
+
}
|
|
909
|
+
} catch (e) {
|
|
910
|
+
// Do nothing if nodeinfo can't be fetched
|
|
911
|
+
}
|
|
818
912
|
}
|
|
819
913
|
})();
|
|
820
914
|
}, [
|
|
@@ -824,7 +918,7 @@ const $641e93142bcf5435$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora
|
|
|
824
918
|
]);
|
|
825
919
|
return schema;
|
|
826
920
|
};
|
|
827
|
-
var $
|
|
921
|
+
var $6a227ddc2fd92a7a$export$2e2bcd8739ae039 = $6a227ddc2fd92a7a$var$useNodeinfo;
|
|
828
922
|
|
|
829
923
|
|
|
830
924
|
|
|
@@ -1018,5 +1112,5 @@ var $51cccd331ea8b13d$export$2e2bcd8739ae039 = $51cccd331ea8b13d$var$useMentions
|
|
|
1018
1112
|
|
|
1019
1113
|
|
|
1020
1114
|
|
|
1021
|
-
export {$7ce737d4a1c88e63$export$2e2bcd8739ae039 as CommentsField, $d3be168cd1e7aaae$export$2e2bcd8739ae039 as CollectionList, $ea214512ab1a2e8f$export$2e2bcd8739ae039 as ReferenceCollectionField, $
|
|
1115
|
+
export {$7ce737d4a1c88e63$export$2e2bcd8739ae039 as CommentsField, $d3be168cd1e7aaae$export$2e2bcd8739ae039 as CollectionList, $ea214512ab1a2e8f$export$2e2bcd8739ae039 as ReferenceCollectionField, $8281f3ce3b9d6123$export$2e2bcd8739ae039 as useCollection, $cc1d1cd0e97c63a2$export$2e2bcd8739ae039 as useInbox, $6a227ddc2fd92a7a$export$2e2bcd8739ae039 as useNodeinfo, $4d1d40fdbcd30589$export$2e2bcd8739ae039 as useOutbox, $2514c63dc8f4867c$export$2e2bcd8739ae039 as useWebfinger, $51cccd331ea8b13d$export$2e2bcd8739ae039 as useMentions, $338f387df48a40d7$export$1ec8e53e7d982d22 as ACTIVITY_TYPES, $338f387df48a40d7$export$9649665d7ccb0dc2 as ACTOR_TYPES, $338f387df48a40d7$export$c49cfb2681596b20 as OBJECT_TYPES, $338f387df48a40d7$export$4d8d554031975581 as PUBLIC_URI};
|
|
1022
1116
|
//# sourceMappingURL=index.es.js.map
|