import {LitElement, html, unsafeHTML, until} from './lit-all.min.js'; import * as tfrpc from '/static/tfrpc.js'; import {styles} from './tf-styles.js'; class TfTabNewsFeedElement extends LitElement { static get properties() { return { whoami: {type: String}, users: {type: Object}, hash: {type: String}, following: {type: Array}, messages: {type: Array}, drafts: {type: Object}, expanded: {type: Object}, } } static styles = styles; constructor() { super(); let self = this; this.whoami = null; this.users = {}; this.hash = '#'; this.following = []; this.drafts = {}; this.expanded = {}; } async fetch_messages() { if (this.hash.startsWith('#@')) { let r = await tfrpc.rpc.query( ` WITH mine AS (SELECT messages.* FROM messages WHERE messages.author = ? ORDER BY sequence DESC LIMIT 20) SELECT messages.* FROM mine JOIN messages_refs ON mine.id = messages_refs.ref JOIN messages ON messages_refs.message = messages.id UNION SELECT * FROM mine `, [ this.hash.substring(1), ]); return r; } else if (this.hash.startsWith('#%')) { return await tfrpc.rpc.query( ` SELECT messages.* FROM messages WHERE id = ?1 UNION SELECT messages.* FROM messages JOIN messages_refs ON messages.id = messages_refs.message WHERE messages_refs.ref = ?1 `, [ this.hash.substring(1), ]); } else { return await tfrpc.rpc.query( ` WITH news AS (SELECT messages.* FROM messages JOIN json_each(?) AS following ON messages.author = following.value WHERE messages.timestamp > ? ORDER BY messages.timestamp DESC) SELECT messages.* FROM news JOIN messages_refs ON news.id = messages_refs.ref JOIN messages ON messages_refs.message = messages.id UNION SELECT messages.* FROM news JOIN messages_refs ON news.id = messages_refs.message JOIN messages ON messages_refs.ref = messages.id UNION SELECT news.* FROM news `, [ JSON.stringify(this.following), new Date().valueOf() - 24 * 60 * 60 * 1000, ]); } } render() { if (!this.messages || this._messages_hash !== this.hash || this._messages_following !== this.following) { console.log(`loading messages for ${this.whoami}`); let self = this; this.messages = []; this._messages_hash = this.hash; this._messages_following = this.following; this.fetch_messages().then(function(messages) { self.messages = messages; console.log(`loading mesages done for ${self.whoami}`); }).catch(function(error) { alert(JSON.stringify(error, null, 2)); }); } return html``; } } class TfTabNewsElement extends LitElement { static get properties() { return { whoami: {type: String}, users: {type: Object}, hash: {type: String}, unread: {type: Array}, following: {type: Array}, drafts: {type: Object}, expanded: {type: Object}, } } static styles = styles; constructor() { super(); let self = this; this.whoami = null; this.users = {}; this.hash = '#'; this.unread = []; this.following = []; this.cache = {}; this.drafts = {}; this.expanded = {}; tfrpc.rpc.localStorageGet('drafts').then(function(d) { self.drafts = JSON.parse(d || '{}'); }); } show_more() { let unread = this.unread; let news = this.renderRoot?.getElementById('news'); if (news) { console.log('injecting messages', news.messages); news.messages = Object.values(Object.fromEntries([...this.unread, ...news.messages].map(x => [x.id, x]))); this.dispatchEvent(new CustomEvent('refresh')); } } new_messages_text() { if (!this.unread?.length) { return 'No new messages.'; } let counts = {}; for (let message of this.unread) { let type = 'private'; try { type = JSON.parse(message.content).type || type; } catch { } counts[type] = (counts[type] || 0) + 1; } return 'Show New: ' + Object.keys(counts).sort().map(x => (counts[x].toString() + ' ' + x + 's')).join(', '); } draft(event) { let id = event.detail.id || ''; if (event.detail.draft !== undefined) { let draft = {}; draft[id] = event.detail.draft; this.drafts = Object.assign({}, this.drafts, draft); } else { delete this.drafts[id]; this.drafts = Object.assign({}, this.drafts); } tfrpc.rpc.localStorageSet('drafts', JSON.stringify(this.drafts)); } on_expand(event) { if (event.detail.expanded) { let expand = {}; expand[event.detail.id] = true; this.expanded = Object.assign({}, this.expanded, expand); } else { delete this.expanded[event.detail.id]; this.expanded = Object.assign({}, this.expanded); } } render() { let profile = this.hash.startsWith('#@') ? html`` : undefined; return html`
🏠Home
Welcome, !
${profile} `; } } customElements.define('tf-tab-news-feed', TfTabNewsFeedElement); customElements.define('tf-tab-news', TfTabNewsElement);