dotfiles

My PC Dotfiles & Website
commit d805ef2e08de8b2e267e44a4019a2439d928078b
parent 2ee5748602584affc526d5d6f4d5d0cdc397f61e
Author: maydayv7 <maydayv7@gmail.com>
Date:   Mon, 13 Feb 2023 11:16:26 +0530

fix: Multiple Fixes

+ Add Discord Plugins
+ Fix Syntax Errors
+ Fix GitHub Language Detection

Diffstat:

M.gitattributes | 5+++--
MREADME.md | 2+-
Mfiles/discord/plugins/CreationDate.plugin.js | 1-
Afiles/discord/plugins/DoubleClickToEdit.plugin.js | 328+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Afiles/discord/plugins/ReadAllNotificationsButton.plugin.js | 687+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfiles/discord/plugins/ShowHiddenChannels.plugin.js | 1-
Afiles/discord/plugins/SplitLargeMessages.plugin.js | 350+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfiles/discord/plugins/TypingUsersAvatars.plugin.js | 330+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mmodules/apps/flatpak.nix | 2+-
Msite/content/anime.md | 9++++++---
Msite/content/now.md | 2+-
11 files changed, 1547 insertions(+), 170 deletions(-)

diff --git a/.gitattributes b/.gitattributes @@ -1 +1,2 @@ -*.secret binary -\ No newline at end of file +*.secret binary +files/discord/plugins/* linguist-vendored +\ No newline at end of file diff --git a/README.md b/README.md @@ -612,7 +612,7 @@ You can navigate to the `README`'s present in the various directories to know mo </details> -> Last Updated: **January** 2023 +> Last Updated: **February** 2023 If you like this project, consider leaving a [star](https://github.com/maydayv7/dotfiles) diff --git a/files/discord/plugins/CreationDate.plugin.js b/files/discord/plugins/CreationDate.plugin.js @@ -9,7 +9,6 @@ * @patreon https://www.patreon.com/MircoWittrien * @website https://mwittrien.github.io/ * @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/CreationDate/ - * @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/CreationDate/CreationDate.plugin.js */ module.exports = (_ => { diff --git a/files/discord/plugins/DoubleClickToEdit.plugin.js b/files/discord/plugins/DoubleClickToEdit.plugin.js @@ -0,0 +1,328 @@ +/** + * @name Double Click To Edit + * @author Farcrada, original idea by Jiiks + * @version 9.4.4 + * @description Double click a message you wrote to quickly edit it. + * + * @invite qH6UWCwfTu + * @website https://github.com/Farcrada/DiscordPlugins/ + * @source https://github.com/Farcrada/DiscordPlugins/blob/master/Double-click-to-edit/DoubleClickToEdit.plugin.js + */ + +/** @type {typeof import("react")} */ +const React = BdApi.React, + + { Webpack, Webpack: { Filters }, Data } = BdApi, + + config = { + info: { + name: "Double Click To Edit", + id: "DoubleClickToEdit", + description: "Double click a message you wrote to quickly edit it", + version: "9.4.4", + author: "Farcrada", + updateUrl: "https://raw.githubusercontent.com/Farcrada/DiscordPlugins/master/Double-click-to-edit/DoubleClickToEdit.plugin.js" + } + }, + + blacklist = [ + //Object + "video", + "emoji", + //Classes + "content", + "reactionInner" + ]; + + +module.exports = class DoubleClickToEdit { + + + load() { + try { global.ZeresPluginLibrary.PluginUpdater.checkForUpdate(config.info.name, config.info.version, config.info.updateUrl); } + catch (err) { console.error(config.info.name, "Failed to reach the ZeresPluginLibrary for Plugin Updater.", err); } + } + + start() { + try { + //Classes + this.selectedClass = Webpack.getModule(Filters.byProps("message", "selected")).selected; + this.messagesWrapper = Webpack.getModule(Filters.byProps("empty", "messagesWrapper")).messagesWrapper; + + //Copy to clipboard + this.copyToClipboard = Webpack.getModule(Filters.byProps("clipboard", "app")).clipboard.copy; + + //Reply functions + this.replyToMessage = Webpack.getModule(m => m?.toString?.()?.replace('\n', '')?.search(/(channel:[\w|\w],message:[\w|\w],shouldMention:!)/) > -1, { searchExports: true }) + this.getChannel = Webpack.getModule(Filters.byProps("getChannel", "getDMFromUserId")).getChannel; + + //Stores + this.MessageStore = Webpack.getModule(Filters.byProps("receiveMessage", "editMessage")); + this.CurrentUserStore = Webpack.getModule(Filters.byProps("getCurrentUser")); + + //Settings + const filter = Webpack.Filters.byStrings(`["tag","children","className","faded","disabled","required","error"]`), + target = Webpack.getModule(m => Object.values(m).some(filter)); + this.FormTitle = target[Object.keys(target).find(k => filter(target[k]))]; + this.RadioItem = Webpack.getModule(m => m?.Sizes?.NONE, { searchExports: true }); + this.SwitchItem = Webpack.getModule(Filters.byStrings("=e.note")); + + + //Events + global.document.addEventListener('dblclick', this.doubleclickFunc); + + //Load settings + //Edit + this.doubleClickToEditModifier = Data.load(config.info.id, "doubleClickToEditModifier") ?? false; + this.editModifier = Data.load(config.info.id, "editModifier") ?? "shift"; + //Reply + this.doubleClickToReply = Data.load(config.info.id, "doubleClickToReply") ?? false; + this.doubleClickToReplyModifier = Data.load(config.info.id, "doubleClickToReplyModifier") ?? false; + this.replyModifier = Data.load(config.info.id, "replyModifier") ?? "shift"; + //Copy + this.doubleClickToCopy = Data.load(config.info.id, "doubleClickToCopy") ?? false; + this.copyModifier = Data.load(config.info.id, "copyModifier") ?? "shift"; + + } + catch (err) { + try { + console.error("Attempting to stop after starting error...", err); + this.stop(); + } + catch (err) { + console.error(config.info.name + ".stop()", err); + } + } + } + + //By doing this we make sure we're able to remove our event + //otherwise it gets stuck on the page and never actually unloads. + doubleclickFunc = (e) => this.handler(e); + + stop = () => document.removeEventListener('dblclick', this.doubleclickFunc); + + getSettingsPanel() { + //Anonymous function to preserve the this scope, + //which also makes it an anonymous functional component; + //Pretty neat. + return () => { + //Edit + const [editEnableModifier, setEditEnableModifier] = React.useState(this.doubleClickToEditModifier), + [editModifier, setEditModifier] = React.useState(this.editModifier), + //Reply + [reply, setReply] = React.useState(this.doubleClickToReply), + [replyEnableModifier, setReplyEnableModifier] = React.useState(this.doubleClickToReplyModifier), + [replyModifier, setReplyModifier] = React.useState(this.replyModifier), + //Copy + [copy, setCopy] = React.useState(this.doubleClickToCopy), + [copyModifier, setCopyModifier] = React.useState(this.copyModifier); + + return [ + //Edit + React.createElement(this.SwitchItem, { + //The state that is loaded with the default value + value: editEnableModifier, + note: "Enable modifier for double clicking to edit", + //Since onChange passes the current state we can simply invoke it as such + onChange: (newState) => { + //Saving the new state + this.doubleClickToEditModifier = newState; + Data.save(config.info.id, "doubleClickToEditModifier", newState); + setEditEnableModifier(newState); + } + //Discord Is One Of Those + }, "Enable Edit Modifier"), + React.createElement(this.FormTitle, { + disabled: !editEnableModifier, + tag: "h3" + }, "Modifer to hold to edit a message"), + React.createElement(this.RadioItem, { + disabled: !editEnableModifier, + value: editModifier, + options: [ + { name: "Shift", value: "shift" }, + { name: "Ctrl", value: "ctrl" }, + { name: "Alt", value: "alt" } + ], + onChange: (newState) => { + this.editModifier = newState.value; + Data.save(config.info.id, "editModifier", newState.value); + setEditModifier(newState.value); + } + }), + + //Reply + React.createElement(this.SwitchItem, { + value: reply, + note: "Double click another's message and start replying.", + onChange: (newState) => { + this.doubleClickToReply = newState; + Data.save(config.info.id, "doubleClickToReply", newState); + setReply(newState); + } + }, "Enable Replying"), + React.createElement(this.SwitchItem, { + disabled: !reply, + value: replyEnableModifier, + note: "Enable modifier for double clicking to reply", + onChange: (newState) => { + this.doubleClickToReplyModifier = newState; + Data.save(config.info.id, "doubleClickToReplyModifier", newState); + setReplyEnableModifier(newState); + } + }, "Enable Reply Modifier"), + React.createElement(this.FormTitle, { + disabled: (!reply || !replyEnableModifier), + tag: "h3" + }, "Modifier to hold when replying to a message"), + React.createElement(this.RadioItem, { + disabled: (!reply || !replyEnableModifier), + value: replyModifier, + options: [ + { name: "Shift", value: "shift" }, + { name: "Ctrl", value: "ctrl" }, + { name: "Alt", value: "alt" } + ], + onChange: (newState) => { + this.replyModifier = newState.value; + Data.save(config.info.id, "replyModifier", newState.value); + setReplyModifier(newState.value); + } + }), + + //Copy + React.createElement(this.SwitchItem, { + value: copy, + note: "Copy selection before entering edit-mode.", + onChange: (newState) => { + this.doubleClickToCopy = newState; + Data.save(config.info.id, "doubleClickToCopy", newState); + setCopy(newState); + } + }, "Enable Copying"), + React.createElement(this.FormTitle, { + disabled: !copy, + tag: "h3" + }, "Modifier to hold before copying text"), + React.createElement(this.RadioItem, { + disabled: !copy, + value: copyModifier, + options: [ + { name: "Shift", value: "shift" }, + { name: "Ctrl", value: "ctrl" }, + { name: "Alt", value: "alt" } + ], + onChange: (newState) => { + this.copyModifier = newState.value; + Data.save(config.info.id, "copyModifier", newState.value); + setCopyModifier(newState.value); + } + }) + ]; + } + } + + handler(e) { + //Check if we're not double clicking + if (typeof (e?.target?.className) !== typeof ("") || + blacklist.some(nameOfClass => e?.target?.className?.indexOf?.(nameOfClass) > -1)) + return; + + //Target the message + const messageDiv = e.target.closest('li > [class^=message]'); + + //If it finds nothing, null it. + if (!messageDiv) + return; + //Make sure we're not resetting when the message is already in edit-mode. + if (messageDiv.classList.contains(this.selectedClass)) + return; + + //Basically make a HTMLElement/Node interactable with it's React components. + const instance = BdApi.getInternalInstance(messageDiv); + //Mandatory nullcheck + if (!instance) + return; + + //When selecting text it might be useful to copy. + const copyKeyHeld = this.checkForModifier(this.doubleClickToCopy, this.copyModifier, e); + if (copyKeyHeld) + this.copyToClipboard(document.getSelection().toString()); + + //The message instance is filled top to bottom, as it is in view. + //As a result, "baseMessage" will be the actual message you want to address. And "message" will be the reply. + //Maybe the message has a reply, so check if "baseMessage" exists and otherwise fallback on "message". + const message = this.getValueFromKey(instance, "baseMessage") ?? this.getValueFromKey(instance, "message"); + + if (!message) + return; + + //Now we do the same thing with the edit and reply modifier + const editKeyHeld = this.checkForModifier(this.doubleClickToEditModifier, this.editModifier, e), + replyKeyHeld = this.checkForModifier(this.doubleClickToReplyModifier, this.replyModifier, e); + + //If a modifier is enabled, check if the key is held, otherwise ignore. + if ((this.doubleClickToEditModifier ? editKeyHeld : true) && message.author.id === this.CurrentUserStore.getCurrentUser().id) + this.MessageStore.startEditMessage(message.channel_id, message.id, message.content); + else if ((this.doubleClickToReplyModifier ? replyKeyHeld : true) && this.doubleClickToReply) + this.replyToMessage(this.getChannel(message.channel_id), message, e); + } + + /** + * + * @param {boolean} enabled Is the modifier enabled + * @param {string} modifier Modifier key to be checked for + * @param {Event} event The event checked against + * @returns {boolean} Whether the modifier is enabled and the modifier is pressed + */ + checkForModifier(enabled, modifier, event) { + if (enabled) + switch (modifier) { + case "shift": return event.shiftKey; + case "ctrl": return event.ctrlKey; + case "alt": return event.altKey; + } + return false; + } + + getValueFromKey(instance, searchkey) { + //Where we want to search. + const whitelist = { + memoizedProps: true, + child: true, + sibling: true + }; + + return function getKey(instance) { + //Pre-define + let result = undefined; + //Make sure it exists and isn't a "paradox". + if (instance && !Node.prototype.isPrototypeOf(instance)) { + //Get our own keys + const keys = Object.getOwnPropertyNames(instance); + //As long as we don't have a result, lets go through. + for (let i = 0; result === undefined && i < keys.length; i++) { + //Store our key for readability + const key = keys[i]; + //Check if there is a key + if (key) { + //Store the value + const value = instance[key]; + //Is our key what we want? + if (searchkey === key) + result = value; + //Otherwise check if the value of a key is something we can search through + //and whitelisted; of course. + else if ((typeof value === "object" || typeof value === "function") && + (whitelist[key] || key[0] == "." || !isNaN(key[0]))) + //Lets go nesting; lets go! + result = getKey(value); + } + } + } + //If a poor sod got found this will not be `undefined` + return result; + //Start our mayhem + }(instance); + } +} diff --git a/files/discord/plugins/ReadAllNotificationsButton.plugin.js b/files/discord/plugins/ReadAllNotificationsButton.plugin.js @@ -0,0 +1,686 @@ +/** + * @name ReadAllNotificationsButton + * @author DevilBro + * @authorId 278543574059057154 + * @version 1.7.3 + * @description Adds a Clear Button to the Server List and the Mentions Popout + * @invite Jx3TjNS + * @donate https://www.paypal.me/MircoWittrien + * @patreon https://www.patreon.com/MircoWittrien + * @website https://mwittrien.github.io/ + * @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ReadAllNotificationsButton/ + */ + +module.exports = (_ => { + const changeLog = { + + }; + + return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class { + constructor (meta) {for (let key in meta) this[key] = meta[key];} + getName () {return this.name;} + getAuthor () {return this.author;} + getVersion () {return this.version;} + getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;} + + downloadLibrary () { + require("request").get("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js", (e, r, b) => { + if (!e && b && r.statusCode == 200) require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.showToast("Finished downloading BDFDB Library", {type: "success"})); + else BdApi.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library"); + }); + } + + load () { + if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []}); + if (!window.BDFDB_Global.downloadModal) { + window.BDFDB_Global.downloadModal = true; + BdApi.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, { + confirmText: "Download Now", + cancelText: "Cancel", + onCancel: _ => {delete window.BDFDB_Global.downloadModal;}, + onConfirm: _ => { + delete window.BDFDB_Global.downloadModal; + this.downloadLibrary(); + } + }); + } + if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name); + } + start () {this.load();} + stop () {} + getSettingsPanel () { + let template = document.createElement("template"); + template.innerHTML = `<div style="color: var(--header-primary); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`; + template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary); + return template.content.firstElementChild; + } + } : (([Plugin, BDFDB]) => { + var _this; + var blacklist, clearing; + + const ReadAllButtonComponent = class ReadAllButton extends BdApi.React.Component { + clearClick() { + if (_this.settings.batch.guilds) this.clearGuilds(_this.settings.batch.muted ? this.getGuilds() : this.getUnread()); + if (_this.settings.batch.dms) BDFDB.DMUtils.markAsRead(this.getPingedDMs()); + } + clearGuilds(guildIds) { + BDFDB.GuildUtils.markAsRead(guildIds.filter(id => id && !blacklist.includes(id))); + } + getGuilds() { + return BDFDB.LibraryModules.SortedGuildUtils.getFlattenedGuilds().map(g => g.id).filter(n => n); + } + getUnread() { + return this.getGuilds().filter(id => BDFDB.LibraryStores.GuildReadStateStore.hasUnread(id) || BDFDB.LibraryStores.GuildReadStateStore.getMentionCount(id) > 0); + } + getPinged() { + return this.getGuilds().filter(id => BDFDB.LibraryStores.GuildReadStateStore.getMentionCount(id) > 0); + } + getMuted() { + return this.getGuilds().filter(id => BDFDB.LibraryStores.UserGuildSettingsStore.isGuildOrCategoryOrChannelMuted(id)); + } + getPingedDMs() { + return BDFDB.LibraryStores.ChannelStore.getSortedPrivateChannels().map(c => c.id).filter(id => id && BDFDB.LibraryStores.ReadStateStore.getMentionCount(id) > 0); + } + render() { + return BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCNS.guildouter + BDFDB.disCN._readallnotificationsbuttonframe, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCNS.guildiconwrapper + BDFDB.disCN._readallnotificationsbuttoninner, + children: BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCNS.guildiconchildwrapper + BDFDB.disCN._readallnotificationsbuttonbutton, + children: "read all", + onClick: _ => { + if (!_this.settings.general.confirmClear) this.clearClick(); + else BDFDB.ModalUtils.confirm(_this, _this.labels.modal_confirmnotifications, _ => this.clearClick()); + }, + onContextMenu: event => { + BDFDB.ContextMenuUtils.open(_this, event, BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuGroup, { + children: [ + BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, { + label: _this.labels.context_unreadguilds, + id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-unread-read"), + action: _ => this.clearGuilds(this.getUnread()) + }), + BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, { + label: _this.labels.context_pingedguilds, + id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-pinged-read"), + action: _ => this.clearGuilds(this.getPinged()) + }), + BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, { + label: _this.labels.context_mutedguilds, + id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-muted-read"), + action: _ => this.clearGuilds(this.getMuted()) + }), + BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, { + label: _this.labels.context_guilds, + id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-all-read"), + action: _ => this.clearGuilds(this.getGuilds()) + }), + BDFDB.ContextMenuUtils.createItem(BDFDB.LibraryComponents.MenuItems.MenuItem, { + label: _this.labels.context_dms, + id: BDFDB.ContextMenuUtils.createItemId(_this.name, "mark-dms-read"), + action: _ => BDFDB.DMUtils.markAsRead(this.getPingedDMs()) + }) + ] + })); + } + }) + }) + }); + } + }; + + return class ReadAllNotificationsButton extends Plugin { + onLoad () { + _this = this; + + this.defaults = { + general: { + addClearButton: {value: true, description: "Adds a 'Clear Mentions' button to the recent mentions popout"}, + confirmClear: {value: false, description: "Asks for your confirmation before clearing reads"} + }, + batch: { + guilds: {value: true, description: "unread Servers"}, + muted: {value: false, description: "muted unread Servers"}, + dms: {value: false, description: "unread DMs"} + } + }; + + this.modulePatches = { + after: [ + "GuildsBar", + "InboxHeader" + ] + }; + + this.css = ` + ${BDFDB.dotCN.messagespopouttabbar} { + flex: 1 0 auto; + } + ${BDFDB.dotCN.messagespopoutcontrols} { + display: flex; + } + ${BDFDB.dotCN.messagespopoutcontrols} > * { + margin-left: 10px; + } + ${BDFDB.dotCN._readallnotificationsbuttonframe} { + height: 24px; + margin-bottom: 10px; + } + ${BDFDB.dotCN._readallnotificationsbuttonframe}:active { + transform: translateY(1px); + } + ${BDFDB.dotCN._readallnotificationsbuttoninner} { + height: 24px; + } + ${BDFDB.dotCN._readallnotificationsbuttonbutton} { + border-radius: 4px; + height: 24px; + font-size: 12px; + line-height: 1.3; + white-space: nowrap; + cursor: pointer; + } + `; + } + + onStart () { + let loadedBlacklist = BDFDB.DataUtils.load(this, "blacklist"); + this.saveBlacklist(!BDFDB.ArrayUtils.is(loadedBlacklist) ? [] : loadedBlacklist); + + this.forceUpdateAll(); + } + + onStop () { + this.forceUpdateAll(); + } + + getSettingsPanel (collapseStates = {}) { + let settingsPanel, settingsItems = []; + + settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, { + title: "Settings", + collapseStates: collapseStates, + children: Object.keys(this.defaults.general).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, { + type: "Switch", + plugin: this, + keys: ["general", key], + label: this.defaults.general[key].description, + value: this.settings.general[key] + })).concat(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsPanelList, { + title: "When left clicking the 'read all' Button mark following Elements as read:", + first: false, + last: true, + children: Object.keys(this.defaults.batch).map(key => BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, { + type: "Switch", + plugin: this, + keys: ["batch", key], + label: this.defaults.batch[key].description, + value: this.settings.batch[key] + })) + })) + })); + + let listInstance = null, batchSetGuilds = value => { + if (!value) { + for (let id of BDFDB.LibraryModules.SortedGuildUtils.getFlattenedGuildIds()) blacklist.push(id); + blacklist = BDFDB.ArrayUtils.removeCopies(blacklist); + } + else blacklist = []; + this.saveBlacklist(blacklist); + if (listInstance) { + listInstance.props.disabled = blacklist; + BDFDB.ReactUtils.forceUpdate(listInstance); + } + }; + settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.CollapseContainer, { + title: "Server Black List", + collapseStates: collapseStates, + children: [ + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsGuildList, { + className: BDFDB.disCN.marginbottom20, + disabled: BDFDB.DataUtils.load(this, "blacklist"), + onClick: disabledGuilds => this.saveBlacklist(disabledGuilds), + ref: instance => {listInstance = instance;} + }), + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { + type: "Button", + color: BDFDB.LibraryComponents.Button.Colors.GREEN, + label: "Enable for all Servers", + onClick: _ => batchSetGuilds(true), + children: BDFDB.LanguageUtils.LanguageStrings.ENABLE + }), + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsItem, { + type: "Button", + color: BDFDB.LibraryComponents.Button.Colors.PRIMARY, + label: "Disable for all Servers", + onClick: _ => batchSetGuilds(false), + children: BDFDB.LanguageUtils.LanguageStrings.DISABLE + }) + ] + })); + + return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, settingsItems); + } + + onSettingsClosed () { + if (this.SettingsUpdated) { + delete this.SettingsUpdated; + this.forceUpdateAll(); + } + } + + forceUpdateAll () { + BDFDB.DiscordUtils.rerenderAll(); + } + + processGuildsBar (e) { + let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {name: "UnreadDMs"}); + if (index > -1) children.splice(index + 1, 0, BDFDB.ReactUtils.createElement(ReadAllButtonComponent, {})); + } + + processInboxHeader (e) { + if (!this.settings.general.addClearButton || e.instance.props.tab != BDFDB.DiscordConstants.InboxTabs.MENTIONS) return; + let mentionedMessages = BDFDB.LibraryStores.RecentMentionsStore.getMentions(); + if (!mentionedMessages || !mentionedMessages.length) return; + let controls = BDFDB.ReactUtils.findChild(e.returnvalue, {props: [["className", BDFDB.disCN.messagespopoutcontrols]]}); + if (controls) controls.props.children = [ + controls.props.children, + BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, { + text: `${BDFDB.LanguageUtils.LanguageStrings.CLOSE} (${BDFDB.LanguageUtils.LanguageStrings.FORM_LABEL_ALL})`, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.Clickable, { + className: BDFDB.disCNS.messagespopoutbutton + BDFDB.disCNS.messagespopoutbuttonsecondary + BDFDB.disCN.messagespopoutbuttonsize32, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SvgIcon, { + nativeClass: true, + name: BDFDB.LibraryComponents.SvgIcon.Names.CLOSE, + width: 16, + height: 16 + }), + onClick: _ => { + let clear = _ => { + if (clearing) return BDFDB.NotificationUtils.toast(`${this.labels.toast_alreadyclearing} - ${BDFDB.LanguageUtils.LibraryStrings.please_wait}`, {type: "danger"}); + let messages = [].concat(mentionedMessages).filter(n => n); + if (messages.length) { + clearing = true; + let toast = BDFDB.NotificationUtils.toast(`${this.labels.toast_clearing} - ${BDFDB.LanguageUtils.LibraryStrings.please_wait}`, {timeout: 0, ellipsis: true}); + for (let i = 0; i < messages.length; i++) BDFDB.TimeUtils.timeout(_ => { + BDFDB.LibraryModules.RecentMentionUtils.deleteRecentMention(messages[i].id); + if (i == messages.length - 1) { + clearing = false; + toast.close(); + BDFDB.NotificationUtils.toast(this.labels.toastcleared, {type: "success"}); + } + }, i * 1000); + } + }; + if (this.settings.general.confirmClear) BDFDB.ModalUtils.confirm(this, this.labels.modal_confirmmentions, clear); + else clear(); + } + }) + }) + ].flat(10); + } + + saveBlacklist (savedBlacklist) { + blacklist = savedBlacklist; + BDFDB.DataUtils.save(savedBlacklist, this, "blacklist"); + } + + setLabelsByLanguage () { + switch (BDFDB.LanguageUtils.getLanguage().id) { + case "bg": // Bulgarian + return { + context_dms: "Директно съобщение", + context_guilds: "Всички сървъри", + context_mutedguilds: "Приглушени сървъри", + context_pingedguilds: "Pinged сървъри", + context_unreadguilds: "Непрочетени сървъри", + modal_confirmmentions: "Наистина ли искате да изтриете всички непрочетени споменавания?", + modal_confirmnotifications: "Наистина ли искате да изтриете всички непрочетени известия?", + toast_alreadyclearing: "Изтрива някои споменавания вече", + toast_cleared: "Всички последни споменавания бяха изтрити", + toast_clearing: "Изчиства всички скорошни споменавания" + }; + case "da": // Danish + return { + context_dms: "Direkte beskeder", + context_guilds: "Alle servere", + context_mutedguilds: "Dæmpede servere", + context_pingedguilds: "Pingede servere", + context_unreadguilds: "Ulæste servere", + modal_confirmmentions: "Er du sikker på, at du vil slette alle ulæste omtaler?", + modal_confirmnotifications: "Er du sikker på, at du vil slette alle ulæste meddelelser?", + toast_alreadyclearing: "Sletter allerede nogle omtaler", + toast_cleared: "Alle nylige omtaler er blevet slettet", + toast_clearing: "Rydder alle nylige omtaler" + }; + case "de": // German + return { + context_dms: "Direktnachrichten", + context_guilds: "Alle Server", + context_mutedguilds: "Stummgeschaltete Server", + context_pingedguilds: "Gepingte Server", + context_unreadguilds: "Ungelesene Server", + modal_confirmmentions: "Möchten Sie wirklich alle ungelesenen Erwähnungen löschen?", + modal_confirmnotifications: "Möchten Sie wirklich alle ungelesenen Benachrichtigungen löschen?", + toast_alreadyclearing: "Löscht bereits einige Erwähnungen", + toast_cleared: "Alle kürzlich Erwähnungen wurden gelöscht", + toast_clearing: "Löscht alle letzten Erwähnungen" + }; + case "el": // Greek + return { + context_dms: "Αμεσα μηνύματα", + context_guilds: "Όλοι οι διακομιστές", + context_mutedguilds: "Σίγαση διακομιστών", + context_pingedguilds: "Διακομιστές Ping", + context_unreadguilds: "Μη αναγνωσμένοι διακομιστές", + modal_confirmmentions: "Είστε βέβαιοι ότι θέλετε να διαγράψετε όλες τις μη αναγνωσμένες αναφορές;", + modal_confirmnotifications: "Είστε βέβαιοι ότι θέλετε να διαγράψετε όλες τις μη αναγνωσμένες ειδοποιήσεις;", + toast_alreadyclearing: "Διαγράφει ήδη κάποιες αναφορές", + toast_cleared: "Όλες οι πρόσφατες αναφορές έχουν διαγραφεί", + toast_clearing: "Διαγράφει όλες τις πρόσφατες αναφορές" + }; + case "es": // Spanish + return { + context_dms: "Mensajes directos", + context_guilds: "Todos los servidores", + context_mutedguilds: "Servidores silenciados", + context_pingedguilds: "Servidores con ping", + context_unreadguilds: "Servidores no leídos", + modal_confirmmentions: "¿Estás seguro de que deseas eliminar todas las menciones no leídas?", + modal_confirmnotifications: "¿Está seguro de que desea eliminar todas las notificaciones no leídas?", + toast_alreadyclearing: "Elimina algunas menciones ya", + toast_cleared: "Se han eliminado todas las menciones recientes", + toast_clearing: "Borra todas las menciones recientes" + }; + case "fi": // Finnish + return { + context_dms: "Suorat viestit", + context_guilds: "Kaikki palvelimet", + context_mutedguilds: "Mykistetyt palvelimet", + context_pingedguilds: "Pinged-palvelimet", + context_unreadguilds: "Lukemattomat palvelimet", + modal_confirmmentions: "Haluatko varmasti poistaa kaikki lukemattomat maininnat?", + modal_confirmnotifications: "Haluatko varmasti poistaa kaikki lukemattomat ilmoitukset?", + toast_alreadyclearing: "Poistaa jo joitain mainintoja", + toast_cleared: "Kaikki viimeisimmät maininnat on poistettu", + toast_clearing: "Tyhjentää kaikki viimeisimmät maininnat" + }; + case "fr": // French + return { + context_dms: "Messages directs", + context_guilds: "Tous les serveurs", + context_mutedguilds: "Serveurs muets", + context_pingedguilds: "Serveurs ping", + context_unreadguilds: "Serveurs non lus", + modal_confirmmentions: "Voulez-vous vraiment supprimer toutes les mentions non lues?", + modal_confirmnotifications: "Voulez-vous vraiment supprimer toutes les notifications non lues?", + toast_alreadyclearing: "Supprime déjà certaines mentions", + toast_cleared: "Toutes les mentions récentes ont été supprimées", + toast_clearing: "Efface toutes les mentions récentes" + }; + case "hr": // Croatian + return { + context_dms: "Direktna poruka", + context_guilds: "Svi poslužitelji", + context_mutedguilds: "Prigušeni poslužitelji", + context_pingedguilds: "Pingirani poslužitelji", + context_unreadguilds: "Nepročitani poslužitelji", + modal_confirmmentions: "Jeste li sigurni da želite izbrisati sva nepročitana spominjanja?", + modal_confirmnotifications: "Jeste li sigurni da želite izbrisati sve nepročitane obavijesti?", + toast_alreadyclearing: "Briše već spomenute", + toast_cleared: "Sva nedavna spominjanja su izbrisana", + toast_clearing: "Briše sva nedavna spominjanja" + }; + case "hu": // Hungarian + return { + context_dms: "Közvetlen üzenet", + context_guilds: "Minden szerver", + context_mutedguilds: "Némított szerverek", + context_pingedguilds: "Pingelt szerverek", + context_unreadguilds: "Olvasatlan szerverek", + modal_confirmmentions: "Biztosan törli az összes olvasatlan említést?", + modal_confirmnotifications: "Biztosan törli az összes olvasatlan értesítést?", + toast_alreadyclearing: "Néhány említést már töröl", + toast_cleared: "Az összes közelmúltbeli említést törölték", + toast_clearing: "Törli az összes közelmúltbeli említést" + }; + case "it": // Italian + return { + context_dms: "Messaggi diretti", + context_guilds: "Tutti i server", + context_mutedguilds: "Server disattivati", + context_pingedguilds: "Server sottoposti a ping", + context_unreadguilds: "Server non letti", + modal_confirmmentions: "Sei sicuro di voler eliminare tutte le menzioni non lette?", + modal_confirmnotifications: "Sei sicuro di voler eliminare tutte le notifiche non lette?", + toast_alreadyclearing: "Elimina già alcune menzioni", + toast_cleared: "Tutte le menzioni recenti sono state eliminate", + toast_clearing: "Cancella tutte le menzioni recenti" + }; + case "ja": // Japanese + return { + context_dms: "ダイレクトメッセージ", + context_guilds: "すべてのサーバー", + context_mutedguilds: "ミュートされたサーバー", + context_pingedguilds: "pingされたサーバー", + context_unreadguilds: "未読サーバー", + modal_confirmmentions: "未読のメンションをすべて削除してもよろしいですか?", + modal_confirmnotifications: "未読の通知をすべて削除してもよろしいですか?", + toast_alreadyclearing: "すでにいくつかの言及を削除します", + toast_cleared: "最近の言及はすべて削除されました", + toast_clearing: "最近の言及をすべてクリアします" + }; + case "ko": // Korean + return { + context_dms: "쪽지", + context_guilds: "모든 서버", + context_mutedguilds: "음소거 된 서버", + context_pingedguilds: "핑된 서버", + context_unreadguilds: "읽지 않은 서버", + modal_confirmmentions: "읽지 않은 모든 멘션을 삭제 하시겠습니까?", + modal_confirmnotifications: "읽지 않은 모든 알림을 삭제 하시겠습니까?", + toast_alreadyclearing: "이미 일부 멘션을 삭제합니다.", + toast_cleared: "모든 최근 멘션이 삭제되었습니다.", + toast_clearing: "최근 멘션을 모두 지 웁니다." + }; + case "lt": // Lithuanian + return { + context_dms: "Tiesioginiai pranešimai", + context_guilds: "Visi serveriai", + context_mutedguilds: "Nutildyti serveriai", + context_pingedguilds: "„Pinged“ serveriai", + context_unreadguilds: "Neskaityti serveriai", + modal_confirmmentions: "Ar tikrai norite ištrinti visus neperskaitytus paminėjimus?", + modal_confirmnotifications: "Ar tikrai norite ištrinti visus neperskaitytus pranešimus?", + toast_alreadyclearing: "Kai kurie paminėjimai jau ištrinami", + toast_cleared: "Visi naujausi paminėjimai buvo ištrinti", + toast_clearing: "Išvalo visus naujausius paminėjimus" + }; + case "nl": // Dutch + return { + context_dms: "Directe berichten", + context_guilds: "Alle servers", + context_mutedguilds: "Gedempte servers", + context_pingedguilds: "Gepingde servers", + context_unreadguilds: "Ongelezen servers", + modal_confirmmentions: "Weet u zeker dat u alle ongelezen vermeldingen wilt verwijderen?", + modal_confirmnotifications: "Weet u zeker dat u alle ongelezen meldingen wilt verwijderen?", + toast_alreadyclearing: "Verwijdert al enkele vermeldingen", + toast_cleared: "Alle recente vermeldingen zijn verwijderd", + toast_clearing: "Wist alle recente vermeldingen" + }; + case "no": // Norwegian + return { + context_dms: "Direktemeldinger", + context_guilds: "Alle servere", + context_mutedguilds: "Dempede servere", + context_pingedguilds: "Pingede servere", + context_unreadguilds: "Uleste servere", + modal_confirmmentions: "Er du sikker på at du vil slette alle uleste omtaler?", + modal_confirmnotifications: "Er du sikker på at du vil slette alle uleste varsler?", + toast_alreadyclearing: "Sletter allerede noen omtaler", + toast_cleared: "Alle nylige omtaler er slettet", + toast_clearing: "Fjerner alle nylige omtaler" + }; + case "pl": // Polish + return { + context_dms: "Bezpośrednie wiadomości", + context_guilds: "Wszystkie serwery", + context_mutedguilds: "Wyciszone serwery", + context_pingedguilds: "Serwery pingowane", + context_unreadguilds: "Nieprzeczytane serwery", + modal_confirmmentions: "Czy na pewno chcesz usunąć wszystkie nieprzeczytane wzmianki?", + modal_confirmnotifications: "Czy na pewno chcesz usunąć wszystkie nieprzeczytane powiadomienia?", + toast_alreadyclearing: "Usuwa już niektóre wzmianki", + toast_cleared: "Wszystkie ostatnie wzmianki zostały usunięte", + toast_clearing: "Usuwa wszystkie ostatnie wzmianki" + }; + case "pt-BR": // Portuguese (Brazil) + return { + context_dms: "Mensagens diretas", + context_guilds: "Todos os servidores", + context_mutedguilds: "Servidores Silenciados", + context_pingedguilds: "Servidores com ping", + context_unreadguilds: "Servidores não lidos", + modal_confirmmentions: "Tem certeza de que deseja excluir todas as menções não lidas?", + modal_confirmnotifications: "Tem certeza de que deseja excluir todas as notificações não lidas?", + toast_alreadyclearing: "Exclui algumas menções já", + toast_cleared: "Todas as menções recentes foram excluídas", + toast_clearing: "Limpa todas as menções recentes" + }; + case "ro": // Romanian + return { + context_dms: "Mesaje directe", + context_guilds: "Toate serverele", + context_mutedguilds: "Servere mutate", + context_pingedguilds: "Servere pinged", + context_unreadguilds: "Servere necitite", + modal_confirmmentions: "Sigur doriți să ștergeți toate mențiunile necitite?", + modal_confirmnotifications: "Sigur doriți să ștergeți toate notificările necitite?", + toast_alreadyclearing: "Șterge deja câteva mențiuni", + toast_cleared: "Toate mențiunile recente au fost șterse", + toast_clearing: "Șterge toate mențiunile recente" + }; + case "ru": // Russian + return { + context_dms: "Прямые сообщения", + context_guilds: "Все серверы", + context_mutedguilds: "Отключенные серверы", + context_pingedguilds: "Проверенные серверы", + context_unreadguilds: "Непрочитанные серверы", + modal_confirmmentions: "Вы уверены, что хотите удалить все непрочитанные упоминания?", + modal_confirmnotifications: "Вы действительно хотите удалить все непрочитанные уведомления?", + toast_alreadyclearing: "Удаляет уже некоторые упоминания", + toast_cleared: "Все недавние упоминания были удалены", + toast_clearing: "Удаляет все недавние упоминания" + }; + case "sv": // Swedish + return { + context_dms: "Direktmeddelanden", + context_guilds: "Alla servrar", + context_mutedguilds: "Dämpade servrar", + context_pingedguilds: "Pingade servrar", + context_unreadguilds: "Olästa servrar", + modal_confirmmentions: "Är du säker på att du vill ta bort alla olästa omnämnanden?", + modal_confirmnotifications: "Är du säker på att du vill ta bort alla olästa aviseringar?", + toast_alreadyclearing: "Raderar några omnämnanden redan", + toast_cleared: "Alla nya omnämnanden har tagits bort", + toast_clearing: "Rensar alla senaste omnämnanden" + }; + case "th": // Thai + return { + context_dms: "ข้อความโดยตรง", + context_guilds: "เซิร์ฟเวอร์ทั้งหมด", + context_mutedguilds: "เซิร์ฟเวอร์ที่ปิดเสียง", + context_pingedguilds: "เซิร์ฟเวอร์ Pinged", + context_unreadguilds: "เซิร์ฟเวอร์ที่ยังไม่ได้อ่าน", + modal_confirmmentions: "แน่ใจไหมว่าต้องการลบข้อความที่ยังไม่ได้อ่านทั้งหมด", + modal_confirmnotifications: "แน่ใจไหมว่าต้องการลบการแจ้งเตือนที่ยังไม่ได้อ่านทั้งหมด", + toast_alreadyclearing: "ลบการกล่าวถึงบางส่วนแล้ว", + toast_cleared: "ลบการกล่าวถึงล่าสุดทั้งหมดแล้ว", + toast_clearing: "ล้างการพูดถึงล่าสุดทั้งหมด" + }; + case "tr": // Turkish + return { + context_dms: "Direkt Mesajlar", + context_guilds: "Tüm Sunucular", + context_mutedguilds: "Sessiz Sunucular", + context_pingedguilds: "Ping Gönderilen Sunucular", + context_unreadguilds: "Okunmamış Sunucular", + modal_confirmmentions: "Okunmamış tüm bahisleri silmek istediğinizden emin misiniz?", + modal_confirmnotifications: "Okunmamış tüm bildirimleri silmek istediğinizden emin misiniz?", + toast_alreadyclearing: "Zaten bazı bahsetmeleri siler", + toast_cleared: "Son bahsedenlerin tümü silindi", + toast_clearing: "Tüm son bahsedilenleri temizler" + }; + case "uk": // Ukrainian + return { + context_dms: "Прямі повідомлення", + context_guilds: "Усі сервери", + context_mutedguilds: "Приглушені сервери", + context_pingedguilds: "Pinged сервери", + context_unreadguilds: "Непрочитані сервери", + modal_confirmmentions: "Ви впевнені, що хочете видалити всі непрочитані згадки?", + modal_confirmnotifications: "Ви впевнені, що хочете видалити всі непрочитані сповіщення?", + toast_alreadyclearing: "Видаляє деякі згадки вже", + toast_cleared: "Усі останні згадування були видалені", + toast_clearing: "Очищає всі останні згадування" + }; + case "vi": // Vietnamese + return { + context_dms: "Tin nhắn trực tiếp", + context_guilds: "Tất cả máy chủ", + context_mutedguilds: "Máy chủ bị tắt tiếng", + context_pingedguilds: "Máy chủ Pinged", + context_unreadguilds: "Máy chủ chưa đọc", + modal_confirmmentions: "Bạn có chắc chắn muốn xóa tất cả các đề cập chưa đọc không?", + modal_confirmnotifications: "Bạn có chắc chắn muốn xóa tất cả các thông báo chưa đọc không?", + toast_alreadyclearing: "Đã xóa một số đề cập", + toast_cleared: "Tất cả các đề cập gần đây đã bị xóa", + toast_clearing: "Xóa tất cả các đề cập gần đây" + }; + case "zh-CN": // Chinese (China) + return { + context_dms: "直接讯息", + context_guilds: "所有服务器", + context_mutedguilds: "静音服务器", + context_pingedguilds: "绑定服务器", + context_unreadguilds: "未读服务器", + modal_confirmmentions: "您确定要删除所有未读的提及吗?", + modal_confirmnotifications: "您确定要删除所有未读的通知吗?", + toast_alreadyclearing: "已删除一些提及", + toast_cleared: "最近所有提及的内容均已删除", + toast_clearing: "清除所有最近提及的内容" + }; + case "zh-TW": // Chinese (Taiwan) + return { + context_dms: "直接訊息", + context_guilds: "所有服務器", + context_mutedguilds: "靜音服務器", + context_pingedguilds: "綁定服務器", + context_unreadguilds: "未讀服務器", + modal_confirmmentions: "您確定要刪除所有未讀的提及嗎?", + modal_confirmnotifications: "您確定要刪除所有未讀的通知嗎?", + toast_alreadyclearing: "已刪除一些提及", + toast_cleared: "最近所有提及的內容均已刪除", + toast_clearing: "清除所有最近提及的內容" + }; + default: // English + return { + context_dms: "Direct Messages", + context_guilds: "All Servers", + context_mutedguilds: "Muted Servers", + context_pingedguilds: "Pinged Servers", + context_unreadguilds: "Unread Servers", + modal_confirmmentions: "Are you sure you want to delete all unread Mentions?", + modal_confirmnotifications: "Are you sure you want to delete all unread Notifications?", + toast_alreadyclearing: "Already clearing some Mentions", + toast_cleared: "All recent Mentions have been cleared", + toast_clearing: "Clearing all recent Mentions" + }; + } + } + }; + })(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog)); +})(); +\ No newline at end of file diff --git a/files/discord/plugins/ShowHiddenChannels.plugin.js b/files/discord/plugins/ShowHiddenChannels.plugin.js @@ -9,7 +9,6 @@ * @patreon https://www.patreon.com/MircoWittrien * @website https://mwittrien.github.io/ * @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ShowHiddenChannels/ - * @updateUrl https://mwittrien.github.io/BetterDiscordAddons/Plugins/ShowHiddenChannels/ShowHiddenChannels.plugin.js */ module.exports = (_ => { diff --git a/files/discord/plugins/SplitLargeMessages.plugin.js b/files/discord/plugins/SplitLargeMessages.plugin.js @@ -0,0 +1,350 @@ +/** + * @name SplitLargeMessages + * @author DevilBro + * @authorId 278543574059057154 + * @version 1.8.0 + * @description Allows you to enter larger Messages, which will automatically split into several smaller Messages + * @invite Jx3TjNS + * @donate https://www.paypal.me/MircoWittrien + * @patreon https://www.patreon.com/MircoWittrien + * @website https://mwittrien.github.io/ + * @source https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/SplitLargeMessages/ + */ + +module.exports = (_ => { + const changeLog = { + + }; + + return !window.BDFDB_Global || (!window.BDFDB_Global.loaded && !window.BDFDB_Global.started) ? class { + constructor (meta) {for (let key in meta) this[key] = meta[key];} + getName () {return this.name;} + getAuthor () {return this.author;} + getVersion () {return this.version;} + getDescription () {return `The Library Plugin needed for ${this.name} is missing. Open the Plugin Settings to download it. \n\n${this.description}`;} + + downloadLibrary () { + require("request").get("https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js", (e, r, b) => { + if (!e && b && r.statusCode == 200) require("fs").writeFile(require("path").join(BdApi.Plugins.folder, "0BDFDB.plugin.js"), b, _ => BdApi.showToast("Finished downloading BDFDB Library", {type: "success"})); + else BdApi.alert("Error", "Could not download BDFDB Library Plugin. Try again later or download it manually from GitHub: https://mwittrien.github.io/downloader/?library"); + }); + } + + load () { + if (!window.BDFDB_Global || !Array.isArray(window.BDFDB_Global.pluginQueue)) window.BDFDB_Global = Object.assign({}, window.BDFDB_Global, {pluginQueue: []}); + if (!window.BDFDB_Global.downloadModal) { + window.BDFDB_Global.downloadModal = true; + BdApi.showConfirmationModal("Library Missing", `The Library Plugin needed for ${this.name} is missing. Please click "Download Now" to install it.`, { + confirmText: "Download Now", + cancelText: "Cancel", + onCancel: _ => {delete window.BDFDB_Global.downloadModal;}, + onConfirm: _ => { + delete window.BDFDB_Global.downloadModal; + this.downloadLibrary(); + } + }); + } + if (!window.BDFDB_Global.pluginQueue.includes(this.name)) window.BDFDB_Global.pluginQueue.push(this.name); + } + start () {this.load();} + stop () {} + getSettingsPanel () { + let template = document.createElement("template"); + template.innerHTML = `<div style="color: var(--header-primary); font-size: 16px; font-weight: 300; white-space: pre; line-height: 22px;">The Library Plugin needed for ${this.name} is missing.\nPlease click <a style="font-weight: 500;">Download Now</a> to install it.</div>`; + template.content.firstElementChild.querySelector("a").addEventListener("click", this.downloadLibrary); + return template.content.firstElementChild; + } + } : (([Plugin, BDFDB]) => { + const messageDelay = 1000; //changing at own risk, might result in bans or mutes + let maxMessageLength = 2000; + + return class SplitLargeMessages extends Plugin { + onLoad () { + this.defaults = { + general: { + byNewlines: {value: false, description: "Try to split Messages on Newlines instead of Spaces", note: "This will stop Sentences from being cut, but might result in more Messages being sent"}, + }, + amounts: { + splitCounter: {value: 0, description: "Messages will be split after roughly X Characters"}, + } + }; + + this.modulePatches = { + before: [ + "ChannelTextAreaContainer", + "ChannelTextAreaEditor" + ], + after: [ + "ChannelTextAreaContainer" + ] + }; + + this.css = ` + ${BDFDB.dotCN.textareacharcounterupsell} { + display: none; + } + `; + } + + onStart () { + maxMessageLength = BDFDB.LibraryModules.NitroUtils.canUseIncreasedMessageLength(BDFDB.LibraryStores.UserStore.getCurrentUser()) ? BDFDB.DiscordConstants.MAX_MESSAGE_LENGTH_PREMIUM : BDFDB.DiscordConstants.MAX_MESSAGE_LENGTH; + + BDFDB.PatchUtils.patch(this, BDFDB.LibraryModules.ChatRestrictionUtils, "applyChatRestrictions", {before: e => { + if (e.methodArguments[0] && e.methodArguments[0].content && !this.isSlowDowned(e.methodArguments[0].channel)) e.methodArguments[0].content = "_"; + }}); + + BDFDB.PatchUtils.forceAllUpdates(this); + } + + onStop () { + BDFDB.PatchUtils.forceAllUpdates(this); + } + + getSettingsPanel (collapseStates = {}) { + let settingsPanel; + return settingsPanel = BDFDB.PluginUtils.createSettingsPanel(this, { + collapseStates: collapseStates, + children: _ => { + let settingsItems = []; + + for (let key in this.defaults.general) settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, { + type: "Switch", + plugin: this, + keys: ["general", key], + label: this.defaults.general[key].description, + note: this.defaults.general[key].note, + value: this.settings.general[key] + })); + + settingsItems.push(BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.SettingsSaveItem, { + type: "TextInput", + childProps: { + type: "number" + }, + plugin: this, + keys: ["amounts", "splitCounter"], + label: this.defaults.amounts.splitCounter.description, + basis: "20%", + min: 1000, + max: maxMessageLength, + value: this.settings.amounts.splitCounter < 1000 || this.settings.amounts.splitCounter > maxMessageLength ? maxMessageLength : this.settings.amounts.splitCounter + })); + + return settingsItems; + } + }); + } + + onSettingsClosed (e) { + if (this.SettingsUpdated) { + delete this.SettingsUpdated; + BDFDB.PatchUtils.forceAllUpdates(this); + } + } + + processChannelTextAreaContainer (e) { + if (e.instance.props.type != BDFDB.DiscordConstants.ChannelTextAreaTypes.NORMAL && e.instance.props.type != BDFDB.DiscordConstants.ChannelTextAreaTypes.NORMAL_WITH_ACTIVITY && e.instance.props.type != BDFDB.LibraryComponents.ChannelTextAreaTypes.SIDEBAR) return; + const splitMessageLength = this.settings.amounts.splitCounter < 1000 || this.settings.amounts.splitCounter > maxMessageLength ? maxMessageLength : this.settings.amounts.splitCounter; + if (!e.returnvalue) { + BDFDB.PatchUtils.patch(this, e.instance.props, "onSubmit", {instead: e2 => { + if (e2.methodArguments[0].value.length > splitMessageLength && !this.isSlowDowned(e.instance.props.channel)) { + e2.stopOriginalMethodCall(); + let messages = this.formatText(e2.methodArguments[0].value).filter(n => n); + for (let i in messages) BDFDB.TimeUtils.timeout(_ => { + let last = i >= messages.length-1; + e2.originalMethod(last ? Object.assign({}, e2.methodArguments[0], {value: messages[i]}) : {stickers: [], uploads: [], value: messages[i]}); + if (i >= messages.length-1) BDFDB.NotificationUtils.toast(this.labels.toast_allsent, {type: "success"}); + }, messageDelay * i * (messages > 4 ? 2 : 1)); + return Promise.resolve({ + shouldClear: true, + shouldRefocus: true + }); + } + else return e2.callOriginalMethodAfterwards(); + }}, {noCache: true}); + } + else { + let [children, index] = BDFDB.ReactUtils.findParent(e.returnvalue, {name: "ChannelTextAreaCounter"}); + if (index > -1 && children[index].props.textValue && children[index].props.textValue.length > splitMessageLength && !this.isSlowDowned(e.instance.props.channel)) children[index] = BDFDB.ReactUtils.createElement("div", { + className: BDFDB.disCNS.textareacharcounter + BDFDB.disCN.textareacharcountererror, + children: BDFDB.ReactUtils.createElement(BDFDB.LibraryComponents.TooltipContainer, { + text: Math.ceil(children[index].props.textValue.length / splitMessageLength * (39/40)) + " " + BDFDB.LanguageUtils.LanguageStrings.MESSAGES, + children: BDFDB.ReactUtils.createElement("span", { + children: splitMessageLength - children[index].props.textValue.length + }) + }) + }); + } + } + + processChannelTextAreaEditor (e) { + if (e.instance.props.type == BDFDB.DiscordConstants.ChannelTextAreaTypes.NORMAL || e.instance.props.type == BDFDB.DiscordConstants.ChannelTextAreaTypes.NORMAL_WITH_ACTIVITY || e.instance.props.type == BDFDB.LibraryComponents.ChannelTextAreaTypes.SIDEBAR) e.instance.props.uploadPromptCharacterCount = 999999999999999; + } + + isSlowDowned (channel) { + return channel.rateLimitPerUser && !BDFDB.UserUtils.can("MANAGE_CHANNELS", BDFDB.UserUtils.me.id, channel.id) && !BDFDB.UserUtils.can("MANAGE_MESSAGES", BDFDB.UserUtils.me.id, channel.id); + } + + formatText (text) { + const separator = !this.settings.general.byNewlines ? "\n" : " "; + const splitMessageLength = this.settings.amounts.splitCounter < 1000 || this.settings.amounts.splitCounter > maxMessageLength ? maxMessageLength : this.settings.amounts.splitCounter; + + text = text.replace(/\t/g, " "); + let longWords = text.match(new RegExp(`[^${separator.replace("\n", "\\n")}]{${splitMessageLength * (19/20)},}`, "gm")); + if (longWords) for (let longWord of longWords) { + let count1 = 0; + let shortWords = []; + longWord.split("").forEach(c => { + if (shortWords[count1] && (shortWords[count1].length >= splitMessageLength * (19/20) || (c == "\n" && shortWords[count1].length >= splitMessageLength * (19/20) - 100))) count1++; + shortWords[count1] = shortWords[count1] ? shortWords[count1] + c : c; + }); + text = text.replace(longWord, shortWords.join(separator)); + } + let messages = []; + let count2 = 0; + text.split(separator).forEach((word) => { + if (messages[count2] && (messages[count2] + "" + word).length > splitMessageLength * (39/40)) count2++; + messages[count2] = messages[count2] ? messages[count2] + separator + word : word; + }); + + let insertCodeBlock = null, insertCodeLine = null; + for (let j = 0; j < messages.length; j++) { + if (insertCodeBlock) { + messages[j] = insertCodeBlock + messages[j]; + insertCodeBlock = null; + } + else if (insertCodeLine) { + messages[j] = insertCodeLine + messages[j]; + insertCodeLine = null; + } + + let codeBlocks = messages[j].match(/`{3,}[\S]*\n|`{3,}/gm); + let codeLines = messages[j].match(/[^`]{0,1}`{1,2}[^`]|[^`]`{1,2}[^`]{0,1}/gm); + + if (codeBlocks && codeBlocks.length % 2 == 1) { + messages[j] = messages[j] + "```"; + insertCodeBlock = codeBlocks[codeBlocks.length-1] + "\n"; + } + else if (codeLines && codeLines.length % 2 == 1) { + insertCodeLine = codeLines[codeLines.length-1].replace(/[^`]/g, ""); + messages[j] = messages[j] + insertCodeLine; + } + } + return messages; + } + + setLabelsByLanguage () { + switch (BDFDB.LanguageUtils.getLanguage().id) { + case "bg": // Bulgarian + return { + toast_allsent: "Всички изпратени съобщения" + }; + case "da": // Danish + return { + toast_allsent: "Alle beskeder sendt" + }; + case "de": // German + return { + toast_allsent: "Alle Nachrichten gesendet" + }; + case "el": // Greek + return { + toast_allsent: "Όλα τα μηνύματα εστάλησαν" + }; + case "es": // Spanish + return { + toast_allsent: "Todos los mensajes enviados" + }; + case "fi": // Finnish + return { + toast_allsent: "Kaikki viestit lähetetty" + }; + case "fr": // French + return { + toast_allsent: "Tous les messages envoyés" + }; + case "hr": // Croatian + return { + toast_allsent: "Sve poruke poslane" + }; + case "hu": // Hungarian + return { + toast_allsent: "Minden üzenet elküldve" + }; + case "it": // Italian + return { + toast_allsent: "Tutti i messaggi inviati" + }; + case "ja": // Japanese + return { + toast_allsent: "送信されたすべてのメッセージ" + }; + case "ko": // Korean + return { + toast_allsent: "보낸 모든 메시지" + }; + case "lt": // Lithuanian + return { + toast_allsent: "Visi pranešimai išsiųsti" + }; + case "nl": // Dutch + return { + toast_allsent: "Alle berichten zijn verzonden" + }; + case "no": // Norwegian + return { + toast_allsent: "Alle meldinger sendt" + }; + case "pl": // Polish + return { + toast_allsent: "Wszystkie wiadomości wysłane" + }; + case "pt-BR": // Portuguese (Brazil) + return { + toast_allsent: "Todas as mensagens enviadas" + }; + case "ro": // Romanian + return { + toast_allsent: "Toate mesajele trimise" + }; + case "ru": // Russian + return { + toast_allsent: "Все сообщения отправлены" + }; + case "sv": // Swedish + return { + toast_allsent: "Alla meddelanden skickade" + }; + case "th": // Thai + return { + toast_allsent: "ส่งข้อความทั้งหมดแล้ว" + }; + case "tr": // Turkish + return { + toast_allsent: "Tüm mesajlar gönderildi" + }; + case "uk": // Ukrainian + return { + toast_allsent: "Усі повідомлення надіслано" + }; + case "vi": // Vietnamese + return { + toast_allsent: "Tất cả tin nhắn đã gửi" + }; + case "zh-CN": // Chinese (China) + return { + toast_allsent: "已发送所有消息" + }; + case "zh-TW": // Chinese (Taiwan) + return { + toast_allsent: "已發送所有消息" + }; + default: // English + return { + toast_allsent: "All Messages sent" + }; + } + } + }; + })(window.BDFDB_Global.PluginUtils.buildPlugin(changeLog)); +})(); diff --git a/files/discord/plugins/TypingUsersAvatars.plugin.js b/files/discord/plugins/TypingUsersAvatars.plugin.js @@ -1,81 +1,89 @@ - /** - * @name TypingUsersAvatars - * @source https://github.com/QWERTxD/BetterDiscordPlugins/blob/main/TypingUsersAvatars/TypingUsersAvatars.plugin.js - * @updateUrl https://raw.githubusercontent.com/QWERTxD/BetterDiscordPlugins/main/TypingUsersAvatars/TypingUsersAvatars.plugin.js - * @website https://github.com/QWERTxD/BetterDiscordPlugins/tree/main/TypingUsersAvatars - * @version 1.0.2 - * @description Shows avatars of typing users. - */ - - const request = require('request'); - const fs = require('fs'); - const path = require('path'); - - const config = { - info: { - name: 'TypingUsersAvatars', - authors: [ - { - name: 'QWERT' - } - ], - version: '1.0.2', - description: 'Shows avatars of typing users.', - }, - changelog: [ - { - title: 'Fixed', - type: 'fixed', - items: [ - 'the crashing issue' - ] +/** +* @name TypingUsersAvatars +* @source https://github.com/QWERTxD/BetterDiscordPlugins/blob/main/TypingUsersAvatars/TypingUsersAvatars.plugin.js +* @website https://github.com/QWERTxD/BetterDiscordPlugins/tree/main/TypingUsersAvatars +* @version 1.0.5 +* @description Shows avatars of typing users. +*/ + +const request = require('request'); +const fs = require('fs'); +const path = require('path'); + +const config = { + info: { + name: 'TypingUsersAvatars', + authors: [ + { + name: 'QWERT' + } + ], + version: '1.0.5', + description: 'Shows avatars of typing users.', + github_raw: "https://raw.githubusercontent.com/QWERTxD/BetterDiscordPlugins/main/TypingUsersAvatars/TypingUsersAvatars.plugin.js", + }, + changelog: [ + { + title: 'What\'s new?', + type: 'added', + items: [ + 'Added option to show guild avatars of typing users', + ] + } + ], + defaultConfig: [ + { + type: 'switch', + name: 'Show users status', + id: 'showStatus', + value: true + }, + { + type: 'switch', + name: 'Show guild avatars', + id: 'showGuildAvatar', + value: true + } + ] +}; + +module.exports = !global.ZeresPluginLibrary ? class { + constructor() { + this._config = config; + } + + load() { + BdApi.showConfirmationModal('Library plugin is needed', + `The library plugin needed for AQWERT'sPluginBuilder is missing. Please click Download Now to install it.`, { + confirmText: 'Download', + cancelText: 'Cancel', + onConfirm: () => { + request.get('https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js', (error, response, body) => { + if (error) + return electron.shell.openExternal('https://betterdiscord.net/ghdl?url=https://raw.githubusercontent.com/rauenzi/BDPluginLibrary/master/release/0PluginLibrary.plugin.js'); + + fs.writeFileSync(path.join(BdApi.Plugins.folder, '0PluginLibrary.plugin.js'), body); + }); } - ], - defaultConfig: [ - { - type: 'switch', - name: 'Show users status', - id: 'showStatus', - value: true - } - ] - }; - - module.exports = !global.ZeresPluginLibrary ? class { - constructor() { - this._config = config; - } - - load() { - BdApi.showConfirmationModal('Library plugin is needed', - `The library plugin needed for AQWERT'sPluginBuilder is missing. Please click Download Now to install it.`, { - confirmText: 'Download', - cancelText: 'Cancel', - onConfirm: () => { - request.get('https://rauenzi.github.io/BDPluginLibrary/release/0PluginLibrary.plugin.js', (error, response, body) => { - if (error) - return electron.shell.openExternal('https://betterdiscord.net/ghdl?url=https://raw.githubusercontent.com/rauenzi/BDPluginLibrary/master/release/0PluginLibrary.plugin.js'); - - fs.writeFileSync(path.join(BdApi.Plugins.folder, '0PluginLibrary.plugin.js'), body); - }); - } - }); - } - - start() { } - - stop() { } - } : (([Plugin, Library]) => { - const { DiscordModules, WebpackModules, PluginUtilities, Patcher, ReactComponents, Popouts, Utilities, DiscordSelectors } = Library; - const { React, UserStore, RelationshipStore, UserStatusStore, Strings } = DiscordModules; - const Avatar = WebpackModules.getByProps('AnimatedAvatar'); - const VoiceUserSummary = WebpackModules.findByDisplayName("VoiceUserSummaryItem") - - class AvatarComponent extends React.Component { - render() { - const {user, status} = this.props; - return React.createElement(Avatar.default, { - src: user.getAvatarURL(), + }); + } + + start() { } + + stop() { } +} : (([Plugin, Library]) => { + const { DiscordModules, WebpackModules, PluginUtilities, Patcher, ReactComponents, Popouts, Utilities, DiscordSelectors } = Library; + const { React, UserStore, RelationshipStore, UserStatusStore, Strings } = DiscordModules; + const AssetUtils = WebpackModules.getByProps("getUserBannerURL"); + const Avatar = WebpackModules.getByProps('AnimatedAvatar'); + const VoiceUserSummary = WebpackModules.findByDisplayName("VoiceUserSummaryItem") + + class AvatarComponent extends React.Component { + render() { + const { user, status, guildId } = this.props; + const guildAvatar = AssetUtils.getGuildMemberAvatarURL({ guildId: guildId, userId: user.id, avatar: user.guildMemberAvatars[guildId] }); + return React.createElement(Avatar.default, { + src: user?.guildMemberAvatars[guildId] ? guildAvatar : user.getAvatarURL(), status: status, size: Avatar.Sizes.SIZE_16, onClick() { @@ -83,100 +91,103 @@ } }) } + } + + class plugin extends Plugin { + constructor() { + super(); + this.getSettingsPanel = () => { + return this.buildSettingsPanel().getElement(); + }; } - - class plugin extends Plugin { - constructor() { - super(); - this.getSettingsPanel = () => { - return this.buildSettingsPanel().getElement(); - }; - } - - onStart() { - Utilities.suppressErrors(this.patch.bind(this))(); - - PluginUtilities.addStyle('TypingUsersAvatars', ` - .typing-2GQL18 > .text-1y-e8- { + + onStart() { + Utilities.suppressErrors(this.patch.bind(this))(); + + PluginUtilities.addStyle('TypingUsersAvatars', ` + .typing-2J1mQU .text-3S7XCz { margin: 0; } - - .typing-2GQL18 .wrapper-3t9DeA { + + .typing-2J1mQU .wrapper-1VLyxH { display: flex; margin: 0 4px; } - - .typing-2GQL18 > .text-1y-e8-, - .typing-2GQL18 > .text-1y-e8- > strong { + + .typing-2J1mQU .text-3S7XCz, + .typing-2J1mQU .text-3S7XCz > strong { display: contents; } - + .several-users { margin-left: 5px; margin-right: 5px; } - - .several-users > .avatarSize-EXG1Is { + + .several-users .avatarSize-1KpZ5E { margin: 0; } - `) - } - - onStop() { - Patcher.unpatchAll(); - PluginUtilities.removeStyle('TypingUsersAvatars'); - } - - filter(users) { - return Object.keys(users).filter((user) => { - return user != UserStore.getCurrentUser().id && !RelationshipStore.isBlocked(user); - }) - } - - /* code highly inspired by https://github.com/rauenzi/BetterDiscordAddons/blob/master/Plugins/BetterRoleColors/BetterRoleColors.plugin.js */ - async patch() { - const TypingUsers = await ReactComponents.getComponentByName('TypingUsers', DiscordSelectors.Typing.typing); - Patcher.after(TypingUsers.component.prototype, 'render', (thisObject, [props], ret) => { - const typingUsers = this.filter({...thisObject.props.typingUsers}); - - for (let u = 0; u < typingUsers.length; u++) { - const user = UserStore.getUser(typingUsers[u]); - const status = this.settings.showStatus ? UserStatusStore.getStatus(user.id) : null; - if(ret.props.children[1].props.children !== Strings.SEVERAL_USERS_TYPING) { - ret.props.children[1].props.children[2* u].props.children.unshift(React.createElement("div", { - id: `typing-user-${user.id}`, - children: React.createElement(AvatarComponent, {user, status}) - })); - }else{ - ret.props.children[1].props.children = [ - React.createElement(VoiceUserSummary, { - className: "several-users", - users: typingUsers.map(UserStore.getUser), - max: 3 - }), - ret.props.children[1].props.children - ] - - } + `) + } + + onStop() { + Patcher.unpatchAll(); + PluginUtilities.removeStyle('TypingUsersAvatars'); + } + + filter(users) { + return Object.keys(users).filter((user) => { + return user != UserStore.getCurrentUser().id && !RelationshipStore.isBlocked(user); + }) + } + + /* code highly inspired by https://github.com/rauenzi/BetterDiscordAddons/blob/master/Plugins/BetterRoleColors/BetterRoleColors.plugin.js */ + async patch() { + const TypingUsers = await ReactComponents.getComponentByName('TypingUsers', DiscordSelectors.Typing.typing); + Patcher.after(TypingUsers.component.prototype, 'render', (thisObject, [props], ret) => { + const typingUsers = this.filter({ ...thisObject.props.typingUsers }); + const guildId = thisObject.props?.guildId; + + for (let u = 0; u < typingUsers.length; u++) { + const user = UserStore.getUser(typingUsers[u]); + const status = this.settings.showStatus ? UserStatusStore.getStatus(user.id) : null; + + if (ret.props.children[0].props.children[1]?.props.children !== Strings.Messages.SEVERAL_USERS_TYPING) { + const usersComponent = ret.props.children[0].props.children[1].props.children.filter(user => user.props); + + usersComponent[u].props.children.unshift(React.createElement("div", { + id: `typing-user-${user.id}`, + children: React.createElement(AvatarComponent, { user, status, guildId }) + })); + } else { + ret.props.children[0].props.children = [ + React.createElement(VoiceUserSummary, { + className: "several-users", + users: typingUsers.map(UserStore.getUser), + max: 3 + }), + ret.props.children[0].props.children + ] } - - if(!ret) return; - const tree = ret.props.children; - if(!tree) return; - - tree.map((child) => { - const children = child?.props?.children; - if(!children || typeof children !== 'object') return; - - child.props.style = { - display: 'flex', - alignItems: 'center' - }; - }) - }) - } - - } - - return plugin; - })(global.ZeresPluginLibrary.buildPlugin(config)); -\ No newline at end of file + } + + if (!ret) return; + const tree = ret.props.children; + if (!tree) return; + + tree.map((child) => { + const children = child?.props?.children; + if (!children || typeof children !== 'object') return; + + child.props.style = { + display: 'flex', + alignItems: 'center' + }; + }) + }) + } + + } + + return plugin; +})(global.ZeresPluginLibrary.buildPlugin(config)); diff --git a/modules/apps/flatpak.nix b/modules/apps/flatpak.nix @@ -31,7 +31,7 @@ in { }; install = mkOption { description = "Application Derivation"; - apply = url: fetchAppFromFlatHub url; + apply = fetchAppFromFlatHub; }; }; })); diff --git a/site/content/anime.md b/site/content/anime.md @@ -54,6 +54,7 @@ comments = true - Rent-a-Girlfriend <sup>\*</sup> - RikeKoi <sup>#</sup> - Scums Wish <sup>\*</sup> +- Senryu Girl - Spy X Family <sup>\*</sup> <sup>#</sup> - Steins;Gate <sup>#</sup> - Sword Art Online <sup>#</sup> @@ -74,7 +75,9 @@ comments = true # Ongoing +- [x] BLUE LOCK - [x] Tomo-chan wa Onnanoko! +- [x] Koori Zokusei Danshi to Cool na Douryou Joshi # Manhua @@ -99,9 +102,9 @@ comments = true - [ ] Hyouka - [ ] One Outs - [x] Chainsaw Man -- [ ] Jujutsu Kaisen -- [x] Tokyo Revengers -- [ ] Attack on Titan +- [ ] Jujutsu Kaisen <sup>#</sup> +- [x] Tokyo Revengers <sup>#</sup> +- [ ] Attack on Titan <sup>#</sup> - [ ] A Place Further than the Universe --- diff --git a/site/content/now.md b/site/content/now.md @@ -12,4 +12,4 @@ This page is inspired by [NowNowNow](https://nownownow.com) Nothing much else really! ;) -> Last Updated: **January** 2023 +> Last Updated: **February** 2023