diff --git a/src/Views/page.js b/src/Views/page.js index e559f6c..5abf674 100644 --- a/src/Views/page.js +++ b/src/Views/page.js @@ -22,7 +22,9 @@ class PageView extends BaseView { requests: [ {type: 'content', fields: "*", query: `${field} = @key`}, {name: 'Pcontent', type: 'content', fields: "*", query: `id = @content.parentId`}, + {name: 'Pengagement', type: 'content_engagement', fields: "*", query: "contentId IN @content.id"}, {type: 'message', fields: "*", query: "contentId IN @content.id AND !notdeleted()", order: 'id_desc', limit: 30}, + {name: 'engagement', type: 'message_engagement', fields: "*", query: "messageId IN @message.id"}, {name: 'replies', type: 'message', fields: '*', query: "id in @message.values.replyingTo AND id NOT IN @message.id"}, {name: 'Mpinned', type: 'message', fields: "*", query: "id IN @content.values.pinned"}, {type: 'user', fields: "*", query: "id IN @content.createUserId OR id IN @message.createUserId OR id IN @message.editUserId OR id IN @Mpinned.createUserId OR id IN @Mpinned.editUserId OR id IN @replies.createUserId"}, diff --git a/src/activity.js b/src/activity.js index 64bfa80..a547993 100644 --- a/src/activity.js +++ b/src/activity.js @@ -200,7 +200,7 @@ let Act = { /// sidebar messages /// // TODO: ensure that these are displayed BEFORE any websocket new messages - Sidebar.display_messages(objects.message, true) + do_when_ready(_=>Sidebar.display_messages(objects.message, true)) /// activity tab /// for (let act of objects.activity) diff --git a/src/entity.js b/src/entity.js index 9328fca..2a83266 100644 --- a/src/entity.js +++ b/src/entity.js @@ -115,6 +115,13 @@ for (let name in ABOUT.details.types) { value: Object.freeze([]), writable: true, } + proto_desc.ReactedWith = { + value: Object.freeze({}), + writable: true, + } + // TODO: one thing to ask -- if i edit on a "replied" value, will LinkedUsers populate? + // why is ReactedWith not being set on messages in display_live? + // why is ReactedWith not set in the message cache?? is there a message cache? } if (name == 'watch') { // FIXME: this could possibly happen before it's defined @@ -253,7 +260,7 @@ const Entity = NAMESPACE({ }, // link user data with comments - link_comments({message, user, content, replies}) { + link_comments({message, user, content, replies, engagement}) { replies?.forEach((r) => { r.Author = new Author(r, user[~r.createUserId], content?.[~r.contentId]) }) @@ -265,6 +272,13 @@ const Entity = NAMESPACE({ m.values.replyingTo ? replies?.[~m.values.replyingTo] : null ) m.LinkedUsers = m.uidsInText.map(uid => user[~uid]).filter(v => v) + if (Object.keys(m.engagement).length) { + m.ReactedWith = {} + for (const type of Object.keys(m.engagement)) { + let r = engagement?.find(e => e.messageId == m.id && e.type == type); + if (r) m.ReactedWith[type] = r + } + } } }, diff --git a/src/messages.js b/src/messages.js index 1fb1d53..41539be 100644 --- a/src/messages.js +++ b/src/messages.js @@ -113,14 +113,50 @@ class MessageList { // return: Element draw_part(msg) { let e = MessageList.part_template() + let markup = e.firstElementChild e.dataset.id = msg.id if (msg.edited) - e.className += " edited" + e.classList.add('edited') + if (Object.keys(msg.engagement).length) { + e.classList.add('reacted') + let rl = MessageList.react_list() + for (const [react, count] of Object.entries(msg.engagement.reaction)) { + let r = MessageList.react() + let [rv, rc] = r.children + + // for (let i = 0; i < count; i++) { + // let rvi = document.createElement('span') + // rvi.textContent = react + // rv.appendChild(rvi) + // } + + rv.textContent = react + rc.textContent = count.toString() + + // if (count == 1) r.replaceWith(rv) + + let reactedWith = msg.ReactedWith.reaction?.engagement == react; + if (reactedWith) + r.classList.add('reacted-with') + + r.onclick = (ev) => { + const b = ev.currentTarget + let addReact = !reactedWith + let what = addReact ? 'setengagement' : 'deleteengagement' + let req = `Shortcuts/message/${msg.id}/${what}/reaction` + Array.from(rl.children).forEach(el => el.disabled = true) + Req.request(req, null, addReact ? react : null) + } + + rl.appendChild(r) + } + e.appendChild(rl) + } if (msg.module !== null && msg.uidsInText.length > 0) msg.LinkedUsers.forEach(user => { msg.text = msg.text.replace(new RegExp(`%${user.id}%`, "g"), user.username) }) - Markup.convert_lang(msg.text, msg.values.m, e.firstElementChild, {intersection_observer: View.observer}) + Markup.convert_lang(msg.text, msg.values.m, markup, {intersection_observer: View.observer}) if (msg.values.replyingTo) { const { replyingTo } = msg.values const replyBlock = MessageList.reply_template() @@ -346,8 +382,9 @@ class MessageList { values: {last: id, pid: this.pid}, requests: [ {type:'message', fields:'*', query, order, limit:amount}, + {name:'engagement', type:'message_engagement', fields:'*', query:"messageId in @message.id"}, {name:'replies', type:'message', fields:'*', query:'id in @message.values.replyingTo'}, - {type:'user', fields:'*', query:"id in @message.createUserId OR id IN @replies.createUserId"}, + {type:'user', fields:'*', query:"id in @message.createUserId OR id IN @replies.createUserId"} ], }, resp=>{ let first = true @@ -473,6 +510,8 @@ MessageList.reply_template = 𐀶` ` +MessageList.react_list = 𐀶`
` +MessageList.react = 𐀶`