
This feature involved a lot of refactoring in order to get working correctly. I wanted to continue using the timeline view for chats thus I used alternative styling & structure for DM event kinds. This worked create since the elements map does not care. There is some queing that has to be done to decrypt message content thus I allow viewing messages even if they haven't been decrypted yet. I think this is good for transparency since you understand what is and is not decrypted. I do think that the UX could improve, because even tho it is fast, it's flashes on new messages. I did not implement saving of latest messages. I will do this later, but this feature is big enough to merge as is: an alpha state that works. I further abstracted profile & name updating to work in a more global manner. Additionally I rewrote code that had attribute scripts to use addEventListener instead. This is needed to happen anyways for security and made the codebase easier to manage.
81 lines
2.4 KiB
JavaScript
81 lines
2.4 KiB
JavaScript
function view_dm_update(model) {
|
|
const el = find_node("#dms");
|
|
const order = [];
|
|
model.dms.forEach((dm, pubkey, m) => {
|
|
if (!dm.events.length)
|
|
return;
|
|
const i = arr_bsearch_insert(order, dm, dm_cmp);
|
|
order.splice(i, 0, dm);
|
|
if (!dm.needs_redraw)
|
|
return;
|
|
let gel = find_node(`[data-pubkey='${pubkey}']`, el);
|
|
if (!gel) {
|
|
gel = new_el_dmgroup(model, dm);
|
|
gel.addEventListener("click", onclick_dm);
|
|
el.appendChild(gel);
|
|
}
|
|
update_el_dmgroup(model, dm, gel);
|
|
dm.needs_redraw = false;
|
|
});
|
|
|
|
// I'm not sure what is faster, doing a frag update all at once OR just
|
|
// updating individual positions. If they all update it's slower, but the
|
|
// chances of them all updating is is small and only garuenteed when it
|
|
// draws the first time.
|
|
//const frag = new DocumentFragment();
|
|
for (let i = 0; i < order.length; i++) {
|
|
let dm = order[i];
|
|
let xel = el.children[i];
|
|
if (dm.pubkey == xel.dataset.pubkey)
|
|
continue;
|
|
let gel = find_node(`[data-pubkey='${order[i].pubkey}']`, el);
|
|
el.insertBefore(gel, xel);
|
|
//frag.appendChild(gel);
|
|
}
|
|
//el.appendChild(frag);
|
|
}
|
|
|
|
function dm_cmp(a, b) {
|
|
const x = a.events[0].created_at;
|
|
const y = b.events[0].created_at;
|
|
if (x > y)
|
|
return -1;
|
|
if (x < y)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
function update_el_dmgroup(model, dm, el) {
|
|
const ev = dm.events[0];
|
|
const profile = model_get_profile(model, dm.pubkey);
|
|
const message = ev.decrypted || ev.content || "No Message.";
|
|
const time = fmt_datetime(new Date(ev.created_at * 1000));
|
|
const cel = find_node(".count", el)
|
|
cel.innerText = dm.new_count;
|
|
cel.classList.toggle("active", dm.new_count > 0);
|
|
find_node(".time", el).innerText = time;
|
|
find_node(".message", el).innerText = message;
|
|
find_node(".username", el).innerText = fmt_name(profile);
|
|
}
|
|
|
|
function new_el_dmgroup(model, dm) {
|
|
const profile = model_get_profile(model, dm.pubkey);
|
|
return html2el(`<div class="dm-group bottom-border clickable" data-pubkey="${dm.pubkey}">
|
|
<div>${render_profile_img(profile, true)}</div>
|
|
<div class="content">
|
|
<div class="count"></div>
|
|
<label class="username" data-pubkey="${dm.pubkey}"></label>
|
|
<p class="message"></p>
|
|
<label class="time"></label>
|
|
</div>
|
|
</div>`);
|
|
}
|
|
|
|
function onclick_dm(ev) {
|
|
const el = find_parent(ev.target, "[data-pubkey]");
|
|
if (!el || !el.dataset.pubkey) {
|
|
log_error("did not find dm pubkey");
|
|
return;
|
|
}
|
|
view_timeline_apply_mode(DAMUS, VM_DM_THREAD, {pubkey: el.dataset.pubkey});
|
|
}
|