Added support for rendering mentions.

This commit is contained in:
Thomas Mathews 2023-01-16 19:52:41 -08:00
parent 20d56bf3fe
commit 7ccb07ffc3
5 changed files with 69 additions and 12 deletions

View file

@ -25,8 +25,8 @@ function event_tags_pubkey(ev, pubkey) {
return false
}
function event_get_pubkeys(ev) {
const keys = [ev.pubkey];
function event_get_tagged_pubkeys(ev) {
const keys = [];
for (const tag of ev.tags) {
if (tag.length >= 2 && tag[0] == "p")
keys.push(tag[1]);
@ -34,6 +34,12 @@ function event_get_pubkeys(ev) {
return keys;
}
function event_get_pubkeys(ev) {
const keys = event_get_tagged_pubkeys(ev);
keys.splice(0, 0, ev.pubkey);
return keys;
}
function event_calculate_pow(ev) {
const id_bits = leading_zero_bits(ev.id)
for (const tag of ev.tags) {

View file

@ -72,6 +72,7 @@ async function webapp_init() {
// WARNING Order Matters!
init_message_textareas();
init_timeline(model);
init_my_pfp(model);
init_postbox(model);
init_profile();

View file

@ -24,7 +24,7 @@ function linkify(text="", show_media=false) {
})
}
function format_content(ev, show_media) {
function format_content(model, ev, show_media) {
if (ev.kind === KIND_REACTION) {
if (ev.content === "" || ev.content === "+")
return "❤️"
@ -32,7 +32,8 @@ function format_content(ev, show_media) {
}
const content = (ev.kind == KIND_DM ? ev.decrypted || ev.content : ev.content)
.trim();
const body = fmt_body(content, show_media);
const body = fmt_mentions(model, fmt_body(content, show_media),
event_get_tagged_pubkeys(ev));
let cw = get_content_warning(ev.tags)
if (cw !== null) {
let cwHTML = "Content Warning"
@ -50,6 +51,46 @@ function format_content(ev, show_media) {
return body;
}
function fmt_mentions(model, str, pubkeys) {
var buf = "";
for (var i = 0; i < str.length; i++) {
let c = str.charAt(i);
let peek = str.charAt(i+1);
if (!(c == "#" && peek == "[")) {
buf += c;
continue;
}
const start = i;
i += 2;
let x = "";
for(;;) {
c = str.charAt(i);
if (c >= '0' && c <= '9') {
x += c;
i++;
} else if (c == ']') {
break;
} else {
buf += x;
x = "";
break;
}
}
if (x == "")
continue;
// Specification says it's 0-based, but everyone is doing 1-base
let pubkey = pubkeys[parseInt(x)];
if (!pubkey) {
buf += "(Invalid User Mentioned)"
continue;
}
let profile = model_get_profile(model, pubkey);
buf += `<span class="username clickable" data-pubkey="${pubkey}">
${fmt_name(profile)}</span>`;
}
return buf;
}
/* fmt_body will parse images, blockquotes, and sanitize the content.
*/
function fmt_body(content, show_media) {

View file

@ -94,7 +94,7 @@ function render_dm(model, ev, opts) {
return html`<div id="ev${ev.id}" class="${classes}">
<div class="wrap">
<div class="body">
<p>$${format_content(ev, show_media)}</p>
<p>$${format_content(model, ev, show_media)}</p>
</div>
<div class="timestamp" data-timestamp="${ev.created_at}">${delta}</div>
</div>
@ -109,7 +109,7 @@ function event_shows_media(model, ev, mode) {
function rerender_dm(model, ev, el) {
let show_media = event_shows_media(model, ev, model.embeds);
find_node(".body > p", el).innerHTML = format_content(ev, show_media);
find_node(".body > p", el).innerHTML = format_content(model, ev, show_media);
}
function render_event_nointeract(model, ev, opts={}) {
@ -145,7 +145,7 @@ function render_event_body(model, ev, opts) {
let str = "<div>";
str += shared ? render_shared_by(ev, opts) : render_replying_to(model, ev);
str += `</div><p>
${format_content(ev, show_media)}
${format_content(model, ev, show_media)}
</p>`;
str += render_reactions(model, ev);
str += opts.nobar || ev.kind == KIND_DM ? "" :
@ -258,8 +258,7 @@ function render_pubkey(pk) {
return fmt_pubkey(pk);
}
function render_username(pk, profile)
{
function render_username(pk, profile) {
return (profile && profile.name) || render_pubkey(pk)
}
@ -269,9 +268,9 @@ function render_mentioned_name(pk, profile) {
function render_name(pk, profile, prefix="") {
// Beware of whitespace.
return html`<span>${prefix}<span class="username clickable" data-pubkey="${pk}"
onclick="open_profile('${pk}')"
> ${fmt_profile_name(profile, fmt_pubkey(pk))}</span></span>`
return html`<span>${prefix}<span class="username clickable"
role="open-profile" data-pubkey="${pk}">
${fmt_profile_name(profile, fmt_pubkey(pk))}</span></span>`
}
function render_profile_img(profile, noclick=false) {

View file

@ -468,6 +468,16 @@ function html2el(html) {
return div.firstChild;
}
function init_timeline(model) {
const el = view_get_timeline_el();
el.addEventListener("click", onclick_timeline);
}
function onclick_timeline(ev) {
if (ev.target.matches(".username[data-pubkey]")) {
open_profile(ev.target.dataset.pubkey);
}
}
function init_my_pfp(model) {
find_nodes(`img[role='my-pfp']`).forEach((el)=> {
el.dataset.pubkey = model.pubkey;