//META{"name":"UnreadCountBadges","website":"https://metalloriff.github.io/toms-discord-stuff/","source":"https://github.com/Metalloriff/BetterDiscordPlugins/blob/master/UnreadCountBadges.plugin.js"}*//
class UnreadCountBadges {
getName() { return "UnreadCountBadges"; }
getDescription() { return "Adds an unread count badge on unread servers and channels."; }
getVersion() { return "0.2.7"; }
getAuthor() { return "Metalloriff"; }
getChanges() {
return {
"0.1.1":
`
Redid the way the plugin counts unreads. The upsides of this, is that the counts will have no limit now, will be more accurate, and will not require the channel/server to be loaded. The downside is that it will only show unread messages since the plugin was started.
Fixed messages not being marked as read until you switch channels/servers.
`,
"0.1.2":
`
The last update was a lie, it was far from more accurate. Fixed that.
`,
"0.2.2":
`
Discord broke it, I fixed it, that is all.
`,
"0.2.5":
`
Fixed channel unread styles.
Fixed muted channels never being read.
Fixed the muted channel opacity setting.
`
};
}
load() {}
start() {
let libLoadedEvent = () => {
try{ this.onLibLoaded(); }
catch(err) { console.error(this.getName(), "fatal error, plugin could not be started!", err); try { this.stop(); } catch(err) { console.error(this.getName() + ".stop()", err); } }
};
let lib = document.getElementById("NeatoBurritoLibrary");
if(!lib) {
lib = document.createElement("script");
lib.id = "NeatoBurritoLibrary";
lib.type = "text/javascript";
lib.src = "https://rawgit.com/Metalloriff/BetterDiscordPlugins/master/Lib/NeatoBurritoLibrary.js";
document.head.appendChild(lib);
}
this.forceLoadTimeout = setTimeout(libLoadedEvent, 30000);
if(typeof window.NeatoLib !== "undefined") libLoadedEvent();
else lib.addEventListener("load", libLoadedEvent);
}
getSettingsPanel() {
setTimeout(() => {
NeatoLib.Settings.pushElement(NeatoLib.Settings.Elements.createToggleGroup("ucb-toggles", "Toggles", [
{ title : "Ignore muted servers", value : "ignoreMutedGuilds", setValue : this.settings.ignoreMutedGuilds }
], choice => {
this.settings[choice.value] = !this.settings[choice.value];
this.applySettings();
this.saveSettings();
}), this.getName());
NeatoLib.Settings.pushElement(NeatoLib.Settings.Elements.createNewTextField("Badge color", this.settings.badgeColor, e => {
this.settings.badgeColor = e.target.value;
this.applySettings();
this.saveSettings();
}), this.getName());
NeatoLib.Settings.pushHTML(`
`, this.getName());
for(let example of document.getElementsByClassName("containerDefault-1ZnADq ucb-ex")) {
const wrapper = example.getElementsByClassName("wrapper-KpKNwI")[0],
content = example.getElementsByClassName("content-20Aix8")[0],
text = example.getElementsByClassName("overflowEllipsis-jeThUf")[0];
wrapper.originalClassName = wrapper.className;
content.originalClassName = content.className;
text.originalClassName = text.className;
example.addEventListener("mouseenter", () => {
wrapper.className = "wrapperHoveredText-2geN_M wrapper-KpKNwI";
content.className = "contentHoveredText-2D9B-x content-20Aix8";
text.className = "nameHoveredText-1uO31y name-3M0b8v overflowEllipsis-jeThUf";
});
example.addEventListener("mouseleave", () => {
wrapper.className = wrapper.originalClassName;
content.className = content.originalClassName;
text.className = text.originalClassName;
});
}
NeatoLib.Settings.pushElement(NeatoLib.Settings.Elements.createNewTextField("Muted channel badge opacity", this.settings.mutedChannelBadgeOpacity, e => {
if(isNaN(e.target.value)) return NeatoLib.showToast("Value must be a number", "error");
this.settings.mutedChannelBadgeOpacity = e.target.value;
this.applySettings();
this.saveSettings();
}), this.getName());
NeatoLib.Settings.pushChangelogElements(this);
}, 0);
return NeatoLib.Settings.Elements.pluginNameLabel(this.getName());
}
saveSettings() {
NeatoLib.Settings.save(this);
}
onLibLoaded() {
this.settings = NeatoLib.Settings.load(this, {
displayUpdateNotes : true,
badgeColor : "#7289da",
mutedChannelBadgeOpacity : 0.3,
ignoreMutedGuilds : true
});
NeatoLib.Updates.check(this);
if(this.settings.displayUpdateNotes) NeatoLib.Changelog.compareVersions(this.getName(), this.getChanges());
this.guildModule = NeatoLib.Modules.get(["getGuild", "getGuilds"]);
this.unreadModule = NeatoLib.Modules.get("getUnreadCount");
this.channelModule = NeatoLib.Modules.get(["getChannel", "getChannels"]);
this.muteModule = NeatoLib.Modules.get("isMuted");
this.scrollModule = NeatoLib.Modules.get("isAtBottom");
this.badges = {};
this.channelBadges = {};
this.unreads = {};
this.checkForBottom = () => {
let guild = NeatoLib.getSelectedGuildId();
if(this.scrollModule.isAtBottom(guild)) {
this.updateBadges(guild);
}
};
this.applySettings();
this.switchEvent = () => {
for(let cid in this.channelBadges) {
this.channelBadges[cid].remove();
delete this.channelBadges[cid];
}
this.updateBadges();
let scroller = document.getElementsByClassName("messages scroller")[0], guild = NeatoLib.getSelectedGuild();
if(scroller && guild) scroller.addEventListener("scroll", this.checkForBottom);
};
this.checkForBottomUpdate = setInterval(this.checkForBottom, 500);
NeatoLib.Events.attach("switch", this.switchEvent);
this.unpatchHandleMessage = NeatoLib.monkeyPatchInternal(NeatoLib.Modules.get("handleMessage"), "handleMessage", e => {
try {
const data = e.args[0];
if(data.type == "MESSAGE_CREATE" && data.message) {
if(!this.unreads[data.message.guild_id]) this.unreads[data.message.guild_id] = { total : 0 };
if(!this.muteModule.isGuildOrCategoryOrChannelMuted(data.message.guild_id, data.message.channel_id) || !this.settings.ignoreMutedGuilds) this.unreads[data.message.guild_id].total++;
if(!this.unreads[data.message.guild_id][data.message.channel_id]) this.unreads[data.message.guild_id][data.message.channel_id] = 0;
this.unreads[data.message.guild_id][data.message.channel_id]++;
this.updateBadges(data.message.guild_id);
}
} catch(err) {
console.error(err);
} finally {
return e.callDefault();
}
}, this.getName());
NeatoLib.Events.onPluginLoaded(this);
this.updateBadges();
}
applySettings() {
if(this.styles) this.styles.destroy();
this.styles = NeatoLib.injectCSS(`
.${NeatoLib.getClass("unreadMentionsBar", "scroller")} .${NeatoLib.getClass("lurkingGuild", "badge")}.unread-count-badge {
bottom: 35px;
background-color: ${this.settings.badgeColor};
}
#app-mount .unread-count-channel-badge {
background-color: ${this.settings.badgeColor};
}
.${NeatoLib.Modules.get("wrapperMutedText").wrapperMutedText.split(" ").join(".")} .unread-count-channel-badge {
opacity: ${this.settings.mutedChannelBadgeOpacity};
}
`);
}
updateBadges(guild) {
const guilds = !guild ? this.guildModule.getGuilds() : undefined, selectedGuild = NeatoLib.getSelectedGuild();
const updateUnreadFor = id => {
if(!this.unreads[id]) return;
if(selectedGuild && selectedGuild.id == id) {
const classes = NeatoLib.Modules.get("wrapperDefaultText"), channels = document.getElementsByClassName(classes.wrapper);
for(let i = 0; i < channels.length; i++) {
const cid = NeatoLib.ReactData.getProp(channels[i].parentElement, "channel.id");
if(!cid) continue;
if(this.unreads[id][cid] > 0 && this.unreadModule.getUnreadCount(cid) == 0) {
this.unreads[id].total -= this.unreads[id][cid];
if(this.unreads[id].total < 0) this.unreads[id].total = 0;
this.unreads[id][cid] = 0;
}
if(this.unreads[id][cid] > 0) {
if(this.channelBadges[cid]) this.channelBadges[cid].firstChild.innerText = this.unreads[id][cid];
else this.channelBadges[cid] = channels[i].getElementsByClassName(classes.content)[0].lastChild.appendChild(this.createChannelBadge(this.unreads[id][cid]));
} else if(this.channelBadges[cid]) {
this.channelBadges[cid].remove();
delete this.channelBadges[cid];
}
}
}
if(this.unreads[id].total > 0) {
if(this.badges[id] != undefined) this.badges[id].innerText = this.unreads[id].total;
else this.badges[id] = NeatoLib.DOM.searchForParentElementByClassName(document.querySelector("[style*='" + id + "']"), NeatoLib.getClass("lurkingGuild", "container")).appendChild(this.createBadge(this.unreads[id].total));
} else if(this.badges[id]) {
this.badges[id].remove();
delete this.badges[id];
for(let cid in this.channelBadges) {
this.channelBadges[cid].remove();
delete this.channelBadges[cid];
}
}
};
if(guild) return updateUnreadFor(guild);
else if(guilds) for(let id in guilds) updateUnreadFor(id);
}
createBadge(unreadCount) {
const badge = document.createElement("div");
badge.className = "wrapper-232cHJ " + NeatoLib.getClass("lurkingGuild", "badge") + " unread-count-badge";
badge.innerText = unreadCount;
return badge;
}
createChannelBadge(unreadCount) {
const badge = document.createElement("div");
badge.className = NeatoLib.getClass("containerDragAfter", "iconSpacing");
badge.innerHTML = `${unreadCount}
`;
return badge;
}
stop() {
const css = document.getElementById("uc-css");
if(css) css.remove();
NeatoLib.Events.detach("switch", this.switchEvent);
this.styles.destroy();
for(let id in this.badges) this.badges[id].remove();
for(let id in this.channelBadges) this.channelBadges[id].remove();
this.unpatchHandleMessage();
clearInterval(this.checkForBottomUpdate);
}
}