forked from cory/tildefriends
164 lines
5.0 KiB
JavaScript
164 lines
5.0 KiB
JavaScript
|
import {LitElement, html, 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},
|
||
|
reply: {type: Boolean},
|
||
|
raw: {type: Boolean},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static styles = styles;
|
||
|
|
||
|
constructor() {
|
||
|
super();
|
||
|
let self = this;
|
||
|
this.whoami = null;
|
||
|
this.message = {};
|
||
|
this.users = {};
|
||
|
this.reply = false;
|
||
|
this.raw = false;
|
||
|
}
|
||
|
|
||
|
show_reply() {
|
||
|
this.reply = true;
|
||
|
}
|
||
|
|
||
|
render_votes() {
|
||
|
function normalize_expression(expression) {
|
||
|
if (expression === 'Like' || !expression) {
|
||
|
return '👍';
|
||
|
} else {
|
||
|
return expression;
|
||
|
}
|
||
|
}
|
||
|
return html`<div>${(this.message.votes || []).map(vote => html`<span title="${this.users[vote.author]?.name ?? vote.author}">${normalize_expression(vote.content.vote.expression)}</span>`)}</div>`;
|
||
|
}
|
||
|
|
||
|
render_raw() {
|
||
|
return html`<div style="white-space: pre-wrap">${JSON.stringify(this.message, null, 2)}</div>`
|
||
|
}
|
||
|
|
||
|
vote(emoji) {
|
||
|
let reaction = emoji.emoji;
|
||
|
let message = this.message.id;
|
||
|
if (confirm('Are you sure you want to react with ' + reaction + ' to ' + message + '?')) {
|
||
|
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));
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
let content = this.message?.content;
|
||
|
let self = this;
|
||
|
let raw_button = this.raw ?
|
||
|
html`<input type="button" value="Message" @click=${() => self.raw = false}></input>` :
|
||
|
html`<input type="button" value="Raw" @click=${() => self.raw = true}></input>`;
|
||
|
function small_frame(inner) {
|
||
|
return html`
|
||
|
<div style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; display: inline-block">
|
||
|
<tf-user id=${self.message.author} .users=${self.users}></tf-user>
|
||
|
<span style="padding-right: 8px"><a target="_top" href=${'#' + self.message.id}>%</a> ${new Date(self.message.timestamp).toLocaleString()}</span>
|
||
|
${raw_button}
|
||
|
${self.raw ? self.render_raw() : inner}
|
||
|
${self.render_votes()}
|
||
|
</div>
|
||
|
`
|
||
|
}
|
||
|
if (this.message.placeholder) {
|
||
|
return html`
|
||
|
<div style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px">
|
||
|
${this.message.id} (placeholder)
|
||
|
<div>${this.render_votes()}</div>
|
||
|
${(this.message.child_messages || []).map(x => html`
|
||
|
<tf-message .message=${x} whoami=${this.whoami} .users=${this.users}></tf-message>
|
||
|
`)}
|
||
|
</div>`;
|
||
|
} else if (content.type == 'about') {
|
||
|
return small_frame(html`
|
||
|
<div style="font-weight: bold">Updated profile:</div>
|
||
|
<pre style="white-space: pre-wrap">${JSON.stringify(content, null, 2)}</pre>
|
||
|
`);
|
||
|
} else if (content.type == 'contact') {
|
||
|
return small_frame(html`
|
||
|
<div>
|
||
|
is now
|
||
|
${
|
||
|
content.blocking === true ? 'blocking' :
|
||
|
content.blocking === false ? 'unblocking' :
|
||
|
content.following === true ? 'following' :
|
||
|
content.following === false ? 'unfollowing' :
|
||
|
'?'
|
||
|
}
|
||
|
<tf-user id=${this.message.content.contact} .users=${this.users}></tf-user>
|
||
|
</div>
|
||
|
`);
|
||
|
} else if (content.type == 'post') {
|
||
|
let reply = this.reply ? html`
|
||
|
<tf-compose
|
||
|
?enabled=${this.reply}
|
||
|
whoami=${this.whoami}
|
||
|
.users=${this.users}
|
||
|
root=${this.message.content.root || this.message.id}
|
||
|
branch=${this.message.id}
|
||
|
@tf-discard=${() => this.reply = false}></tf-compose>
|
||
|
` : html`
|
||
|
<input type="button" value="Reply" @click=${this.show_reply}></input>
|
||
|
`;
|
||
|
let self = this;
|
||
|
let body = this.raw ?
|
||
|
this.render_raw() :
|
||
|
unsafeHTML(tfutils.markdown(content.text));
|
||
|
return html`
|
||
|
<style>
|
||
|
img {
|
||
|
max-width: 100%;
|
||
|
height: auto;
|
||
|
}
|
||
|
</style>
|
||
|
<div style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px">
|
||
|
<div style="display: flex; flex-direction: row">
|
||
|
<tf-user id=${this.message.author} .users=${this.users}></tf-user>
|
||
|
<span style="flex: 1"></span>
|
||
|
<span style="padding-right: 8px"><a target="_top" href=${'#' + self.message.id}>%</a> ${new Date(this.message.timestamp).toLocaleString()}</span>
|
||
|
<span>${raw_button}</span>
|
||
|
</div>
|
||
|
<div>${body}</div>
|
||
|
${this.render_votes()}
|
||
|
<div>
|
||
|
${reply}
|
||
|
<input type="button" value="React" @click=${this.react}></input>
|
||
|
</div>
|
||
|
${(this.message.child_messages || []).map(x => html`<tf-message .message=${x} whoami=${this.whoami} .users=${this.users}></tf-message>`)}
|
||
|
</div>
|
||
|
`;
|
||
|
} else if (typeof(this.message.content) == 'string') {
|
||
|
return small_frame(html`<span>🔒</span>`);
|
||
|
} else {
|
||
|
return small_frame(this.render_raw());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
customElements.define('tf-message', TfMessageElement);
|