// This file contains all methods related to rendering UI elements. Rendering // is done by simple string manipulations & templates. If you need to write // loops simply write it in code and return strings. /*function render_timeline_event(damus, view, ev) { const root_id = get_thread_root_id(damus, ev.id) const max_depth = root_id ? get_thread_max_depth(damus, view, root_id) : get_default_max_depth(damus, view) if (ev.refs && ev.refs.root && view.expanded.has(ev.refs.root)) max_depth = null return render_event(damus, view, ev, {max_depth}) } */ function render_reply_line_top(has_top_line) { const classes = has_top_line ? "" : "invisible" return `
` } function render_reply_line_bot() { return `
` } function render_thread_collapsed(model, ev, opts) { if (opts.is_composing) return "" return `
Read More
` } /*function render_replied_events(damus, view, ev, opts) { if (!(ev.refs && ev.refs.reply)) return ""; const reply_ev = damus.all_events[ev.refs.reply] if (!reply_ev) return ""; opts.replies = opts.replies == null ? 1 : opts.replies + 1 if (!(opts.max_depth == null || opts.replies < opts.max_depth)) return render_thread_collapsed(damus, ev, opts); opts.is_reply = true return render_event(damus, view, reply_ev, opts) } function render_replying_to_chat(damus, ev) { const chatroom = (ev.refs.root && damus.chatrooms[ev.refs.root]) || {} const roomname = chatroom.name || ev.refs.root || "??" const pks = ev.refs.pubkeys || [] const names = pks.map(pk => render_mentioned_name(pk, damus.profiles[pk])).join(", ") const to_users = pks.length === 0 ? "" : ` to ${names}` return `
replying${to_users} in ${roomname}
` }*/ function render_replying_to(model, ev) { if (!(ev.refs && ev.refs.reply)) return ""; if (ev.kind === KIND_CHATROOM) return render_replying_to_chat(model, ev); let pubkeys = ev.refs.pubkeys || [] if (pubkeys.length === 0 && ev.refs.reply) { const replying_to = model.all_events[ev.refs.reply] if (!replying_to) return html`
reply to ${ev.refs.reply}
`; pubkeys = [replying_to.pubkey] } const names = pubkeys.map((pk) => { return render_mentioned_name(pk, model.profiles[pk]); }).join(", ") return ` replying to ${names} ` } function render_share(damus, view, ev, opts) { const shared_ev = damus.all_events[ev.refs && ev.refs.root] // If the shared event hasn't been resolved or leads to a circular event // kind we will skip out on it. if (!shared_ev || shared_ev.kind == KIND_SHARE) return ""; opts.shared = { pubkey: ev.pubkey, profile: damus.profiles[ev.pubkey] } return render_event(damus, shared_ev, opts) } function render_comment_body(model, ev, opts) { const can_delete = model.pubkey === ev.pubkey; const bar = !event_can_reply(ev) || opts.nobar ? "" : render_action_bar(model, ev, {can_delete}); // Only show media for content that is by friends. const show_media = !opts.is_composing && model.contacts.friends.has(ev.pubkey); return `
${render_replying_to(model, ev)} ${render_shared_by(ev, opts)}

${format_content(ev, show_media)}

${render_reactions(model, ev)} ${bar}` } function render_shared_by(ev, opts) { if (!opts.shared) return ""; const { profile, pubkey } = opts.shared return `
Shared by ${render_name(pubkey, profile)}
` } function render_event(model, ev, opts={}) { let { has_bot_line, has_top_line, reply_line_bot, } = opts if (ev.kind == KIND_SHARE) { return render_share(model, ev, opts); } const thread_root = (ev.refs && ev.refs.root) || ev.id; const profile = model.profiles[ev.pubkey]; const delta = fmt_since_str(new Date().getTime(), ev.created_at*1000) const border_bottom = opts.is_composing || has_bot_line ? "" : "bottom-border"; let thread_btn = ""; if (!reply_line_bot) reply_line_bot = ''; return html`
$${render_reply_line_top(has_top_line)} $${render_pfp(ev.pubkey, profile)} $${reply_line_bot}
$${render_name(ev.pubkey, profile)} ${delta}
$${render_comment_body(model, ev, opts)}
` } function render_event_nointeract(model, ev, opts={}) { const profile = model.profiles[ev.pubkey]; const delta = fmt_since_str(new Date().getTime(), ev.created_at*1000) return html`
$${render_pfp(ev.pubkey, profile)}
$${render_name(ev.pubkey, profile)} ${delta}
$${render_comment_body(model, ev, opts)}
` } function render_react_onclick(our_pubkey, reacting_to, emoji, reactions) { const reaction = reactions[our_pubkey] if (!reaction) { return html`onclick="send_reply('${emoji}', '${reacting_to}')"` } else { return html`onclick="delete_post('${reaction.id}')"` } } function render_reaction_group(model, emoji, reactions, reacting_to) { let count = 0; let str = ""; for (const k in reactions) { count++; if (count > 5) { str = `${count}`; break; } const pubkey = reactions[k].pubkey; str += render_pfp(pubkey, model.profiles[pubkey], {noclick:true}); } let onclick = render_react_onclick(model.pubkey, reacting_to.id, emoji, reactions); return html` ${emoji} $${str} `; } function render_action_bar(model, ev, opts={}) { const { pubkey } = model; let { can_delete } = opts; let delete_html = "" if (can_delete) { delete_html = html` ` } // TODO rewrite all of the toggle heart code. It's mine & I hate it. const reaction = model_get_reacts_to(model, pubkey, ev.id, R_HEART); const liked = !!reaction; const reaction_id = reaction ? reaction.id : ""; return html`
$${delete_html}
` } function render_reactions_inner(model, ev) { const groups = get_reactions(model, ev.id) let str = "" for (const emoji of Object.keys(groups)) { str += render_reaction_group(model, emoji, groups[emoji], ev) } return str; } function render_reactions(model, ev) { return html`
$${render_reactions_inner(model, ev)}
` } // Utility Methods function render_pubkey(pk) { return fmt_pubkey(pk); } function render_username(pk, profile) { return (profile && profile.name) || render_pubkey(pk) } function render_mentioned_name(pk, profile) { return render_name(pk, profile, ""); } function render_name(pk, profile, prefix="") { // Beware of whitespace. return html`${prefix}${fmt_profile_name(profile, fmt_pubkey(pk))}` } function render_pfp(pk, profile, opts={}) { const name = fmt_profile_name(profile, fmt_pubkey(pk)); let str = html`class="pfp clickable" onclick="open_profile('${pk}')"`; if (opts.noclick) str = "class='pfp'"; return html`` }