From 183094ad63ce96eff59c0954a33a30fc1c8b21bc Mon Sep 17 00:00:00 2001 From: Chupalika Date: Sun, 28 Mar 2021 08:28:11 -0400 Subject: [PATCH] Track and view replies (#133) * Track and view replies * Tweaks to reply saving (PR #133) Co-authored-by: chylex --- reserve.txt | 6 ++- src/tracker/savefile.js | 7 +++- src/viewer/scripts/discord.js | 77 ++++++++++++++++++++-------------- src/viewer/scripts/state.js | 17 ++++++-- src/viewer/styles/messages.css | 62 +++++++++++++++++++++++++++ 5 files changed, 133 insertions(+), 36 deletions(-) diff --git a/reserve.txt b/reserve.txt index 1ebd734..8b7e414 100644 --- a/reserve.txt +++ b/reserve.txt @@ -28,6 +28,7 @@ e a t d +r te tag avatar @@ -50,10 +51,13 @@ embeds attachments title description +reply toDate memoizedProps props children channel messages -msSaveBlob \ No newline at end of file +msSaveBlob +messageReference +message_id diff --git a/src/tracker/savefile.js b/src/tracker/savefile.js index 8c0024f..7d4634f 100644 --- a/src/tracker/savefile.js +++ b/src/tracker/savefile.js @@ -56,7 +56,8 @@ * { * url: * }, ... - * ] + * ], + * r: // only present if referencing another message (reply) * }, ... * }, ... * } @@ -234,6 +235,10 @@ class SAVEFILE{ })); } + if (discordMessage.messageReference !== null){ + obj.r = discordMessage.messageReference.message_id; + } + return obj; } diff --git a/src/viewer/scripts/discord.js b/src/viewer/scripts/discord.js index f98e3a3..311c88b 100644 --- a/src/viewer/scripts/discord.js +++ b/src/viewer/scripts/discord.js @@ -41,6 +41,36 @@ var DISCORD = (function(){ var templateEmbedRichUnsupported; var templateEmbedDownload; + var processMessageContents = function(contents){ + var processed = DOM.escapeHTML(contents.replace(REGEX.formatUrlNoEmbed, "$1")); + + if (STATE.settings.enableFormatting){ + var escapeHtmlMatch = (full, match) => "&#"+match.charCodeAt(0)+";"; + + processed = processed + .replace(REGEX.specialEscapedBacktick, "`") + .replace(REGEX.formatCodeBlock, (full, ignore, match) => ""+match.replace(REGEX.specialUnescaped, escapeHtmlMatch)+"") + .replace(REGEX.formatCodeInline, (full, ignore, match) => ""+match.replace(REGEX.specialUnescaped, escapeHtmlMatch)+"") + .replace(REGEX.specialEscapedSingle, escapeHtmlMatch) + .replace(REGEX.specialEscapedDouble, full => full.replace(/\\/g, "").replace(/(.)/g, escapeHtmlMatch)) + .replace(REGEX.formatBold, "$1") + .replace(REGEX.formatItalic, (full, pre, match) => pre === '\\' ? full : (pre || "")+""+match+"") + .replace(REGEX.formatUnderline, "$1") + .replace(REGEX.formatStrike, "$1"); + } + + var animatedEmojiExtension = STATE.settings.enableAnimatedEmoji ? "gif" : "png"; + + processed = processed + .replace(REGEX.formatUrl, "$1") + .replace(REGEX.mentionChannel, (full, match) => "#"+STATE.getChannelName(match)+"") + .replace(REGEX.mentionUser, (full, match) => "@"+STATE.getUserName(match)+"") + .replace(REGEX.customEmojiStatic, ":$1:") + .replace(REGEX.customEmojiAnimated, ":$1:"); + + return "

"+processed+"

"; + }; + return { setup: function(){ templateChannelServer = new TEMPLATE([ @@ -59,18 +89,22 @@ var DISCORD = (function(){ templateMessageNoAvatar = new TEMPLATE([ "
", + "
{reply}
", "

{user.name}{timestamp}{edit}{jump}

", "
{contents}{embeds}{attachments}
", "
" ].join("")); templateMessageWithAvatar = new TEMPLATE([ + "
", + "
{reply}
", "
", "
{avatar}
", "
", "

{user.name}{timestamp}{edit}{jump}

", "
{contents}{embeds}{attachments}
", "
", + "
", "
" ].join("")); @@ -128,37 +162,7 @@ var DISCORD = (function(){ return getHumanReadableTime(value); } else if (property === "contents"){ - if (value == null || value.length === 0){ - return ""; - } - - var processed = DOM.escapeHTML(value.replace(REGEX.formatUrlNoEmbed, "$1")); - - if (STATE.settings.enableFormatting){ - var escapeHtmlMatch = (full, match) => "&#"+match.charCodeAt(0)+";"; - - processed = processed - .replace(REGEX.specialEscapedBacktick, "`") - .replace(REGEX.formatCodeBlock, (full, ignore, match) => ""+match.replace(REGEX.specialUnescaped, escapeHtmlMatch)+"") - .replace(REGEX.formatCodeInline, (full, ignore, match) => ""+match.replace(REGEX.specialUnescaped, escapeHtmlMatch)+"") - .replace(REGEX.specialEscapedSingle, escapeHtmlMatch) - .replace(REGEX.specialEscapedDouble, full => full.replace(/\\/g, "").replace(/(.)/g, escapeHtmlMatch)) - .replace(REGEX.formatBold, "$1") - .replace(REGEX.formatItalic, (full, pre, match) => pre === '\\' ? full : (pre || "")+""+match+"") - .replace(REGEX.formatUnderline, "$1") - .replace(REGEX.formatStrike, "$1"); - } - - var animatedEmojiExtension = STATE.settings.enableAnimatedEmoji ? "gif" : "png"; - - processed = processed - .replace(REGEX.formatUrl, "$1") - .replace(REGEX.mentionChannel, (full, match) => "#"+STATE.getChannelName(match)+"") - .replace(REGEX.mentionUser, (full, match) => "@"+STATE.getUserName(match)+"") - .replace(REGEX.customEmojiStatic, ":$1:") - .replace(REGEX.customEmojiAnimated, ":$1:"); - - return "

"+processed+"

"; + return value == null || value.length === 0 ? "" : processMessageContents(value); } else if (property === "embeds"){ if (!value){ @@ -200,6 +204,17 @@ var DISCORD = (function(){ else if (property === "jump"){ return STATE.hasActiveFilter ? "Jump to message" : ""; } + else if (property === "reply"){ + if (value === null) { + return ""; + } + + var user = "" + value.user.name + ""; + var avatar = value.avatar ? "" + templateUserAvatar.apply(value.avatar) + "" : ""; + var contents = value.contents ? "" + processMessageContents(value.contents) + "" : ""; + + return "Jump to reply" + avatar + user + "" + contents; + } }); } }; diff --git a/src/viewer/scripts/state.js b/src/viewer/scripts/state.js index 88bf46b..0d68000 100644 --- a/src/viewer/scripts/state.js +++ b/src/viewer/scripts/state.js @@ -37,7 +37,7 @@ var STATE = (function(){ ROOT.onChannelsRefreshed = function(callback){ eventOnChannelsRefreshed = callback; }; - + ROOT.onMessagesRefreshed = function(callback){ eventOnMessagesRefreshed = callback; }; @@ -147,7 +147,17 @@ var STATE = (function(){ var message = messages[key]; var user = FILE.getUser(message.u); var avatar = user.avatar ? { id: FILE.getUserId(message.u), path: user.avatar } : null; - + + var reply = ("r" in message && message.r in messages) ? messages[message.r] : null; + var replyUser = reply ? FILE.getUser(reply.u) : null; + var replyAvatar = replyUser && replyUser.avatar ? { id: FILE.getUserId(reply.u), path: replyUser.avatar } : null; + var replyObj = reply ? { + "id": message.r, + "user": replyUser, + "avatar": replyAvatar, + "contents": reply.m + } : null; + return { "user": user, "avatar": avatar, @@ -156,7 +166,8 @@ var STATE = (function(){ "embeds": message.e, "attachments": message.a, "edit": ("te" in message) ? message.te : (message.f & 1) === 1, - "jump": key + "jump": key, + "reply": replyObj }; }); }; diff --git a/src/viewer/styles/messages.css b/src/viewer/styles/messages.css index 7697aa7..f18bdea 100644 --- a/src/viewer/styles/messages.css +++ b/src/viewer/styles/messages.css @@ -154,3 +154,65 @@ vertical-align: -30%; object-fit: contain; } + +.reply-message { + margin: 0 0 -2px 52px; + display: flex; + align-items: baseline; + flex-wrap: wrap; + line-height: 120%; + white-space: nowrap; +} + +.reply-message .jump { + color: rgba(255, 255, 255, 0.4); + font-size: 12px; + text-underline-offset: 1px; + margin-right: 7px; +} + +.reply-message .emoji { + width: 16px; + height: 16px; + vertical-align: -20%; + object-fit: contain; +} + +.reply-message .user { + margin-right: 5px; +} + +.reply-avatar { + margin-right: 4px; +} + +.reply-avatar img { + width: 16px; + border-radius: 50%; + vertical-align: middle; +} + +.reply-username { + color: #FFF; + font-size: 12px; + font-weight: 600; + letter-spacing: 0; +} + +.reply-contents { + display: inline-block; + color: rgba(255, 255, 255, 0.7); + font-size: 12px; + max-width: calc(80%); +} + +.reply-contents p { + margin: 0; + overflow: hidden; + text-overflow: ellipsis; +} + +.reply-contents a { + color: #0096CF; + text-decoration: none; +}