import {LitElement, html, unsafeHTML, until} from './lit-all.min.js'; import * as tfrpc from '/static/tfrpc.js'; import {styles} from './tf-styles.js'; class TfNewsElement extends LitElement { static get properties() { return { whoami: {type: String}, users: {type: Object}, messages: {type: Array}, following: {type: Array}, drafts: {type: Object}, expanded: {type: Object}, channel: {type: String}, channel_unread: {type: Number}, }; } static styles = styles; constructor() { super(); let self = this; this.whoami = null; this.users = {}; this.messages = []; this.following = []; this.drafts = {}; this.expanded = {}; this.channel_unread = -1; } process_messages(messages) { let self = this; let messages_by_id = {}; console.log('processing', messages.length, 'messages'); function ensure_message(id) { let found = messages_by_id[id]; if (found) { return found; } else { let added = { id: id, placeholder: true, content: '"placeholder"', parent_message: undefined, child_messages: [], votes: [], }; messages_by_id[id] = added; return added; } } function link_message(message) { if (message.content.type === 'vote') { let parent = ensure_message(message.content.vote.link); if (!parent.votes) { parent.votes = []; } parent.votes.push(message); message.parent_message = message.content.vote.link; } else if (message.content.type == 'post') { if (message.content.root) { if (typeof message.content.root === 'string') { let m = ensure_message(message.content.root); if (!m.child_messages) { m.child_messages = []; } m.child_messages.push(message); message.parent_message = message.content.root; } else { let m = ensure_message(message.content.root[0]); if (!m.child_messages) { m.child_messages = []; } m.child_messages.push(message); message.parent_message = message.content.root[0]; } } } } for (let message of messages) { message.votes = []; message.parent_message = undefined; message.child_messages = undefined; } for (let message of messages) { try { message.content = JSON.parse(message.content); } catch {} if (!messages_by_id[message.id]) { messages_by_id[message.id] = message; link_message(message); } else if (messages_by_id[message.id].placeholder) { let placeholder = messages_by_id[message.id]; messages_by_id[message.id] = message; message.parent_message = placeholder.parent_message; message.child_messages = placeholder.child_messages; message.votes = placeholder.votes; if ( placeholder.parent_message && messages_by_id[placeholder.parent_message] ) { let children = messages_by_id[placeholder.parent_message].child_messages; children.splice(children.indexOf(placeholder), 1); children.push(message); } link_message(message); } } return messages_by_id; } update_latest_subtree_timestamp(messages) { let latest = 0; for (let message of messages || []) { if (message.latest_subtree_timestamp === undefined) { message.latest_subtree_timestamp = Math.max( message.timestamp ?? 0, this.update_latest_subtree_timestamp(message.child_messages) ); } latest = Math.max(latest, message.latest_subtree_timestamp); } return latest; } finalize_messages(messages_by_id) { function recursive_sort(messages, top) { if (messages) { if (top) { messages.sort( (a, b) => b.latest_subtree_timestamp - a.latest_subtree_timestamp ); } else { messages.sort((a, b) => a.timestamp - b.timestamp); } for (let message of messages) { recursive_sort(message.child_messages, false); } return messages.map((x) => Object.assign({}, x)); } else { return {}; } } let roots = Object.values(messages_by_id).filter((x) => !x.parent_message); this.update_latest_subtree_timestamp(roots); return recursive_sort(roots, true); } group_following(messages) { let result = []; let group = []; for (let message of messages) { if (message?.content?.type === 'contact') { group.push(message); } else { if (group.length > 0) { result.push({ type: 'contact_group', messages: group, }); group = []; } result.push(message); } } return result; } load_and_render(messages) { let messages_by_id = this.process_messages(messages); let final_messages = this.group_following( this.finalize_messages(messages_by_id) ); return html`
${final_messages.map( (x) => html`` )}
`; } render() { return this.load_and_render(this.messages || []); } } customElements.define('tf-news', TfNewsElement);