diff --git a/reserve.txt b/reserve.txt index 6b49e19..535e0e1 100644 --- a/reserve.txt +++ b/reserve.txt @@ -10,6 +10,8 @@ enableFormatting _enableFormatting enableAnimatedEmoji _enableAnimatedEmoji +enableUserAvatars +_enableUserAvatars DHT_LOADED DHT_EMBEDDED meta @@ -28,9 +30,13 @@ t d te tag +avatar author type state +position +topic +nsfw id username bot diff --git a/src/tracker/discord.js b/src/tracker/discord.js index 71a693d..bacfe61 100644 --- a/src/tracker/discord.js +++ b/src/tracker/discord.js @@ -129,7 +129,8 @@ var DISCORD = (function(){ "server": name, "channel": name, "id": link, - "type": (icon && (icon.src.includes("/channel-icons/") || icon.src.includes("/assets/"))) ? "GROUP" : "DM" + "type": (icon && (icon.src.includes("/channel-icons/") || icon.src.includes("/assets/"))) ? "GROUP" : "DM", + "extra": {} }; } else{ @@ -152,7 +153,12 @@ var DISCORD = (function(){ "server": channelListEle.querySelector("header > h1").innerText, "channel": channelObj.name, "id": channelObj.id, - "type": "SERVER" + "type": "SERVER", + "extra": { + "position": channelObj.position, + "topic": channelObj.topic, + "nsfw": channelObj.nsfw + } }; } diff --git a/src/tracker/savefile.js b/src/tracker/savefile.js index 6cec9d3..4ebc133 100644 --- a/src/tracker/savefile.js +++ b/src/tracker/savefile.js @@ -7,6 +7,7 @@ * users: { * : { * name: , + * avatar: , * tag: // only present if not a bot * }, ... * }, @@ -27,7 +28,10 @@ * channels: { * : { * server: , - * name: + * name: , + * position: , // only present if server type == SERVER + * topic: , // only present if server type == SERVER + * nsfw: // only present if server type == SERVER * }, ... * } * }, @@ -103,7 +107,7 @@ class SAVEFILE{ return parsedObj && typeof parsedObj.meta === "object" && typeof parsedObj.data === "object"; } - findOrRegisterUser(userId, userName, userDiscriminator){ + findOrRegisterUser(userId, userName, userDiscriminator, userAvatar){ if (!(userId in this.meta.users)){ this.meta.users[userId] = { "name": userName @@ -113,6 +117,10 @@ class SAVEFILE{ this.meta.users[userId].tag = userDiscriminator; } + if (userAvatar){ + this.meta.users[userId].avatar = userAvatar; + } + this.meta.userindex.push(userId); return this.tmp.userlookup[userId] = this.meta.userindex.length-1; } @@ -140,7 +148,7 @@ class SAVEFILE{ } } - tryRegisterChannel(serverIndex, channelId, channelName){ + tryRegisterChannel(serverIndex, channelId, channelName, extraInfo){ if (!this.meta.servers[serverIndex]){ return undefined; } @@ -153,6 +161,18 @@ class SAVEFILE{ "name": channelName }; + if (extraInfo.position){ + this.meta.channels[channelId].position = extraInfo.position; + } + + if (extraInfo.topic){ + this.meta.channels[channelId].topic = extraInfo.topic; + } + + if (extraInfo.nsfw){ + this.meta.channels[channelId].nsfw = extraInfo.nsfw; + } + this.tmp.channelkeys.add(channelId); return true; } @@ -171,7 +191,7 @@ class SAVEFILE{ var author = discordMessage.author; var obj = { - u: this.findOrRegisterUser(author.id, author.username, author.bot ? null : author.discriminator), + u: this.findOrRegisterUser(author.id, author.username, author.bot ? null : author.discriminator, author.avatar), t: discordMessage.timestamp.toDate().getTime() }; @@ -244,12 +264,13 @@ class SAVEFILE{ for(var userId in obj.meta.users){ var oldUser = obj.meta.users[userId]; - userMap[obj.meta.userindex.findIndex(id => id == userId)] = this.findOrRegisterUser(userId, oldUser.name, oldUser.tag); + userMap[obj.meta.userindex.findIndex(id => id == userId)] = this.findOrRegisterUser(userId, oldUser.name, oldUser.tag, oldUser.avatar); } for(var channelId in obj.meta.channels){ var oldServer = obj.meta.servers[obj.meta.channels[channelId].server]; - this.tryRegisterChannel(this.findOrRegisterServer(oldServer.name, oldServer.type), channelId, obj.meta.channels[channelId].name); + var oldChannel = obj.meta.channels[channelId]; + this.tryRegisterChannel(this.findOrRegisterServer(oldServer.name, oldServer.type), channelId, oldChannel.name, oldChannel /* filtered later */); } for(var channelId in obj.data){ diff --git a/src/tracker/state.js b/src/tracker/state.js index 60f06c6..46cbca2 100644 --- a/src/tracker/state.js +++ b/src/tracker/state.js @@ -79,10 +79,10 @@ var STATE = (function(){ /* * Registers a Discord server and channel. */ - addDiscordChannel(serverName, serverType, channelId, channelName){ + addDiscordChannel(serverName, serverType, channelId, channelName, extraInfo){ var serverIndex = this.getSavefile().findOrRegisterServer(serverName, serverType); - if (this.getSavefile().tryRegisterChannel(serverIndex, channelId, channelName) === true){ + if (this.getSavefile().tryRegisterChannel(serverIndex, channelId, channelName, extraInfo) === true){ triggerStateChanged("data", "channel"); } } diff --git a/src/tracker/Σ.js b/src/tracker/Σ.js index 2ef31e2..85d1fec 100644 --- a/src/tracker/Σ.js +++ b/src/tracker/Σ.js @@ -38,7 +38,7 @@ DISCORD.setupMessageUpdateCallback(hasMoreMessages => { return; } - STATE.addDiscordChannel(info.server, info.type, info.id, info.channel); + STATE.addDiscordChannel(info.server, info.type, info.id, info.channel, info.extra); let messages = DISCORD.getMessages(); @@ -99,7 +99,7 @@ STATE.onStateChanged((type, enabled) => { let messages = DISCORD.getMessages(); if (messages != null){ - STATE.addDiscordChannel(info.server, info.type, info.id, info.channel); + STATE.addDiscordChannel(info.server, info.type, info.id, info.channel, info.extra); STATE.addDiscordMessages(info.id, messages); } else{ diff --git a/src/viewer/scripts/discord.js b/src/viewer/scripts/discord.js index 7c065d9..f7e6424 100644 --- a/src/viewer/scripts/discord.js +++ b/src/viewer/scripts/discord.js @@ -32,7 +32,9 @@ var DISCORD = (function(){ var templateChannelServer; var templateChannelPrivate; - var templateMessage; + var templateMessageNoAvatar; + var templateMessageWithAvatar; + var templateUserAvatar; var templateEmbedImage; var templateEmbedRich; var templateEmbedRichNoDescription; @@ -43,25 +45,39 @@ var DISCORD = (function(){ setup: function(){ templateChannelServer = new TEMPLATE([ "
", - "
#{name}{msgcount}
", + "
#{name}{nsfw}{msgcount}
", "{server.name} ({server.type})", "
" ].join("")); templateChannelPrivate = new TEMPLATE([ "
", - "
{name}{msgcount}
", + "
{name}{msgcount}
", "({server.type})", "
" ].join("")); - templateMessage = new TEMPLATE([ + templateMessageNoAvatar = new TEMPLATE([ "
", - "

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

", + "

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

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

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

", + "
{contents}{embeds}{attachments}
", + "
", + "
" + ].join("")); + + templateUserAvatar = new TEMPLATE([ + "" + ].join("")); + templateEmbedImage = new TEMPLATE([ "(image attachment not found)
" ].join("")); @@ -94,12 +110,18 @@ var DISCORD = (function(){ case "DM": return "user"; } } + else if (property === "nsfw"){ + return value ? "NSFW" : ""; + } }); }, getMessageHTML: function(message){ - return templateMessage.apply(message, (property, value) => { - if (property === "timestamp"){ + return (STATE.settings.enableUserAvatars ? templateMessageWithAvatar : templateMessageNoAvatar).apply(message, (property, value) => { + if (property === "avatar"){ + return value ? templateUserAvatar.apply(value) : ""; + } + else if (property === "timestamp"){ return getHumanReadableTime(value); } else if (property === "contents"){ @@ -129,7 +151,7 @@ var DISCORD = (function(){ processed = processed .replace(REGEX.formatUrl, "$1") .replace(REGEX.mentionChannel, (full, match) => "#"+STATE.getChannelName(match)+"") - .replace(REGEX.mentionUser, (full, match) => "@"+STATE.getUserName(match)+"") + .replace(REGEX.mentionUser, (full, match) => "@"+STATE.getUserName(match)+"") .replace(REGEX.customEmojiStatic, ":$1:") .replace(REGEX.customEmojiAnimated, ":$1:"); diff --git a/src/viewer/scripts/gui.js b/src/viewer/scripts/gui.js index 3d2d19e..392c7c5 100644 --- a/src/viewer/scripts/gui.js +++ b/src/viewer/scripts/gui.js @@ -38,6 +38,7 @@ var GUI = (function(){ showModal(560, `

+

`); var setupCheckBox = function(id, settingName){ @@ -48,6 +49,7 @@ var GUI = (function(){ setupCheckBox("dht-cfg-imgpreviews", "enableImagePreviews"); setupCheckBox("dht-cfg-formatting", "enableFormatting"); + setupCheckBox("dht-cfg-useravatars", "enableUserAvatars"); setupCheckBox("dht-cfg-animemoji", "enableAnimatedEmoji"); }; diff --git a/src/viewer/scripts/savefile.js b/src/viewer/scripts/savefile.js index 040aedb..107e483 100644 --- a/src/viewer/scripts/savefile.js +++ b/src/viewer/scripts/savefile.js @@ -35,6 +35,10 @@ class SAVEFILE{ return this.meta.users[this.meta.userindex[index]] || { "name": "<unknown>" }; } + getUserId(index){ + return this.meta.userindex[index]; + } + getUserById(user){ return this.meta.users[user] || { "name": user }; } diff --git a/src/viewer/scripts/state.js b/src/viewer/scripts/state.js index 6636dd8..706aaa8 100644 --- a/src/viewer/scripts/state.js +++ b/src/viewer/scripts/state.js @@ -69,11 +69,15 @@ var STATE = (function(){ ROOT.getChannelName = function(channel){ return FILE.getChannelById(channel).name; }; - + ROOT.getUserName = function(user){ return FILE.getUserById(user).name; }; + ROOT.getUserTag = function(user){ + return FILE.getUserById(user).tag; + }; + // -------------------------- // Channel list and selection // -------------------------- @@ -100,7 +104,10 @@ var STATE = (function(){ "id": key, "name": channels[key].name, "server": FILE.getServer(channels[key].server), - "msgcount": getFilteredMessageKeys(key).length + "msgcount": getFilteredMessageKeys(key).length, + "topic": channels[key].topic || "", + "nsfw": channels[key].nsfw || false, + "position": channels[key].position || -1 })).sort((ac, bc) => { var as = ac.server; var bs = bc.server; @@ -137,9 +144,12 @@ var STATE = (function(){ return MSGS.slice(startIndex, !messagesPerPage ? undefined : startIndex+messagesPerPage).map(key => { var message = messages[key]; + var user = FILE.getUser(message.u); + var avatar = user.avatar ? { id: FILE.getUserId(message.u), path: user.avatar } : null; return { - "user": FILE.getUser(message.u), + "user": user, + "avatar": avatar, "timestamp": message.t, "contents": ("m" in message) ? message.m : null, "embeds": message.e, @@ -327,6 +337,7 @@ var STATE = (function(){ defineSettingProperty("enableImagePreviews", true, fromBooleanString); defineSettingProperty("enableFormatting", true, fromBooleanString); + defineSettingProperty("enableUserAvatars", true, fromBooleanString); defineSettingProperty("enableAnimatedEmoji", true, fromBooleanString); // End diff --git a/src/viewer/styles/channels.css b/src/viewer/styles/channels.css index 826c3f1..56b9851 100644 --- a/src/viewer/styles/channels.css +++ b/src/viewer/styles/channels.css @@ -31,7 +31,7 @@ overflow: hidden; } -#channels .msgcount { +#channels .tag { flex-shrink: 1; background-color: rgba(255, 255, 255, 0.08); border-radius: 4px; diff --git a/src/viewer/styles/messages.css b/src/viewer/styles/messages.css index 16ffa9f..7697aa7 100644 --- a/src/viewer/styles/messages.css +++ b/src/viewer/styles/messages.css @@ -16,6 +16,27 @@ display: block; } +#messages .avatar-wrapper { + display: flex; + flex-direction: row; + align-items: flex-start; + align-content: flex-start; +} + +#messages .avatar-wrapper > div { + flex: 1 1 auto; +} + +#messages .avatar { + flex: 0 0 38px !important; + margin: 8px 14px 0 0; +} + +#messages .avatar img { + width: 38px; + border-radius: 50%; +} + #messages .username { color: #FFF; font-size: 15px;