@socialwebfoundation/ap-components
Version:
A collection of Web Components for displaying objects from the ActivityPub API
103 lines (93 loc) • 2.7 kB
JavaScript
import { html, css, unsafeHTML } from 'https://cdn.jsdelivr.net/gh/lit/dist@3/all/lit-all.min.js';
import DOMPurify from 'https://cdn.jsdelivr.net/npm/dompurify@3.2.3/+esm';
import { ActivityPubElement } from './ap-element.js';
export class ActivityPubNote extends ActivityPubElement {
static get properties() {
return {
...super.properties,
_attributedTo: { type: Object, state: true },
}
}
static styles = [super.styles, css`
:host {
display: block;
min-width: var(--ap-min-width);
min-height: var(--ap-min-height);
}
.icon {
float: left;
margin-right: 8px;
}
.skeleton {
min-width: var(--ap-min-width);
min-height: var(--ap-min-height);
background-color: lightgray;
}
`];
constructor() {
super();
}
render() {
if (this._error) {
return html`
<div class="note">
<p class="error">${this._error}</p>
</div>
`
} else if (!this.json) {
return html`
<div class="note">
<div class="skeleton"></div>
</div>
`
} else if (!this._attributedTo) {
return html`
<div class="note">
<div class="skeleton"></div>
</div>
`
} else {
return html`
<div class="note">
<avatar-icon class="icon" size="64" url="${this.getIcon(this._attributedTo)}"></avatar-icon>
<p class="name">${this._attributedTo.name}</p>
<div class="content">
${unsafeHTML(DOMPurify.sanitize(this.content))}
</div>
<p class="published">
<a class="url" href="${this.url}">
${this.published}
</a>
</p>
</div>
`;
}
}
updated(changedProperties) {
super.updated(changedProperties);
if (changedProperties.has('json')) {
this.fetchAttributedTo();
}
}
async fetchAttributedTo() {
if (this.json?.attributedTo) {
if (typeof this.json.attributedTo === 'object') {
this._attributedTo = this.json.attributedTo;
} else if (typeof this.json.attributedTo === 'string') {
try {
const fn = this.constructor.fetchFunction;
const headers = { Accept: this.constructor.MEDIA_TYPES.join(', ') };
const response = await fn(this.json.attributedTo, { headers });
if (!response.ok) {
throw new Error(`HTTP ${response.status} ${response.statusText}`);
}
const json = await response.json();
this._attributedTo = json;
} catch (error) {
this._error = error.message;
}
}
}
}
}
customElements.define('ap-note', ActivityPubNote);