diff options
Diffstat (limited to 'src/graph.js')
| -rw-r--r-- | src/graph.js | 205 |
1 files changed, 0 insertions, 205 deletions
diff --git a/src/graph.js b/src/graph.js deleted file mode 100644 index 7fe842c..0000000 --- a/src/graph.js +++ /dev/null @@ -1,205 +0,0 @@ -import { Component } from 'preact'; -import * as jsonld from 'jsonld'; -import { CORS_PREFIX } from './config'; - -const cors = (url) => `${CORS_PREFIX}/${url}`; - -function wrapCache(target) { - const orig = target.descriptor.value; - - target.descriptor.value = function (id, ...args) { - this.cache[id] ||= orig.call(this, id, ...args); - return this.cache[id]; - }; - - return target; -}; - -const context = [ - 'https://www.w3.org/ns/activitystreams', - { - replies: { '@id': 'as:replies', '@container': '@set' }, - inReplyTo: { '@id': 'as:inReplyTo', '@container': '@set' }, - items: { '@id': 'as:items', '@type': '@id', '@container': '@set' }, - }, -]; - -export class GraphContainer extends Component { - state = { - loading: true, - name: "loading…", - items: {}, - error: null, - }; - - cache = {}; - - componentDidMount() { - this.componentDidUpdate({}); - } - - componentDidUpdate(prevProps) { - if (prevProps.url === this.props.url) return; - - this.loadData(this.props.url) - .catch(error => { - console.error(`Error loading ${this.props.url}:`, error); - this.setState({ - loading: false, - error, - }); - }); - } - - @wrapCache - async loadUser(id) { - if (id === "https://dag.s-ol.nu/users/unknown") { - return { - '@context': context, - id, - type: 'Person', - name: 'unknown', - summary: 'unknown user', - }; - } - - try { - const user = await jsonld.compact(id, context); - user.id = id; - return user; - } catch (error) { - console.error(`Error loading user '${id}':`, error); - return { - '@context': context, - id, - type: 'Person', - name: id, - summary: 'failed to load user information', - }; - } - } - - render() { - window.state = this.state; - return this.props.render(this.state); - } -} - -export class GraphContainerMastodon extends GraphContainer { - @wrapCache - async loadCollection(id, ...args) { - const collection = await jsonld.compact(cors(id), context); - let items = []; - - const addItems = (i) => { - if (Array.isArray(i)) - items = items.concat(i); - else if (i) - items.push(i); - }; - - // discover items - if (collection.items) { - addItems(collection.items); - } else { - let page = collection.first; - const seen = []; - while (page && seen.indexOf(page.id) < 0) { - seen.push(page.id); - addItems(page.items); - - page = page.next && await jsonld.compact(cors(page.next), context); - } - } - - // dereference items - return await Promise.all(items.map(item => this.loadNote(item.id ?? item, ...args))); - } - - @wrapCache - async loadNote(id, items, inReplyTo) { - let item; - try { - item = await jsonld.frame( - cors(id), - { - '@context': context, - type: 'Note', - context: { '@embed': '@never' }, - replies: { '@embed': '@always' }, - inReplyTo: { '@embed': '@never' }, - }, - { omitGraph: true } - ); - - if (item.replies.length) - item.replies = await this.loadCollection(item.replies[0].id, items, [id]); - } catch (error) { - console.error(`Error loading note '${id}':`, error); - item = { - '@context': context, - id, - type: 'Tombstone', - formerType: 'Note', - attributedTo: 'https://dag.s-ol.nu/users/unknown', - published: '1970-01-01T00:00:00Z', - content: `Error loading note: ${error.toString()}`, - replies: [], - inReplyTo, - }; - } - - item.attributedTo = await this.loadUser(item.attributedTo); - items[item.id] = item; - return item; - } - - async loadData(url) { - const items = {}; - const root = await this.loadNote(url, items, []); - - this.setState({ - name: root.name || root.content, - items, - loading: false, - }); - } -} - -export class GraphContainerJSONLD extends GraphContainer { - async loadData(url) { - const response = await fetch(url, { - headers: { 'Accept': 'application/ld+json, application/json' }, - credentials: 'include', - }); - - const discussion = await jsonld.frame( - await response.json(), - { - '@context': context, - type: 'Document', - first: { '@embed': '@never' }, - items: { - context: { '@embed': '@never' }, - replies: { '@embed': '@never' }, - inReplyTo: { '@embed': '@never' }, - attributedTo: { '@embed': '@always' }, - }, - }, - { omitGraph: true } - ); - - const indexedItems = {}; - await Promise.all(discussion.items.map(async (item) => { - item.attributedTo = await this.loadUser(item.attributedTo); - indexedItems[item.id] = item; - })); - - discussion.items = indexedItems; - - this.setState({ - ...discussion, - loading: false, - }); - } -} |
