forked from cory/tildefriends
.gitea
apps
admin
api
apps
blog
db
follow
identity
issues
journal
room
sneaker
ssb
app.js
commonmark-hashtag.js
commonmark.min.js
emojis.js
emojis.json
filesaver.min.js
filesaver.min.js.map
index.html
lit-all.min.js
lit-all.min.js.map
script.js
tf-app.js
tf-compose.js
tf-message.js
tf-news.js
tf-profile.js
tf-reactions-modal.js
tf-styles.js
tf-tab-connections.js
tf-tab-news-feed.js
tf-tab-news.js
tf-tab-query.js
tf-tab-search.js
tf-tag.js
tf-user.js
tf-utils.js
tribute.css
tribute.esm.js
storage
test
todo
web
welcome
wiki
admin.json
api.json
apps.json
blog.json
db.json
follow.json
identity.json
issues.json
journal.json
room.json
sneaker.json
ssb.json
storage.json
test.json
todo.json
web.json
welcome.json
wiki.json
core
deps
docs
metadata
src
tools
.clang-format
.dockerignore
.git-blame-ignore-revs
.gitignore
.gitmodules
.prettierignore
.prettierrc.yaml
CONTRIBUTING.md
Dockerfile
Doxyfile
GNUmakefile
LICENSE
README.md
default.nix
flake.lock
flake.nix
package-lock.json
package.json
817 lines
20 KiB
JavaScript
817 lines
20 KiB
JavaScript
import {LitElement, html, repeat, render, unsafeHTML} from './lit-all.min.js';
|
|
import * as tfrpc from '/static/tfrpc.js';
|
|
import * as tfutils from './tf-utils.js';
|
|
import * as emojis from './emojis.js';
|
|
import {styles} from './tf-styles.js';
|
|
|
|
class TfMessageElement extends LitElement {
|
|
static get properties() {
|
|
return {
|
|
whoami: {type: String},
|
|
message: {type: Object},
|
|
users: {type: Object},
|
|
drafts: {type: Object},
|
|
format: {type: String},
|
|
blog_data: {type: String},
|
|
expanded: {type: Object},
|
|
channel: {type: String},
|
|
channel_unread: {type: Number},
|
|
};
|
|
}
|
|
|
|
static styles = styles;
|
|
|
|
constructor() {
|
|
super();
|
|
let self = this;
|
|
this.whoami = null;
|
|
this.message = {};
|
|
this.users = {};
|
|
this.drafts = {};
|
|
this.format = 'message';
|
|
this.expanded = {};
|
|
this.channel_unread = -1;
|
|
}
|
|
|
|
connectedCallback() {
|
|
super.connectedCallback();
|
|
this._click_callback = this.document_click.bind(this);
|
|
document.body.addEventListener('mouseup', this._click_callback);
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
super.disconnectedCallback();
|
|
document.body.removeEventListener('mouseup', this._click_callback);
|
|
}
|
|
|
|
document_click(event) {
|
|
let content = this.renderRoot.querySelector('.w3-dropdown-content');
|
|
let target = event.target;
|
|
if (content && !content.contains(target)) {
|
|
content.classList.remove('w3-show');
|
|
}
|
|
}
|
|
|
|
show_reply() {
|
|
let event = new CustomEvent('tf-draft', {
|
|
bubbles: true,
|
|
composed: true,
|
|
detail: {
|
|
id: this.message?.id,
|
|
draft: {
|
|
encrypt_to: this.message?.decrypted?.recps,
|
|
},
|
|
},
|
|
});
|
|
this.dispatchEvent(event);
|
|
}
|
|
|
|
discard_reply() {
|
|
this.dispatchEvent(
|
|
new CustomEvent('tf-draft', {
|
|
bubbles: true,
|
|
composed: true,
|
|
detail: {id: this.id, draft: undefined},
|
|
})
|
|
);
|
|
}
|
|
|
|
show_reactions() {
|
|
let modal = document.getElementById('reactions_modal');
|
|
modal.users = this.users;
|
|
modal.votes = this.message?.votes || [];
|
|
}
|
|
|
|
render_votes() {
|
|
function normalize_expression(expression) {
|
|
if (expression === 'Like' || !expression) {
|
|
return '👍';
|
|
} else if (expression === 'Unlike') {
|
|
return '👎';
|
|
} else if (expression === 'heart') {
|
|
return '❤️';
|
|
} else {
|
|
return expression;
|
|
}
|
|
}
|
|
if (this.message?.votes?.length) {
|
|
return html` <div class="w3-container">
|
|
<div
|
|
class="w3-button w3-bar w3-padding-small"
|
|
@click=${this.show_reactions}
|
|
>
|
|
${(this.message.votes || []).map(
|
|
(vote) => html`
|
|
<span
|
|
class="w3-bar-item w3-padding-small"
|
|
title="${this.users[vote.author]?.name ??
|
|
vote.author} ${new Date(vote.timestamp)}"
|
|
>
|
|
${normalize_expression(vote.content.vote.expression)}
|
|
</span>
|
|
`
|
|
)}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
}
|
|
|
|
render_json(value) {
|
|
let json = JSON.stringify(value, null, 2);
|
|
return html`
|
|
<pre style="white-space: pre-wrap; overflow-wrap: anywhere">${json}</pre>
|
|
`;
|
|
}
|
|
|
|
render_raw() {
|
|
let raw = {
|
|
id: this.message?.id,
|
|
previous: this.message?.previous,
|
|
author: this.message?.author,
|
|
sequence: this.message?.sequence,
|
|
timestamp: this.message?.timestamp,
|
|
hash: this.message?.hash,
|
|
content: this.message?.content,
|
|
signature: this.message?.signature,
|
|
};
|
|
return this.render_json(raw);
|
|
}
|
|
|
|
vote(emoji) {
|
|
let reaction = emoji;
|
|
let message = this.message.id;
|
|
tfrpc.rpc
|
|
.appendMessage(this.whoami, {
|
|
type: 'vote',
|
|
vote: {
|
|
link: message,
|
|
value: 1,
|
|
expression: reaction,
|
|
},
|
|
})
|
|
.catch(function (error) {
|
|
alert(error?.message);
|
|
});
|
|
}
|
|
|
|
react(event) {
|
|
emojis.picker((x) => this.vote(x), null, this.whoami);
|
|
}
|
|
|
|
show_image(link) {
|
|
let div = document.createElement('div');
|
|
div.style.left = 0;
|
|
div.style.top = 0;
|
|
div.style.width = '100%';
|
|
div.style.height = '100%';
|
|
div.style.position = 'fixed';
|
|
div.style.background = '#000';
|
|
div.style.zIndex = 100;
|
|
div.style.display = 'grid';
|
|
let img = document.createElement('img');
|
|
img.src = link;
|
|
img.style.maxWidth = '100%';
|
|
img.style.maxHeight = '100%';
|
|
img.style.display = 'block';
|
|
img.style.margin = 'auto';
|
|
img.style.objectFit = 'contain';
|
|
img.style.width = '100%';
|
|
div.appendChild(img);
|
|
function image_close(event) {
|
|
document.body.removeChild(div);
|
|
window.removeEventListener('keydown', image_close);
|
|
}
|
|
div.onclick = image_close;
|
|
window.addEventListener('keydown', image_close);
|
|
document.body.appendChild(div);
|
|
}
|
|
|
|
body_click(event) {
|
|
if (event.srcElement.tagName == 'IMG') {
|
|
this.show_image(event.srcElement.src);
|
|
} else if (
|
|
event.srcElement.tagName == 'DIV' &&
|
|
event.srcElement.classList.contains('img_caption')
|
|
) {
|
|
let next = event.srcElement.nextSibling;
|
|
if (next.style.display != 'none') {
|
|
next.style.display = 'none';
|
|
} else {
|
|
next.style.display = 'block';
|
|
}
|
|
}
|
|
}
|
|
|
|
render_mention(mention) {
|
|
if (!mention?.link || typeof mention.link != 'string') {
|
|
return this.render_json(mention);
|
|
} else if (
|
|
mention?.link?.startsWith('&') &&
|
|
mention?.type?.startsWith('image/')
|
|
) {
|
|
return html`
|
|
<img
|
|
src=${'/' + mention.link + '/view'}
|
|
style="max-width: 128px; max-height: 128px"
|
|
title=${mention.name}
|
|
@click=${() => this.show_image('/' + mention.link + '/view')}
|
|
/>
|
|
`;
|
|
} else if (
|
|
mention.link?.startsWith('&') &&
|
|
mention.name?.startsWith('audio:')
|
|
) {
|
|
return html`
|
|
<audio controls style="height: 32px">
|
|
<source src=${'/' + mention.link + '/view'}></source>
|
|
</audio>
|
|
`;
|
|
} else if (
|
|
mention.link?.startsWith('&') &&
|
|
mention.name?.startsWith('video:')
|
|
) {
|
|
return html`
|
|
<video controls style="max-height: 240px; max-width: 128px">
|
|
<source src=${'/' + mention.link + '/view'}></source>
|
|
</video>
|
|
`;
|
|
} else if (
|
|
mention.link?.startsWith('&') &&
|
|
mention?.type === 'application/tildefriends'
|
|
) {
|
|
return html` <a href=${`/${mention.link}/`}>😎 ${mention.name}</a>`;
|
|
} else if (mention.link?.startsWith('%') || mention.link?.startsWith('@')) {
|
|
return html` <a href=${'#' + encodeURIComponent(mention.link)}
|
|
>${mention.name}</a
|
|
>`;
|
|
} else if (mention.link?.startsWith('#')) {
|
|
return html` <a href=${'#' + encodeURIComponent('#' + mention.link)}
|
|
>${mention.link}</a
|
|
>`;
|
|
} else if (
|
|
Object.keys(mention).length == 2 &&
|
|
mention.link &&
|
|
mention.name
|
|
) {
|
|
return html` <a href=${`/${mention.link}/view`}>${mention.name}</a>`;
|
|
} else {
|
|
return this.render_json(mention);
|
|
}
|
|
}
|
|
|
|
render_mentions() {
|
|
let mentions = this.message?.content?.mentions || [];
|
|
mentions = mentions.filter(
|
|
(x) =>
|
|
this.message?.content?.text?.indexOf(
|
|
typeof x === 'string' ? x : x.link
|
|
) === -1
|
|
);
|
|
if (mentions.length) {
|
|
let self = this;
|
|
return html`
|
|
<fieldset style="padding: 0.5em; border: 1px solid black">
|
|
<legend>Mentions</legend>
|
|
${mentions.map((x) => self.render_mention(x))}
|
|
</fieldset>
|
|
`;
|
|
}
|
|
}
|
|
|
|
total_child_messages(message) {
|
|
if (!message.child_messages) {
|
|
return 0;
|
|
}
|
|
let total = message.child_messages.length;
|
|
for (let m of message.child_messages) {
|
|
total += this.total_child_messages(m);
|
|
}
|
|
return total;
|
|
}
|
|
|
|
set_expanded(expanded, tag) {
|
|
this.dispatchEvent(
|
|
new CustomEvent('tf-expand', {
|
|
bubbles: true,
|
|
composed: true,
|
|
detail: {id: (this.message.id || '') + (tag || ''), expanded: expanded},
|
|
})
|
|
);
|
|
}
|
|
|
|
toggle_expanded(tag) {
|
|
this.set_expanded(
|
|
!this.expanded[(this.message.id || '') + (tag || '')],
|
|
tag
|
|
);
|
|
}
|
|
|
|
render_children() {
|
|
let self = this;
|
|
if (this.message.child_messages?.length) {
|
|
if (!this.expanded[this.message.id]) {
|
|
return html`
|
|
<button
|
|
class="w3-button w3-theme-d1 w3-block w3-bar"
|
|
style="box-sizing: border-box"
|
|
@click=${() => self.set_expanded(true)}
|
|
>
|
|
+ ${this.total_child_messages(this.message) + ' More'}
|
|
</button>
|
|
`;
|
|
} else {
|
|
return html` <div class="w3-container w3-margin-bottom">
|
|
${repeat(
|
|
this.message.child_messages || [],
|
|
(x) => x.id,
|
|
(x) =>
|
|
html`<tf-message
|
|
.message=${x}
|
|
whoami=${this.whoami}
|
|
.users=${this.users}
|
|
.drafts=${this.drafts}
|
|
.expanded=${this.expanded}
|
|
channel=${this.channel}
|
|
channel_unread=${this.channel_unread}
|
|
></tf-message>`
|
|
)}
|
|
</div>
|
|
<button
|
|
class="w3-button w3-theme-d1 w3-block w3-bar"
|
|
style="box-sizing: border-box"
|
|
@click=${() => self.set_expanded(false)}
|
|
>
|
|
Collapse
|
|
</button>`;
|
|
}
|
|
} else {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
mark_unread() {
|
|
this.dispatchEvent(
|
|
new CustomEvent('channelsetunread', {
|
|
bubbles: true,
|
|
composed: true,
|
|
detail: {
|
|
channel: this.channel,
|
|
unread: this.message.rowid,
|
|
},
|
|
})
|
|
);
|
|
}
|
|
|
|
render_channels() {
|
|
let content = this.message?.content;
|
|
if (this?.messsage?.decrypted?.type == 'post') {
|
|
content = this.message.decrypted;
|
|
}
|
|
let channels = [];
|
|
if (typeof content.channel === 'string') {
|
|
channels.push(`#${content.channel}`);
|
|
}
|
|
if (Array.isArray(content.mentions)) {
|
|
for (let mention of content.mentions) {
|
|
if (typeof mention?.link === 'string' && mention.link.startsWith('#')) {
|
|
channels.push(mention.link);
|
|
}
|
|
}
|
|
}
|
|
return channels.map((x) => html`<tf-tag tag=${x}></tf-tag>`);
|
|
}
|
|
|
|
class_background() {
|
|
return this.message?.decrypted
|
|
? 'w3-pale-red'
|
|
: this.message?.rowid >= this.channel_unread
|
|
? 'w3-theme-d2'
|
|
: 'w3-theme-d4';
|
|
}
|
|
|
|
get_content() {
|
|
let content = this.message?.content;
|
|
if (this.message?.decrypted?.type == 'post') {
|
|
content = this.message.decrypted;
|
|
}
|
|
return content;
|
|
}
|
|
|
|
copy_id(event) {
|
|
navigator.clipboard.writeText(this.message?.id);
|
|
}
|
|
|
|
toggle_menu(event) {
|
|
event.srcElement.parentNode
|
|
.querySelector('.w3-dropdown-content')
|
|
.classList.toggle('w3-show');
|
|
}
|
|
|
|
render_menu() {
|
|
let content = this.get_content();
|
|
let formats = [['message', 'Message']];
|
|
if (content?.type == 'post' || content?.type == 'blog') {
|
|
formats.push(['md', 'Markdown']);
|
|
}
|
|
if (this.message?.decrypted) {
|
|
formats.push(['decrypted', 'Decrypted']);
|
|
}
|
|
formats.push(['raw', 'Raw']);
|
|
return html`
|
|
<div class="w3-bar-item w3-right">
|
|
<button class="w3-button w3-theme-d1" @click=${this.toggle_menu}>
|
|
%
|
|
</button>
|
|
<div
|
|
class="w3-dropdown-content w3-bar-block w3-card-4 w3-theme-l1"
|
|
style="right: 48px"
|
|
>
|
|
<a
|
|
target="_top"
|
|
class="w3-button w3-bar-item"
|
|
href=${'#' + encodeURIComponent(this.message?.id)}
|
|
>View Message</a
|
|
>
|
|
<button
|
|
class="w3-button w3-bar-item w3-border-bottom"
|
|
@click=${this.copy_id}
|
|
>
|
|
Copy ID
|
|
</button>
|
|
${this.drafts[this.message?.id] === undefined
|
|
? html`
|
|
<button class="w3-button w3-bar-item" @click=${this.show_reply}>
|
|
⮢ Reply
|
|
</button>
|
|
`
|
|
: undefined}
|
|
<button
|
|
class="w3-button w3-bar-item w3-border-bottom"
|
|
@click=${this.react}
|
|
>
|
|
👍 React
|
|
</button>
|
|
${formats.map(
|
|
([format, name]) => html`
|
|
<button
|
|
class="w3-button w3-bar-item"
|
|
style=${format == this.format ? 'font-weight: bold' : ''}
|
|
@click=${() => (this.format = format)}
|
|
>
|
|
${name}
|
|
</button>
|
|
`
|
|
)}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
render_header() {
|
|
let is_encrypted = this.message?.decrypted
|
|
? html`<span class="w3-bar-item">🔓</span>`
|
|
: typeof this.message?.content == 'string'
|
|
? html`<span class="w3-bar-item">🔒</span>`
|
|
: undefined;
|
|
return html`
|
|
<header class="w3-bar">
|
|
<span class="w3-bar-item">
|
|
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
|
</span>
|
|
${is_encrypted} ${this.render_menu()}
|
|
<div class="w3-bar-item w3-right" style="text-wrap: nowrap">
|
|
${new Date(this.message.timestamp).toLocaleString()}
|
|
</div>
|
|
</header>
|
|
`;
|
|
}
|
|
|
|
render_frame(inner) {
|
|
return html`
|
|
<style>
|
|
code {
|
|
white-space: pre-wrap;
|
|
overflow-wrap: break-word;
|
|
}
|
|
div {
|
|
overflow-wrap: anywhere;
|
|
}
|
|
img {
|
|
max-width: 100%;
|
|
height: auto;
|
|
display: block;
|
|
}
|
|
</style>
|
|
<div
|
|
class="w3-card-4 ${this.class_background()} w3-border-theme w3-margin-top"
|
|
style="overflow: auto; overflow-wrap: anywhere; display: block; max-width: 100%"
|
|
>
|
|
${inner}
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
render_small_frame(inner) {
|
|
let self = this;
|
|
return this.render_frame(html`
|
|
${self.render_header()}
|
|
${self.format == 'raw'
|
|
? html`<div class="w3-container">${self.render_raw()}</div>`
|
|
: inner}
|
|
${self.render_votes()}
|
|
${(self.message.child_messages || []).map(
|
|
(x) => html`
|
|
<tf-message
|
|
.message=${x}
|
|
whoami=${self.whoami}
|
|
.users=${self.users}
|
|
.drafts=${self.drafts}
|
|
.expanded=${self.expanded}
|
|
channel=${self.channel}
|
|
channel_unread=${self.channel_unread}
|
|
></tf-message>
|
|
`
|
|
)}
|
|
`);
|
|
}
|
|
|
|
render_actions() {
|
|
let content = this.get_content();
|
|
let reply =
|
|
this.drafts[this.message?.id] !== undefined
|
|
? html`
|
|
<tf-compose
|
|
whoami=${this.whoami}
|
|
.users=${this.users}
|
|
root=${content.root || this.message.id}
|
|
branch=${this.message.id}
|
|
.drafts=${this.drafts}
|
|
@tf-discard=${this.discard_reply}
|
|
author=${this.message.author}
|
|
></tf-compose>
|
|
`
|
|
: undefined;
|
|
return html`
|
|
<div class="w3-section w3-container">${reply}</div>
|
|
<footer>${this.render_children()}</footer>
|
|
`;
|
|
}
|
|
|
|
render() {
|
|
let content = this.message?.content;
|
|
if (this.message?.decrypted?.type == 'post') {
|
|
content = this.message.decrypted;
|
|
}
|
|
let class_background = this.class_background();
|
|
let self = this;
|
|
if (this.message?.type === 'contact_group') {
|
|
return this.render_frame(
|
|
html` ${this.message.messages.map(
|
|
(x) =>
|
|
html`<tf-message
|
|
.message=${x}
|
|
whoami=${this.whoami}
|
|
.users=${this.users}
|
|
.drafts=${this.drafts}
|
|
.expanded=${this.expanded}
|
|
channel=${this.channel}
|
|
channel_unread=${this.channel_unread}
|
|
></tf-message>`
|
|
)}`
|
|
);
|
|
} else if (this.message.placeholder) {
|
|
return this.render_frame(
|
|
html`<div class="w3-padding">
|
|
<p>
|
|
<a target="_top" href=${'#' + encodeURIComponent(this.message.id)}
|
|
>${this.message.id}</a
|
|
>
|
|
(placeholder)
|
|
</p>
|
|
<div>${this.render_votes()}</div>
|
|
${(this.message.child_messages || []).map(
|
|
(x) => html`
|
|
<tf-message
|
|
.message=${x}
|
|
whoami=${this.whoami}
|
|
.users=${this.users}
|
|
.drafts=${this.drafts}
|
|
.expanded=${this.expanded}
|
|
channel=${this.channel}
|
|
channel_unread=${this.channel_unread}
|
|
></tf-message>
|
|
`
|
|
)}
|
|
</div>`
|
|
);
|
|
} else if (typeof content?.type === 'string') {
|
|
if (content.type == 'about') {
|
|
let name;
|
|
let image;
|
|
let description;
|
|
if (content.name !== undefined) {
|
|
name = html`<div><b>Name:</b> ${content.name}</div>`;
|
|
}
|
|
if (content.image !== undefined) {
|
|
image = html`
|
|
<div><img src=${'/' + (typeof content.image?.link == 'string' ? content.image.link : content.image) + '/view'} style="width: 256px; height: auto"></img></div>
|
|
`;
|
|
}
|
|
if (content.description !== undefined) {
|
|
description = html`
|
|
<div style="flex: 1 0 50%; overflow-wrap: anywhere">
|
|
<div>${unsafeHTML(tfutils.markdown(content.description))}</div>
|
|
</div>
|
|
`;
|
|
}
|
|
let update =
|
|
content.about == this.message.author
|
|
? html`<div style="font-weight: bold">Updated profile.</div>`
|
|
: html`<div style="font-weight: bold">
|
|
Updated profile for
|
|
<tf-user id=${content.about} .users=${this.users}></tf-user>.
|
|
</div>`;
|
|
return this.render_small_frame(html`
|
|
<div class="w3-container">
|
|
<p>${update} ${name} ${image} ${description}</p>
|
|
</div>
|
|
`);
|
|
} else if (content.type == 'contact') {
|
|
return html`
|
|
<div class="w3-padding">
|
|
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
|
is
|
|
${content.blocking === true
|
|
? 'blocking'
|
|
: content.blocking === false
|
|
? 'no longer blocking'
|
|
: content.following === true
|
|
? 'following'
|
|
: content.following === false
|
|
? 'no longer following'
|
|
: '?'}
|
|
<tf-user
|
|
id=${this.message.content.contact}
|
|
.users=${this.users}
|
|
></tf-user>
|
|
</div>
|
|
`;
|
|
} else if (content.type == 'post') {
|
|
let self = this;
|
|
let body;
|
|
switch (this.format) {
|
|
case 'raw':
|
|
body = this.render_raw();
|
|
break;
|
|
case 'md':
|
|
body = html`<code
|
|
style="white-space: pre-wrap; overflow-wrap: anywhere"
|
|
>${content.text}</code
|
|
>`;
|
|
break;
|
|
case 'message':
|
|
body = unsafeHTML(tfutils.markdown(content.text));
|
|
break;
|
|
case 'decrypted':
|
|
body = this.render_json(content);
|
|
break;
|
|
}
|
|
let content_warning = html`
|
|
<div
|
|
class="w3-panel w3-round-xlarge w3-theme-l4"
|
|
style="cursor: pointer"
|
|
@click=${(x) => this.toggle_expanded(':cw')}
|
|
>
|
|
<p>${content.contentWarning}</p>
|
|
</div>
|
|
`;
|
|
let content_html = html`
|
|
${this.render_channels()}
|
|
<div @click=${this.body_click}>${body}</div>
|
|
${this.render_mentions()}
|
|
`;
|
|
let payload = content.contentWarning
|
|
? self.expanded[(this.message.id || '') + ':cw']
|
|
? html` ${content_warning} ${content_html} `
|
|
: content_warning
|
|
: content_html;
|
|
return this.render_frame(html`
|
|
${this.render_header()}
|
|
<div class="w3-container">${payload}</div>
|
|
${this.render_votes()} ${this.render_actions()}
|
|
</div>
|
|
`);
|
|
} else if (content.type === 'issue') {
|
|
return this.render_frame(html`
|
|
${this.render_header()} ${content.text} ${this.render_votes()}
|
|
<footer class="w3-container">
|
|
<button class="w3-button w3-theme-d1" @click=${this.react}>
|
|
React
|
|
</button>
|
|
${this.render_children()}
|
|
</footer>
|
|
`);
|
|
} else if (content.type === 'blog') {
|
|
let self = this;
|
|
tfrpc.rpc.get_blob(content.blog).then(function (data) {
|
|
self.blog_data = data;
|
|
});
|
|
let payload = this.expanded[(this.message.id || '') + ':blog']
|
|
? html`<div>
|
|
${this.blog_data
|
|
? unsafeHTML(tfutils.markdown(this.blog_data))
|
|
: 'Loading...'}
|
|
</div>`
|
|
: undefined;
|
|
let body;
|
|
switch (this.format) {
|
|
case 'raw':
|
|
body = this.render_raw();
|
|
break;
|
|
case 'md':
|
|
body = content.summary;
|
|
break;
|
|
case 'message':
|
|
body = html`
|
|
<div
|
|
style="border: 1px solid #fff; border-radius: 1em; padding: 8px; margin: 4px; cursor: pointer"
|
|
@click=${(x) => self.toggle_expanded(':blog')}>
|
|
<h2>${content.title}</h2>
|
|
<div style="display: flex; flex-direction: row">
|
|
<img src=/${content.thumbnail}/view></img>
|
|
<span>${content.summary}</span>
|
|
</div>
|
|
</div>
|
|
${payload}
|
|
`;
|
|
break;
|
|
}
|
|
return this.render_frame(html`
|
|
${this.render_header()}
|
|
<div>${body}</div>
|
|
${this.render_mentions()} ${this.render_votes()}
|
|
${this.render_actions()}
|
|
`);
|
|
} else if (content.type === 'pub') {
|
|
return this.render_small_frame(
|
|
html` <style>
|
|
span {
|
|
overflow-wrap: anywhere;
|
|
}
|
|
</style>
|
|
<div class="w3-padding">
|
|
<div>
|
|
🍻
|
|
<tf-user
|
|
.users=${this.users}
|
|
id=${content.address.key}
|
|
></tf-user>
|
|
</div>
|
|
<pre>${content.address.host}:${content.address.port}</pre>
|
|
</div>`
|
|
);
|
|
} else if (content.type === 'channel') {
|
|
return this.render_small_frame(html`
|
|
<div class="w3-container">
|
|
<p>
|
|
${content.subscribed ? 'subscribed to' : 'unsubscribed from'}
|
|
<a href=${'#' + encodeURIComponent('#' + content.channel)}
|
|
>#${content.channel}</a
|
|
>
|
|
</p>
|
|
</div>
|
|
`);
|
|
} else if (typeof this.message.content == 'string') {
|
|
if (this.message?.decrypted) {
|
|
if (this.format == 'decrypted') {
|
|
return this.render_small_frame(
|
|
html`<span class="w3-container">🔓</span> ${this.render_json(
|
|
this.message.decrypted
|
|
)}`
|
|
);
|
|
} else {
|
|
return this.render_small_frame(
|
|
html`<span class="w3-container">🔓</span>
|
|
<div class="w3-container">${this.message.decrypted.type}</div>`
|
|
);
|
|
}
|
|
} else {
|
|
return this.render_small_frame();
|
|
}
|
|
} else {
|
|
return this.render_small_frame(
|
|
html`<div class="w3-container">
|
|
<p><b>type</b>: ${content.type}</p>
|
|
</div>`
|
|
);
|
|
}
|
|
} else if (typeof this.message.content == 'string') {
|
|
return this.render_small_frame();
|
|
} else {
|
|
return this.render_small_frame(this.render_raw());
|
|
}
|
|
}
|
|
}
|
|
|
|
customElements.define('tf-message', TfMessageElement);
|