import {LitElement, html, unsafeHTML, until} from './lit-all.min.js'; import * as tfrpc from '/static/tfrpc.js'; import {styles} from './tf-styles.js'; class TfTabNewsElement extends LitElement { static get properties() { return { whoami: {type: String}, users: {type: Object}, hash: {type: String}, following: {type: Array}, drafts: {type: Object}, expanded: {type: Object}, loading: {type: Boolean}, channels: {type: Array}, channels_unread: {type: Object}, channels_latest: {type: Object}, connections: {type: Array}, }; } static styles = styles; constructor() { super(); let self = this; this.whoami = null; this.users = {}; this.hash = '#'; this.following = []; this.cache = {}; this.drafts = {}; this.expanded = {}; this.channels_unread = {}; this.channels_latest = {}; this.channels = []; this.connections = []; tfrpc.rpc.localStorageGet('drafts').then(function (d) { self.drafts = JSON.parse(d || '{}'); }); } connectedCallback() { super.connectedCallback(); document.body.addEventListener('keypress', this.on_keypress.bind(this)); } disconnectedCallback() { super.disconnectedCallback(); document.body.removeEventListener('keypress', this.on_keypress.bind(this)); } load_latest() { let news = this.shadowRoot?.getElementById('news'); if (news) { news.load_latest(); } } draft(event) { let id = event.detail.id || ''; let previous = this.drafts[id]; if (event.detail.draft !== undefined) { this.drafts[id] = event.detail.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); } } on_keypress(event) { if (event.target === document.body && event.key == '.') { this.show_more(); } } unread_status(channel) { if ( this.channels_latest[channel] && this.channels_latest[channel] > 0 && (this.channels_unread[channel] === undefined || this.channels_unread[channel] <= this.channels_latest[channel]) ) { return 'βοΈ '; } } show_sidebar() { this.renderRoot.getElementById('sidebar').style.display = 'block'; this.renderRoot.getElementById('sidebar_overlay').style.display = 'block'; } hide_sidebar() { this.renderRoot.getElementById('sidebar').style.display = 'none'; this.renderRoot.getElementById('sidebar_overlay').style.display = 'none'; } async channel_toggle_subscribed() { let channel = this.hash.substring(2); let subscribed = this.channels.indexOf(channel) != -1; subscribed = !subscribed; await tfrpc.rpc.appendMessage(this.whoami, { type: 'channel', channel: channel, subscribed: subscribed, }); if (subscribed) { this.channels = [].concat([channel], this.channels).sort(); } else { this.channels = this.channels.filter((x) => x != channel); } } channel() { return this.hash.startsWith('##') ? this.hash.substring(2) : undefined; } render_sidebar() { return html` <div class="w3-sidebar w3-bar-block w3-theme-d1 w3-collapse w3-animate-left" style="width: 2in; left: 0; z-index: 5; box-sizing: border-box; top: 0" id="sidebar" > <div class="w3-right w3-button w3-hide-large" @click=${this.hide_sidebar} > × </div> ${this.hash.startsWith('##') && this.channels.indexOf(this.hash.substring(2)) == -1 ? html` <div class="w3-bar-item w3-theme-d2">Viewing</div> <a href="#" class="w3-bar-item w3-button" style="font-weight: bold" >${this.hash.substring(2)}</a > ` : undefined} <div class="w3-bar-item w3-theme-d2">Channels</div> <a href="#" class="w3-bar-item w3-button" style=${this.hash == '#' ? 'font-weight: bold' : undefined} >${this.unread_status('')}general</a > <a href="#@" class="w3-bar-item w3-button" style=${this.hash == '#@' ? 'font-weight: bold' : undefined} >${this.unread_status('@')}@mentions</a > <a href="#π" class="w3-bar-item w3-button" style=${this.hash == '#π' ? 'font-weight: bold' : undefined} >${this.unread_status('π')}πprivate</a > ${Object.keys(this.drafts) .sort() .map( (x) => html` <a href=${'#' + encodeURIComponent(x)} class="w3-bar-item w3-button" style="text-wrap: nowrap; text-overflow: ellipsis" >π ${this.drafts[x]?.text ?? x}</a > ` )} ${this.channels.map( (x) => html` <a href=${'#' + encodeURIComponent('#' + x)} class="w3-bar-item w3-button" style=${this.hash == '##' + x ? 'font-weight: bold' : undefined} >${this.unread_status(x)}#${x}</a > ` )} <div class="w3-bar-item w3-theme-d2">Connections</div> ${this.connections.map((x) => (html` <tf-user class="w3-bar-item" style="max-width: 100%" id=${x.id} .users=${this.users}></tf-user> `))} </div> <div class="w3-overlay" id="sidebar_overlay" @click=${this.hide_sidebar} ></div> `; } render() { let profile = this.hash.startsWith('#@') && this.hash != '#@' ? html`<tf-profile class="tf-profile" id=${this.hash.substring(1)} whoami=${this.whoami} .users=${this.users} ></tf-profile>` : undefined; let edit_profile; if ( !this.loading && this.users[this.whoami]?.name === undefined && this.hash.substring(1) != this.whoami ) { edit_profile = html` <div class="w3-panel w3-padding w3-round w3-card-4 w3-theme-l3" > βΉοΈ Follow your identity link βοΈ above to edit your profile and set your name. </div>`; } return html` ${this.render_sidebar()} <div style="margin-left: 2in; padding: 0px; top: 0; max-height: 100%; overflow: scroll" id="main" class="w3-main" > <div style="padding: 8px"> <p> ${this.hash.startsWith('##') ? html` <button class="w3-button w3-theme-d1" @click=${this.channel_toggle_subscribed} > ${this.channels.indexOf(this.hash.substring(2)) != -1 ? 'Unsubscribe from #' : 'Subscribe to #'}${this.hash.substring(2)} </button> ` : undefined} </p> <div> <div id="show_sidebar" class="w3-button w3-hide-large" @click=${this.show_sidebar} > ☰ </div> Welcome, <tf-user id=${this.whoami} .users=${this.users}></tf-user>! ${edit_profile} </div> <div> <tf-compose id="tf-compose" whoami=${this.whoami} .users=${this.users} .drafts=${this.drafts} @tf-draft=${this.draft} .channel=${this.channel()} ></tf-compose> </div> ${profile} <tf-tab-news-feed id="news" whoami=${this.whoami} .users=${this.users} .following=${this.following} hash=${this.hash} .drafts=${this.drafts} .expanded=${this.expanded} @tf-draft=${this.draft} @tf-expand=${this.on_expand} .channels_unread=${this.channels_unread} .channels_latest=${this.channels_latest} ></tf-tab-news-feed> </div> </div> `; } } customElements.define('tf-tab-news', TfTabNewsElement);