@semapps/activitypub-components 0.6.7 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs.js +378 -545
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +203 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.es.js +380 -547
- package/dist/index.es.js.map +1 -1
- package/package.json +5 -5
package/dist/index.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 {useQueries as $85cNH$useQueries, useInfiniteQuery as $85cNH$useInfiniteQuery, useQueryClient as $85cNH$useQueryClient} from "react-query";
|
|
15
15
|
import {ReactRenderer as $85cNH$ReactRenderer} from "@tiptap/react";
|
|
16
16
|
import $85cNH$tippyjs from "tippy.js";
|
|
17
17
|
|
|
@@ -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}.`);
|
|
93
175
|
}, [
|
|
94
|
-
identity
|
|
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.
|
|
307
|
+
}, [
|
|
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)=>{
|
|
@@ -491,217 +754,40 @@ const $be88b298220210d1$var$CommentsList = ({ comments: comments, userResource:
|
|
|
491
754
|
variant: "body2",
|
|
492
755
|
source: "published",
|
|
493
756
|
showTime: true
|
|
494
|
-
})
|
|
495
|
-
]
|
|
496
|
-
}),
|
|
497
|
-
/*#__PURE__*/ (0, $85cNH$jsx)((0, $85cNH$RichTextField), {
|
|
498
|
-
record: comment,
|
|
499
|
-
variant: "body1",
|
|
500
|
-
source: "content",
|
|
501
|
-
className: classes.content
|
|
502
|
-
})
|
|
503
|
-
]
|
|
504
|
-
})
|
|
505
|
-
]
|
|
506
|
-
}, comment.id)),
|
|
507
|
-
loading && /*#__PURE__*/ (0, $85cNH$jsx)((0, $85cNH$Box), {
|
|
508
|
-
minHeight: 200,
|
|
509
|
-
children: /*#__PURE__*/ (0, $85cNH$jsx)((0, $85cNH$Box), {
|
|
510
|
-
alignItems: "center",
|
|
511
|
-
className: classes.loading,
|
|
512
|
-
children: /*#__PURE__*/ (0, $85cNH$jsx)((0, $85cNH$CircularProgress), {
|
|
513
|
-
size: 60,
|
|
514
|
-
thickness: 6
|
|
515
|
-
})
|
|
516
|
-
})
|
|
517
|
-
})
|
|
518
|
-
]
|
|
519
|
-
});
|
|
520
|
-
};
|
|
521
|
-
var $be88b298220210d1$export$2e2bcd8739ae039 = $be88b298220210d1$var$CommentsList;
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
const $577f4953dfa5de4f$export$e57ff0f701c44363 = (value)=>{
|
|
529
|
-
// If the field is null-ish, we suppose there are no values.
|
|
530
|
-
if (value === null || value === undefined) return [];
|
|
531
|
-
// Return as is.
|
|
532
|
-
if (Array.isArray(value)) return value;
|
|
533
|
-
// Single value is made an array.
|
|
534
|
-
return [
|
|
535
|
-
value
|
|
536
|
-
];
|
|
537
|
-
};
|
|
538
|
-
var $577f4953dfa5de4f$export$2e2bcd8739ae039 = {
|
|
539
|
-
arrayOf: $577f4953dfa5de4f$export$e57ff0f701c44363
|
|
540
|
-
};
|
|
541
|
-
const $577f4953dfa5de4f$export$34aed805e991a647 = (iterable, predicate)=>{
|
|
542
|
-
const seen = new Set();
|
|
543
|
-
return iterable.filter((item)=>{
|
|
544
|
-
const key = predicate(item);
|
|
545
|
-
if (seen.has(key)) return false;
|
|
546
|
-
seen.add(key);
|
|
547
|
-
return true;
|
|
548
|
-
});
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
const $c1e897431d8c5742$var$useItemsFromPagesAndNotifications = (pages, notifications, dereferenceItems)=>{
|
|
553
|
-
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
554
|
-
// Add all items from pages and process notifications (possibly new and deleted items).
|
|
555
|
-
const items = (0, $85cNH$useMemo)(()=>{
|
|
556
|
-
const addItems = notifications.map((n)=>n.type === "Add").map((n)=>n.object);
|
|
557
|
-
const removeItems = notifications.map((n)=>n.type === "Remove").map((n)=>n.object.id || n.object);
|
|
558
|
-
const currentItems = !pages ? [] : pages.flatMap((p)=>(0, $577f4953dfa5de4f$export$e57ff0f701c44363)(p.orderedItems || p.items));
|
|
559
|
-
const currentAndNew = currentItems.concat(addItems);
|
|
560
|
-
return currentAndNew// Filter out removed items.
|
|
561
|
-
.filter((item)=>!removeItems.some((r)=>(r.id ?? r) === (item.id ?? item)))// Filter duplicates.
|
|
562
|
-
.filter((item)=>currentAndNew.some((i2)=>(i2.id ?? i2) === (item.id ?? item)));
|
|
563
|
-
}, pages, notifications);
|
|
564
|
-
if (!dereferenceItems) return {
|
|
565
|
-
loadedItems: items,
|
|
566
|
-
isLoading: false,
|
|
567
|
-
isFetching: false
|
|
568
|
-
};
|
|
569
|
-
// Dereference all items, if they are not yet.
|
|
570
|
-
const itemQueries = (0, $85cNH$useQueries)(items.filter((item)=>typeof item === "string").map((itemUri)=>({
|
|
571
|
-
queryKey: [
|
|
572
|
-
"resource",
|
|
573
|
-
itemUri
|
|
574
|
-
],
|
|
575
|
-
queryFn: async ()=>(await dataProvider.fetch(itemUri)).json,
|
|
576
|
-
staleTime: Infinity
|
|
577
|
-
})));
|
|
578
|
-
// Put all loaded items together (might be dereferenced already, so concatenate).
|
|
579
|
-
const loadedItems = items.filter((item)=>typeof item !== "string").concat(itemQueries.flatMap((itemQuery)=>{
|
|
580
|
-
return itemQuery.isSuccess && itemQuery.data || [];
|
|
581
|
-
}));
|
|
582
|
-
console.log("loadedItems", loadedItems.length, "total", items.length);
|
|
583
|
-
const errors = itemQueries.filter((q)=>q.error);
|
|
584
|
-
return {
|
|
585
|
-
loadedItems: loadedItems,
|
|
586
|
-
isLoading: itemQueries.some((q)=>q.isLoading),
|
|
587
|
-
isFetching: itemQueries.some((q)=>q.isFetching),
|
|
588
|
-
errors: errors.length > 0 && errors
|
|
589
|
-
};
|
|
590
|
-
};
|
|
591
|
-
const $c1e897431d8c5742$var$useCollection = (predicateOrUrl, options = {})=>{
|
|
592
|
-
const { dereferenceItems: dereferenceItems = false, liveUpdates: liveUpdates = true } = options;
|
|
593
|
-
const { data: identity } = (0, $85cNH$useGetIdentity)();
|
|
594
|
-
const [totalItems, setTotalItems] = (0, $85cNH$useState)();
|
|
595
|
-
const [notifications, setNotifications] = (0, $85cNH$useState)([]);
|
|
596
|
-
const [hasLiveUpdates, setHasLiveUpdates] = (0, $85cNH$useState)({
|
|
597
|
-
status: "disconnected",
|
|
598
|
-
error: undefined
|
|
599
|
-
});
|
|
600
|
-
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
601
|
-
// Get collectionUrl from webId predicate or URL.
|
|
602
|
-
const collectionUrl = (0, $85cNH$useMemo)(()=>{
|
|
603
|
-
if (predicateOrUrl) {
|
|
604
|
-
if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
|
|
605
|
-
if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
|
|
606
|
-
}
|
|
607
|
-
return undefined;
|
|
608
|
-
// throw new Error(`No URL available for useCollection: ${predicateOrUrl}.`);
|
|
609
|
-
}, [
|
|
610
|
-
identity,
|
|
611
|
-
predicateOrUrl
|
|
612
|
-
]);
|
|
613
|
-
// Fetch page of collection item references (if pageParam provided)
|
|
614
|
-
// or default to `collectionUrl` (which should give you the first page).
|
|
615
|
-
const fetchCollection = (0, $85cNH$useCallback)(async ({ pageParam: nextPageUrl })=>{
|
|
616
|
-
// Fetch page or first page (collectionUrl)
|
|
617
|
-
let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
|
|
618
|
-
if (json.totalItems) setTotalItems(json.totalItems);
|
|
619
|
-
// If first page, handle this here.
|
|
620
|
-
if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
|
|
621
|
-
if (json.first?.items) {
|
|
622
|
-
if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
|
|
623
|
-
({ json: json } = await dataProvider.fetch(json.first?.next));
|
|
624
|
-
else json = json.first;
|
|
625
|
-
} else // Fetch the first page
|
|
626
|
-
({ json: json } = await dataProvider.fetch(json.first));
|
|
627
|
-
}
|
|
628
|
-
return json;
|
|
629
|
-
}, [
|
|
630
|
-
dataProvider,
|
|
631
|
-
collectionUrl,
|
|
632
|
-
identity,
|
|
633
|
-
setTotalItems
|
|
634
|
-
]);
|
|
635
|
-
// Use infiniteQuery to handle pagination, fetching, etc.
|
|
636
|
-
const { data: data, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $85cNH$useInfiniteQuery)([
|
|
637
|
-
"collection",
|
|
638
|
-
{
|
|
639
|
-
collectionUrl: collectionUrl
|
|
640
|
-
}
|
|
641
|
-
], fetchCollection, {
|
|
642
|
-
enabled: !!(collectionUrl && identity?.id),
|
|
643
|
-
getNextPageParam: (lastPage)=>lastPage.next,
|
|
644
|
-
getPreviousPageParam: (firstPage)=>firstPage.prev
|
|
645
|
-
});
|
|
646
|
-
// Put all items together in a list.
|
|
647
|
-
const { loadedItems: items, isLoading: isLoadingItems, isFetching: isFetchingItems, errors: itemErrors } = $c1e897431d8c5742$var$useItemsFromPagesAndNotifications(data?.pages, notifications, dereferenceItems);
|
|
648
|
-
// Notifications have been processed after hook call, so reset.
|
|
649
|
-
// useEffect(() => {
|
|
650
|
-
// setNotifications([]);
|
|
651
|
-
// }, [notifications])
|
|
652
|
-
// Live Updates
|
|
653
|
-
(0, $85cNH$useEffect)(()=>{
|
|
654
|
-
if (liveUpdates && collectionUrl) // Create ws that listens to collectionUri changes
|
|
655
|
-
(0, $85cNH$getOrCreateWsChannel)(dataProvider.fetch, collectionUrl).then((webSocket)=>{
|
|
656
|
-
webSocket.addEventListener("message", (e)=>{
|
|
657
|
-
if (e.data && e.data.type === "Add" || e.data.type === "Remove") setNotifications([
|
|
658
|
-
...notifications,
|
|
659
|
-
e.data
|
|
660
|
-
]);
|
|
661
|
-
});
|
|
662
|
-
webSocket.addEventListener("error", (e)=>{
|
|
663
|
-
setHasLiveUpdates({
|
|
664
|
-
status: "error",
|
|
665
|
-
error: e
|
|
666
|
-
});
|
|
667
|
-
// TODO: Retry after a while
|
|
668
|
-
});
|
|
669
|
-
webSocket.addEventListener("close", (e)=>{
|
|
670
|
-
setHasLiveUpdates({
|
|
671
|
-
...hasLiveUpdates,
|
|
672
|
-
status: "disconnected"
|
|
673
|
-
});
|
|
674
|
-
});
|
|
675
|
-
setHasLiveUpdates({
|
|
676
|
-
status: "connected"
|
|
677
|
-
});
|
|
678
|
-
}).catch(()=>{}); // If it fails, we won't receive live updates. But that's okay.
|
|
679
|
-
}, [
|
|
680
|
-
collectionUrl,
|
|
681
|
-
liveUpdates,
|
|
682
|
-
dataProvider.fetch
|
|
683
|
-
]);
|
|
684
|
-
const allErrors = (0, $577f4953dfa5de4f$export$e57ff0f701c44363)(collectionError).concat((0, $577f4953dfa5de4f$export$e57ff0f701c44363)(itemErrors));
|
|
685
|
-
return {
|
|
686
|
-
items: items,
|
|
687
|
-
totalItems: totalItems,
|
|
688
|
-
error: allErrors.length > 0 && allErrors,
|
|
689
|
-
refetch: refetch,
|
|
690
|
-
fetchNextPage: fetchNextPage,
|
|
691
|
-
hasNextPage: hasNextPage,
|
|
692
|
-
isLoading: isLoadingPage || isLoadingItems,
|
|
693
|
-
isFetching: isFetchingPage || isFetchingItems,
|
|
694
|
-
isFetchingNextPage: isFetchingNextPage,
|
|
695
|
-
url: collectionUrl,
|
|
696
|
-
hasLiveUpdates: hasLiveUpdates
|
|
697
|
-
};
|
|
757
|
+
})
|
|
758
|
+
]
|
|
759
|
+
}),
|
|
760
|
+
/*#__PURE__*/ (0, $85cNH$jsx)((0, $85cNH$RichTextField), {
|
|
761
|
+
record: comment,
|
|
762
|
+
variant: "body1",
|
|
763
|
+
source: "content",
|
|
764
|
+
className: classes.content
|
|
765
|
+
})
|
|
766
|
+
]
|
|
767
|
+
})
|
|
768
|
+
]
|
|
769
|
+
}, comment.id)),
|
|
770
|
+
loading && /*#__PURE__*/ (0, $85cNH$jsx)((0, $85cNH$Box), {
|
|
771
|
+
minHeight: 200,
|
|
772
|
+
children: /*#__PURE__*/ (0, $85cNH$jsx)((0, $85cNH$Box), {
|
|
773
|
+
alignItems: "center",
|
|
774
|
+
className: classes.loading,
|
|
775
|
+
children: /*#__PURE__*/ (0, $85cNH$jsx)((0, $85cNH$CircularProgress), {
|
|
776
|
+
size: 60,
|
|
777
|
+
thickness: 6
|
|
778
|
+
})
|
|
779
|
+
})
|
|
780
|
+
})
|
|
781
|
+
]
|
|
782
|
+
});
|
|
698
783
|
};
|
|
699
|
-
var $
|
|
784
|
+
var $be88b298220210d1$export$2e2bcd8739ae039 = $be88b298220210d1$var$CommentsList;
|
|
785
|
+
|
|
700
786
|
|
|
701
787
|
|
|
702
788
|
const $7ce737d4a1c88e63$var$CommentsField = ({ source: source, context: context, helperText: helperText, placeholder: placeholder, userResource: userResource, mentions: mentions })=>{
|
|
703
789
|
const record = (0, $85cNH$useRecordContext)();
|
|
704
|
-
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);
|
|
705
791
|
if (!userResource) throw new Error("No userResource defined for CommentsField");
|
|
706
792
|
return /*#__PURE__*/ (0, $85cNH$jsxs)((0, $85cNH$Fragment), {
|
|
707
793
|
children: [
|
|
@@ -737,7 +823,7 @@ var $7ce737d4a1c88e63$export$2e2bcd8739ae039 = $7ce737d4a1c88e63$var$CommentsFie
|
|
|
737
823
|
|
|
738
824
|
const $d3be168cd1e7aaae$var$CollectionList = ({ collectionUrl: collectionUrl, resource: resource, children: children })=>{
|
|
739
825
|
if ((0, $85cNH$react).Children.count(children) !== 1) throw new Error("<CollectionList> only accepts a single child");
|
|
740
|
-
const { items: actorsUris } = (0, $
|
|
826
|
+
const { items: actorsUris } = (0, $8281f3ce3b9d6123$export$2e2bcd8739ae039)(collectionUrl);
|
|
741
827
|
const { data: data, isLoading: isLoading, isFetching: isFetching } = (0, $85cNH$useGetMany)(resource, {
|
|
742
828
|
ids: Array.isArray(actorsUris) ? actorsUris : [
|
|
743
829
|
actorsUris
|
|
@@ -780,302 +866,49 @@ var $ea214512ab1a2e8f$export$2e2bcd8739ae039 = $ea214512ab1a2e8f$var$ReferenceCo
|
|
|
780
866
|
|
|
781
867
|
|
|
782
868
|
|
|
783
|
-
|
|
784
|
-
const $8281f3ce3b9d6123$var$useItemsFromPages = (pages, dereferenceItems)=>{
|
|
785
|
-
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
786
|
-
const items = (0, $85cNH$useMemo)(()=>pages.flatMap((p)=>(0, $577f4953dfa5de4f$export$e57ff0f701c44363)(p.orderedItems || p.items)), [
|
|
787
|
-
pages
|
|
788
|
-
]);
|
|
789
|
-
// We will force dereference, if some items are not URI string references.
|
|
790
|
-
const shouldDereference = (0, $85cNH$useMemo)(()=>{
|
|
791
|
-
return dereferenceItems || items.some((item)=>typeof item !== "string");
|
|
792
|
-
}, [
|
|
793
|
-
dereferenceItems,
|
|
794
|
-
items
|
|
795
|
-
]);
|
|
796
|
-
// Dereference all items, if necessary (even if shouldDereference is false, the hook needs to be called).
|
|
797
|
-
const itemQueries = (0, $85cNH$useQueries)(!shouldDereference ? [] : items.filter((item)=>typeof item === "string").map((itemUri)=>({
|
|
798
|
-
queryKey: [
|
|
799
|
-
"resource",
|
|
800
|
-
itemUri
|
|
801
|
-
],
|
|
802
|
-
queryFn: async ()=>(await dataProvider.fetch(itemUri)).json,
|
|
803
|
-
staleTime: Infinity
|
|
804
|
-
})));
|
|
805
|
-
if (!shouldDereference) return {
|
|
806
|
-
loadedItems: items,
|
|
807
|
-
isLoading: false,
|
|
808
|
-
isFetching: false
|
|
809
|
-
};
|
|
810
|
-
// Put all loaded items together (might be dereferenced already, so concatenate).
|
|
811
|
-
const loadedItems = items.filter((item)=>typeof item !== "string").concat(itemQueries.flatMap((itemQuery)=>{
|
|
812
|
-
return itemQuery.isSuccess && itemQuery.data || [];
|
|
813
|
-
}));
|
|
814
|
-
const errors = itemQueries.filter((q)=>q.error);
|
|
815
|
-
return {
|
|
816
|
-
loadedItems: loadedItems,
|
|
817
|
-
isLoading: itemQueries.some((q)=>q.isLoading),
|
|
818
|
-
isFetching: itemQueries.some((q)=>q.isFetching),
|
|
819
|
-
errors: errors.length > 0 ? errors : undefined
|
|
820
|
-
};
|
|
821
|
-
};
|
|
822
869
|
/**
|
|
823
|
-
*
|
|
824
|
-
*
|
|
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
|
|
825
875
|
* @param {UseCollectionOptions} options Defaults to `{ dereferenceItems: false, liveUpdates: true }`
|
|
826
|
-
*/ const $
|
|
827
|
-
const { dereferenceItems: dereferenceItems = false, liveUpdates: liveUpdates = true } = options;
|
|
876
|
+
*/ const $cc1d1cd0e97c63a2$var$useInbox = (options = {})=>{
|
|
828
877
|
const { data: identity } = (0, $85cNH$useGetIdentity)();
|
|
829
|
-
const
|
|
830
|
-
const
|
|
831
|
-
const [hasLiveUpdates, setHasLiveUpdates] = (0, $85cNH$useState)({
|
|
832
|
-
status: "connecting"
|
|
833
|
-
});
|
|
834
|
-
const dataProvider = (0, $85cNH$useDataProvider)();
|
|
835
|
-
// Get collectionUrl from webId predicate or URL.
|
|
836
|
-
const collectionUrl = (0, $85cNH$useMemo)(()=>{
|
|
837
|
-
if (predicateOrUrl) {
|
|
838
|
-
if (predicateOrUrl.startsWith("http")) return predicateOrUrl;
|
|
839
|
-
if (identity?.webIdData) return identity?.webIdData?.[predicateOrUrl];
|
|
840
|
-
}
|
|
841
|
-
return undefined;
|
|
842
|
-
// throw new Error(`No URL available for useCollection: ${predicateOrUrl}.`);
|
|
843
|
-
}, [
|
|
844
|
-
identity,
|
|
845
|
-
predicateOrUrl
|
|
846
|
-
]);
|
|
847
|
-
// Fetch page of collection item references (if pageParam provided)
|
|
848
|
-
// or default to `collectionUrl` (which should give you the first page).
|
|
849
|
-
const fetchCollection = (0, $85cNH$useCallback)(async ({ pageParam: nextPageUrl })=>{
|
|
850
|
-
// Fetch page or first page (collectionUrl)
|
|
851
|
-
let { json: json } = await dataProvider.fetch(nextPageUrl || collectionUrl);
|
|
852
|
-
if (json.totalItems) setTotalItems(json.totalItems);
|
|
853
|
-
// If first page, handle this here.
|
|
854
|
-
if ((json.type === "OrderedCollection" || json.type === "Collection") && json.first) {
|
|
855
|
-
if (json.first?.items) {
|
|
856
|
-
if (json.first?.items.length === 0 && json.first?.next) // Special case where the first property is an object without items
|
|
857
|
-
({ json: json } = await dataProvider.fetch(json.first?.next));
|
|
858
|
-
else json = json.first;
|
|
859
|
-
} else // Fetch the first page
|
|
860
|
-
({ json: json } = await dataProvider.fetch(json.first));
|
|
861
|
-
}
|
|
862
|
-
return json;
|
|
863
|
-
}, [
|
|
864
|
-
dataProvider,
|
|
865
|
-
collectionUrl,
|
|
866
|
-
identity,
|
|
867
|
-
setTotalItems
|
|
868
|
-
]);
|
|
869
|
-
// Use infiniteQuery to handle pagination, fetching, etc.
|
|
870
|
-
const { data: pageData, error: collectionError, fetchNextPage: fetchNextPage, refetch: refetch, hasNextPage: hasNextPage, isLoading: isLoadingPage, isFetching: isFetchingPage, isFetchingNextPage: isFetchingNextPage } = (0, $85cNH$useInfiniteQuery)([
|
|
871
|
-
"collection",
|
|
872
|
-
{
|
|
873
|
-
collectionUrl: collectionUrl
|
|
874
|
-
}
|
|
875
|
-
], fetchCollection, {
|
|
876
|
-
enabled: !!(collectionUrl && identity?.id),
|
|
877
|
-
getNextPageParam: (lastPage)=>lastPage.next,
|
|
878
|
-
getPreviousPageParam: (firstPage)=>firstPage.prev
|
|
879
|
-
});
|
|
880
|
-
// Put all items together in a list (and dereference, if required).
|
|
881
|
-
const { loadedItems: items, isLoading: isLoadingItems, isFetching: isFetchingItems, errors: itemErrors } = $8281f3ce3b9d6123$var$useItemsFromPages(pageData?.pages ?? [], dereferenceItems);
|
|
882
|
-
const allErrors = (0, $577f4953dfa5de4f$export$e57ff0f701c44363)(collectionError).concat((0, $577f4953dfa5de4f$export$e57ff0f701c44363)(itemErrors));
|
|
883
|
-
const addItem = (0, $85cNH$useCallback)((item, shouldRefetch = true)=>{
|
|
884
|
-
queryClient.setQueryData([
|
|
885
|
-
"collection",
|
|
886
|
-
{
|
|
887
|
-
collectionUrl: collectionUrl
|
|
888
|
-
}
|
|
889
|
-
], (oldData)=>{
|
|
890
|
-
if (!oldData) return oldData;
|
|
891
|
-
setTotalItems(totalItems && totalItems + 1);
|
|
892
|
-
// Destructure, so react knows, it needs to re-render the pages.
|
|
893
|
-
const pages = [
|
|
894
|
-
...oldData.pages
|
|
895
|
-
];
|
|
896
|
-
const firstPageItems = pages?.[0]?.orderedItems || pages?.[0]?.items || [];
|
|
897
|
-
firstPageItems.unshift(item);
|
|
898
|
-
oldData.pages = pages;
|
|
899
|
-
return oldData;
|
|
900
|
-
});
|
|
901
|
-
if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
|
|
902
|
-
"collection",
|
|
903
|
-
{
|
|
904
|
-
collectionUrl: collectionUrl
|
|
905
|
-
}
|
|
906
|
-
], {
|
|
907
|
-
active: true,
|
|
908
|
-
exact: true
|
|
909
|
-
}), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
|
|
910
|
-
}, [
|
|
911
|
-
queryClient,
|
|
912
|
-
collectionUrl
|
|
913
|
-
]);
|
|
914
|
-
const removeItem = (0, $85cNH$useCallback)((item, shouldRefetch = true)=>{
|
|
915
|
-
queryClient.setQueryData([
|
|
916
|
-
"collection",
|
|
917
|
-
{
|
|
918
|
-
collectionUrl: collectionUrl
|
|
919
|
-
}
|
|
920
|
-
], (oldData)=>{
|
|
921
|
-
if (!oldData) return oldData;
|
|
922
|
-
setTotalItems(totalItems && totalItems - 1);
|
|
923
|
-
// Destructure, so react knows, it needs to re-render the pages array.
|
|
924
|
-
const pages = [
|
|
925
|
-
...oldData.pages
|
|
926
|
-
];
|
|
927
|
-
// Find the item in all pages and remove the item to be removed (either item.id or just item)
|
|
928
|
-
pages.forEach((page)=>{
|
|
929
|
-
if (page.orderedItems) page.orderedItems = page.orderedItems.filter((i)=>(i.id || i) !== (item.id || item));
|
|
930
|
-
else if (page.items) page.items = page.items.filter((i)=>(i.id || i) !== (item?.id || item));
|
|
931
|
-
});
|
|
932
|
-
oldData.pages = pages;
|
|
933
|
-
return oldData;
|
|
934
|
-
});
|
|
935
|
-
if (shouldRefetch) setTimeout(()=>queryClient.refetchQueries([
|
|
936
|
-
"collection",
|
|
937
|
-
{
|
|
938
|
-
collectionUrl: collectionUrl
|
|
939
|
-
}
|
|
940
|
-
], {
|
|
941
|
-
active: true,
|
|
942
|
-
exact: true
|
|
943
|
-
}), typeof shouldRefetch === "number" ? shouldRefetch : 2000);
|
|
944
|
-
}, [
|
|
945
|
-
queryClient,
|
|
946
|
-
collectionUrl
|
|
947
|
-
]);
|
|
948
|
-
// Live Updates
|
|
949
|
-
(0, $85cNH$useEffect)(()=>{
|
|
950
|
-
if (liveUpdates && collectionUrl) // Create ws that listens to collectionUri changes
|
|
951
|
-
(0, $85cNH$getOrCreateWsChannel)(dataProvider.fetch, collectionUrl).then((webSocket)=>{
|
|
952
|
-
webSocket.addEventListener("message", (e)=>{
|
|
953
|
-
const data = JSON.parse(e.data);
|
|
954
|
-
if (data && data.type === "Add") addItem(data.object, true);
|
|
955
|
-
else if (data && data.type === "Remove") removeItem(data.object, true);
|
|
956
|
-
});
|
|
957
|
-
webSocket.addEventListener("error", (e)=>{
|
|
958
|
-
setHasLiveUpdates({
|
|
959
|
-
status: "error",
|
|
960
|
-
error: e
|
|
961
|
-
});
|
|
962
|
-
// TODO: Retry after a while
|
|
963
|
-
});
|
|
964
|
-
webSocket.addEventListener("close", (e)=>{
|
|
965
|
-
if (!hasLiveUpdates.error) setHasLiveUpdates({
|
|
966
|
-
...hasLiveUpdates,
|
|
967
|
-
status: "closed"
|
|
968
|
-
});
|
|
969
|
-
});
|
|
970
|
-
setHasLiveUpdates({
|
|
971
|
-
status: "connected"
|
|
972
|
-
});
|
|
973
|
-
}).catch(()=>{}); // If it fails, we won't receive live updates. But that's okay.
|
|
974
|
-
}, [
|
|
975
|
-
collectionUrl,
|
|
976
|
-
liveUpdates,
|
|
977
|
-
dataProvider
|
|
978
|
-
]);
|
|
878
|
+
const { items: items, url: url, hasLiveUpdates: hasLiveUpdates, ...rest } = (0, $8281f3ce3b9d6123$export$2e2bcd8739ae039)("inbox", options);
|
|
879
|
+
const awaitActivity = (0, $600ca419166a1ded$export$2e2bcd8739ae039)(hasLiveUpdates.webSocket);
|
|
979
880
|
return {
|
|
980
881
|
items: items,
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
removeItem: removeItem,
|
|
987
|
-
hasNextPage: hasNextPage,
|
|
988
|
-
isLoading: isLoadingPage || isLoadingItems,
|
|
989
|
-
isFetching: isFetchingPage || isFetchingItems,
|
|
990
|
-
isFetchingNextPage: isFetchingNextPage,
|
|
991
|
-
url: collectionUrl,
|
|
992
|
-
hasLiveUpdates: hasLiveUpdates
|
|
993
|
-
};
|
|
994
|
-
};
|
|
995
|
-
var $8281f3ce3b9d6123$export$2e2bcd8739ae039 = $8281f3ce3b9d6123$var$useCollection;
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
const $542b37cc25b8ccca$var$useInbox = ()=>{
|
|
1002
|
-
const { data: identity } = (0, $85cNH$useGetIdentity)();
|
|
1003
|
-
const inboxUrl = (0, $85cNH$useMemo)(()=>{
|
|
1004
|
-
if (identity?.webIdData) return identity?.webIdData?.inbox;
|
|
1005
|
-
}, [
|
|
1006
|
-
identity
|
|
1007
|
-
]);
|
|
1008
|
-
const sparqlEndpoint = (0, $85cNH$useMemo)(()=>{
|
|
1009
|
-
if (identity?.webIdData) return identity?.webIdData?.endpoints?.["void:sparqlEndpoint"] || `${identity?.id}/sparql`;
|
|
1010
|
-
}, [
|
|
1011
|
-
identity
|
|
1012
|
-
]);
|
|
1013
|
-
const fetch = (0, $85cNH$useCallback)(async ({ filters: filters })=>{
|
|
1014
|
-
if (!sparqlEndpoint || !inboxUrl) return;
|
|
1015
|
-
const token = localStorage.getItem("token");
|
|
1016
|
-
const blankNodesQuery = (0, $85cNH$buildBlankNodesQuery)([
|
|
1017
|
-
"as:object"
|
|
1018
|
-
]);
|
|
1019
|
-
let filtersWhereQuery = "";
|
|
1020
|
-
if (filters) Object.keys(filters).forEach((predicate)=>{
|
|
1021
|
-
if (filters[predicate]) {
|
|
1022
|
-
const object = filters[predicate].startsWith("http") ? `<${filters[predicate]}>` : filters[predicate];
|
|
1023
|
-
filtersWhereQuery += `?s1 ${predicate} ${object} .`;
|
|
1024
|
-
}
|
|
1025
|
-
});
|
|
1026
|
-
const query = `
|
|
1027
|
-
PREFIX as: <https://www.w3.org/ns/activitystreams#>
|
|
1028
|
-
CONSTRUCT {
|
|
1029
|
-
?s1 ?p1 ?o1 .
|
|
1030
|
-
${blankNodesQuery.construct}
|
|
1031
|
-
}
|
|
1032
|
-
WHERE {
|
|
1033
|
-
<${inboxUrl}> as:items ?s1 .
|
|
1034
|
-
?s1 ?p1 ?o1 .
|
|
1035
|
-
FILTER( (isIRI(?s1)) ) .
|
|
1036
|
-
${filtersWhereQuery}
|
|
1037
|
-
${blankNodesQuery.where}
|
|
1038
|
-
}
|
|
1039
|
-
`;
|
|
1040
|
-
const { json: json } = await (0, $85cNH$fetchUtils).fetchJson(sparqlEndpoint, {
|
|
1041
|
-
method: "POST",
|
|
1042
|
-
body: query,
|
|
1043
|
-
headers: new Headers({
|
|
1044
|
-
Accept: "application/ld+json",
|
|
1045
|
-
Authorization: token ? `Bearer ${token}` : undefined
|
|
1046
|
-
})
|
|
1047
|
-
});
|
|
1048
|
-
if (json["@graph"]) return json["@graph"];
|
|
1049
|
-
return null;
|
|
1050
|
-
}, [
|
|
1051
|
-
sparqlEndpoint,
|
|
1052
|
-
inboxUrl
|
|
1053
|
-
]);
|
|
1054
|
-
return {
|
|
1055
|
-
fetch: fetch,
|
|
1056
|
-
url: inboxUrl,
|
|
1057
|
-
owner: identity?.id
|
|
882
|
+
url: url,
|
|
883
|
+
hasLiveUpdates: hasLiveUpdates,
|
|
884
|
+
awaitActivity: awaitActivity,
|
|
885
|
+
owner: identity?.id,
|
|
886
|
+
...rest
|
|
1058
887
|
};
|
|
1059
888
|
};
|
|
1060
|
-
var $
|
|
889
|
+
var $cc1d1cd0e97c63a2$export$2e2bcd8739ae039 = $cc1d1cd0e97c63a2$var$useInbox;
|
|
1061
890
|
|
|
1062
891
|
|
|
1063
892
|
|
|
1064
893
|
|
|
1065
|
-
const $
|
|
894
|
+
const $6a227ddc2fd92a7a$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora.software/ns/schema/2.1")=>{
|
|
1066
895
|
const [schema, setSchema] = (0, $85cNH$useState)();
|
|
1067
896
|
(0, $85cNH$useEffect)(()=>{
|
|
1068
897
|
(async ()=>{
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
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
|
+
}
|
|
1079
912
|
}
|
|
1080
913
|
})();
|
|
1081
914
|
}, [
|
|
@@ -1085,7 +918,7 @@ const $641e93142bcf5435$var$useNodeinfo = (host, rel = "http://nodeinfo.diaspora
|
|
|
1085
918
|
]);
|
|
1086
919
|
return schema;
|
|
1087
920
|
};
|
|
1088
|
-
var $
|
|
921
|
+
var $6a227ddc2fd92a7a$export$2e2bcd8739ae039 = $6a227ddc2fd92a7a$var$useNodeinfo;
|
|
1089
922
|
|
|
1090
923
|
|
|
1091
924
|
|
|
@@ -1279,5 +1112,5 @@ var $51cccd331ea8b13d$export$2e2bcd8739ae039 = $51cccd331ea8b13d$var$useMentions
|
|
|
1279
1112
|
|
|
1280
1113
|
|
|
1281
1114
|
|
|
1282
|
-
export {$7ce737d4a1c88e63$export$2e2bcd8739ae039 as CommentsField, $d3be168cd1e7aaae$export$2e2bcd8739ae039 as CollectionList, $ea214512ab1a2e8f$export$2e2bcd8739ae039 as ReferenceCollectionField, $8281f3ce3b9d6123$export$2e2bcd8739ae039 as useCollection, $
|
|
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};
|
|
1283
1116
|
//# sourceMappingURL=index.es.js.map
|