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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
function event_get_pubkeys(ev) {
|
function event_get_tagged_pubkeys(ev) {
|
||||||
const keys = [ev.pubkey];
|
const keys = [];
|
||||||
for (const tag of ev.tags) {
|
for (const tag of ev.tags) {
|
||||||
if (tag.length >= 2 && tag[0] == "p")
|
if (tag.length >= 2 && tag[0] == "p")
|
||||||
keys.push(tag[1]);
|
keys.push(tag[1]);
|
||||||
|
@ -34,6 +34,12 @@ function event_get_pubkeys(ev) {
|
||||||
return keys;
|
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) {
|
function event_calculate_pow(ev) {
|
||||||
const id_bits = leading_zero_bits(ev.id)
|
const id_bits = leading_zero_bits(ev.id)
|
||||||
for (const tag of ev.tags) {
|
for (const tag of ev.tags) {
|
||||||
|
|
|
@ -72,6 +72,7 @@ async function webapp_init() {
|
||||||
|
|
||||||
// WARNING Order Matters!
|
// WARNING Order Matters!
|
||||||
init_message_textareas();
|
init_message_textareas();
|
||||||
|
init_timeline(model);
|
||||||
init_my_pfp(model);
|
init_my_pfp(model);
|
||||||
init_postbox(model);
|
init_postbox(model);
|
||||||
init_profile();
|
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.kind === KIND_REACTION) {
|
||||||
if (ev.content === "" || ev.content === "+")
|
if (ev.content === "" || ev.content === "+")
|
||||||
return "❤️"
|
return "❤️"
|
||||||
|
@ -32,7 +32,8 @@ function format_content(ev, show_media) {
|
||||||
}
|
}
|
||||||
const content = (ev.kind == KIND_DM ? ev.decrypted || ev.content : ev.content)
|
const content = (ev.kind == KIND_DM ? ev.decrypted || ev.content : ev.content)
|
||||||
.trim();
|
.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)
|
let cw = get_content_warning(ev.tags)
|
||||||
if (cw !== null) {
|
if (cw !== null) {
|
||||||
let cwHTML = "Content Warning"
|
let cwHTML = "Content Warning"
|
||||||
|
@ -50,6 +51,46 @@ function format_content(ev, show_media) {
|
||||||
return body;
|
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.
|
/* fmt_body will parse images, blockquotes, and sanitize the content.
|
||||||
*/
|
*/
|
||||||
function fmt_body(content, show_media) {
|
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}">
|
return html`<div id="ev${ev.id}" class="${classes}">
|
||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<p>$${format_content(ev, show_media)}</p>
|
<p>$${format_content(model, ev, show_media)}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="timestamp" data-timestamp="${ev.created_at}">${delta}</div>
|
<div class="timestamp" data-timestamp="${ev.created_at}">${delta}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,7 +109,7 @@ function event_shows_media(model, ev, mode) {
|
||||||
|
|
||||||
function rerender_dm(model, ev, el) {
|
function rerender_dm(model, ev, el) {
|
||||||
let show_media = event_shows_media(model, ev, model.embeds);
|
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={}) {
|
function render_event_nointeract(model, ev, opts={}) {
|
||||||
|
@ -145,7 +145,7 @@ function render_event_body(model, ev, opts) {
|
||||||
let str = "<div>";
|
let str = "<div>";
|
||||||
str += shared ? render_shared_by(ev, opts) : render_replying_to(model, ev);
|
str += shared ? render_shared_by(ev, opts) : render_replying_to(model, ev);
|
||||||
str += `</div><p>
|
str += `</div><p>
|
||||||
${format_content(ev, show_media)}
|
${format_content(model, ev, show_media)}
|
||||||
</p>`;
|
</p>`;
|
||||||
str += render_reactions(model, ev);
|
str += render_reactions(model, ev);
|
||||||
str += opts.nobar || ev.kind == KIND_DM ? "" :
|
str += opts.nobar || ev.kind == KIND_DM ? "" :
|
||||||
|
@ -258,8 +258,7 @@ function render_pubkey(pk) {
|
||||||
return fmt_pubkey(pk);
|
return fmt_pubkey(pk);
|
||||||
}
|
}
|
||||||
|
|
||||||
function render_username(pk, profile)
|
function render_username(pk, profile) {
|
||||||
{
|
|
||||||
return (profile && profile.name) || render_pubkey(pk)
|
return (profile && profile.name) || render_pubkey(pk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,9 +268,9 @@ function render_mentioned_name(pk, profile) {
|
||||||
|
|
||||||
function render_name(pk, profile, prefix="") {
|
function render_name(pk, profile, prefix="") {
|
||||||
// Beware of whitespace.
|
// Beware of whitespace.
|
||||||
return html`<span>${prefix}<span class="username clickable" data-pubkey="${pk}"
|
return html`<span>${prefix}<span class="username clickable"
|
||||||
onclick="open_profile('${pk}')"
|
role="open-profile" data-pubkey="${pk}">
|
||||||
> ${fmt_profile_name(profile, fmt_pubkey(pk))}</span></span>`
|
${fmt_profile_name(profile, fmt_pubkey(pk))}</span></span>`
|
||||||
}
|
}
|
||||||
|
|
||||||
function render_profile_img(profile, noclick=false) {
|
function render_profile_img(profile, noclick=false) {
|
||||||
|
|
|
@ -468,6 +468,16 @@ function html2el(html) {
|
||||||
return div.firstChild;
|
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) {
|
function init_my_pfp(model) {
|
||||||
find_nodes(`img[role='my-pfp']`).forEach((el)=> {
|
find_nodes(`img[role='my-pfp']`).forEach((el)=> {
|
||||||
el.dataset.pubkey = model.pubkey;
|
el.dataset.pubkey = model.pubkey;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue