// 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) : damus.max_depth 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_events(damus, view) { return view.events .filter((ev, i) => i < 140) .map((ev) => render_timeline_event(damus, view, ev)).join("\n") } 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 === 42) 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 `
reply to ${ev.refs.reply}
` pubkeys = [replying_to.pubkey] } const names = ev.refs.pubkeys.map(pk => render_mentioned_name(pk, model.profiles[pk])).join(", ") return ` replying to ${names} ` } function render_unknown_event(damus, ev) { return "Unknown event " + ev.kind } function render_boost(damus, view, ev, opts) { //todo validate content if (!ev.json_content) return "" //const profile = model.profiles[ev.pubkey] opts.boosted = { pubkey: ev.pubkey, profile: damus.profiles[ev.pubkey] } return render_event(damus, view, ev.json_content, opts) } function render_comment_body(damus, ev, opts) { const can_delete = damus.pubkey === ev.pubkey; const bar = !can_reply(ev) || opts.nobar? "" : render_action_bar(damus, ev, can_delete) const show_media = !opts.is_composing return `
${render_replying_to(damus, ev)} ${render_boosted_by(ev, opts)}

${format_content(ev, show_media)}

${render_reactions(damus, ev)} ${bar} ` } function render_boosted_by(ev, opts) { const b = opts.boosted if (!b) { return "" } return `
Shared by ${render_name(b.pubkey, b.profile)}
` } function render_deleted_comment_body(ev, deleted) { if (deleted.content) { return `
This content was deleted with reason:
${format_content(deleted, false)}
` } return `
This content was deleted.
` } function render_event(damus, view, ev, opts={}) { if (ev.kind === 6) return render_boost(damus, view, ev, opts) if (shouldnt_render_event(damus.pubkey, view, ev, opts)) return "" view.rendered.add(ev.id) const profile = damus.profiles[ev.pubkey] const delta = time_delta(new Date().getTime(), ev.created_at*1000) const has_bot_line = opts.is_reply const reply_line_bot = (has_bot_line && render_reply_line_bot()) || "" const deleted = is_deleted(damus, ev.id) if (deleted && !opts.is_reply) return "" const replied_events = render_replied_events(damus, view, ev, opts) let name = "" if (!deleted) { name = render_name_plain(profile) } const has_top_line = replied_events !== "" const border_bottom = opts.is_composing || has_bot_line ? "" : "bottom-border"; return ` ${replied_events}
${render_reply_line_top(has_top_line)} ${deleted ? render_deleted_pfp() : render_pfp(ev.pubkey, profile)} ${reply_line_bot}
${render_name(ev.pubkey, profile)} ${delta}
${deleted ? render_deleted_comment_body(ev, deleted) : render_comment_body(damus, ev, opts)}
` } function render_react_onclick(our_pubkey, reacting_to, emoji, reactions) { const reaction = reactions[our_pubkey] if (!reaction) { return `onclick="send_reply('${emoji}', '${reacting_to}')"` } else { return `onclick="delete_post('${reaction.id}')"` } } function render_reaction_group(model, emoji, reactions, reacting_to) { const pfps = Object.keys(reactions).map((pk) => render_reaction(model, reactions[pk])) let onclick = render_react_onclick(model.pubkey, reacting_to.id, emoji, reactions) return ` ${emoji} ${pfps.join("\n")} ` } function render_reaction(model, reaction) { const profile = model.profiles[reaction.pubkey] let emoji = reaction.content[0] if (reaction.content === "+" || reaction.content === "") emoji = "❤️" return render_pfp(reaction.pubkey, profile) } function render_action_bar(damus, ev, can_delete) { let delete_html = "" if (can_delete) delete_html = ` ` const groups = get_reactions(damus, ev.id) const like = "❤️" const likes = groups[like] || {} const react_onclick = render_react_onclick(damus.pubkey, ev.id, like, likes) return `
${delete_html}
` } function render_reactions(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}
` } // Utility Methods /* render_name_plain takes in a profile and tries it's best to return a string * that is best suited for the profile. */ function render_name_plain(profile=DEFAULT_PROFILE) { if (profile.sanitized_name) return profile.sanitized_name const display_name = profile.display_name || profile.user const username = profile.name || "anon" const name = display_name || username profile.sanitized_name = sanitize(name) return profile.sanitized_name } function render_pubkey(pk) { return pk.slice(-8) } function render_username(pk, profile) { return (profile && profile.name) || render_pubkey(pk) } function render_mentioned_name(pk, profile) { return render_name(pk, profile, "@"); //return `@${render_username(pk, profile)}` } function render_name(pk, profile, prefix="") { return ` ${prefix}${render_name_plain(profile)} ` } function render_deleted_name() { return "" } function render_pfp(pk, profile) { const name = render_name_plain(profile) return `` } function render_deleted_pfp() { return `
` } function render_loading_spinner() { return `
` }