Added support for rendering mentions.
This commit is contained in:
parent
20d56bf3fe
commit
7ccb07ffc3
5 changed files with 69 additions and 12 deletions
10
js/event.js
10
js/event.js
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
45
js/ui/fmt.js
45
js/ui/fmt.js
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue