diff --git a/assets/locales/en-us.json b/assets/locales/en-us.json index fb2d4b13..e54cb869 100644 --- a/assets/locales/en-us.json +++ b/assets/locales/en-us.json @@ -21,6 +21,10 @@ "mediaKeys": { "name": "Disable Media Keys", "note": "Prevents Discord from hijacking your media keys after playing a video." + }, + "bdContextMenu": { + "name": "Settings Context Menu", + "note": "Adds a BetterDiscord subsection to the settings context menu." } }, "window": { diff --git a/renderer/src/builtins/builtins.js b/renderer/src/builtins/builtins.js index 7e499675..bcbebef5 100644 --- a/renderer/src/builtins/builtins.js +++ b/renderer/src/builtins/builtins.js @@ -4,6 +4,7 @@ export {default as CustomCSS} from "./customcss"; export {default as VoiceDisconnect} from "./general/voicedisconnect"; export {default as MediaKeys} from "./general/mediakeys"; +export {default as BDContextMenu} from "./general/contextmenu"; // export {default as EmoteModule} from "./emotes/emotes"; // export {default as EmoteMenu} from "./emotes/emotemenu"; diff --git a/renderer/src/builtins/general/contextmenu.js b/renderer/src/builtins/general/contextmenu.js new file mode 100644 index 00000000..0fa3efff --- /dev/null +++ b/renderer/src/builtins/general/contextmenu.js @@ -0,0 +1,95 @@ +import Builtin from "@structs/builtin"; + +import Strings from "@modules/strings"; +import Settings from "@modules/settingsmanager"; +import Webpack from "@modules/webpackmodules"; + +import ContextMenuPatcher from "@modules/api/contextmenu"; +import pluginManager from "@modules/pluginmanager"; +import themeManager from "@modules/thememanager"; + + +const ContextMenu = new ContextMenuPatcher(); +const UserSettingsWindow = Webpack.getByProps("open", "updateAccount"); + +export default new class BDContextMenu extends Builtin { + get name() {return "BDContextMenu";} + get category() {return "general";} + get id() {return "bdContextMenu";} + + constructor() { + super(...arguments); + this.callback = this.callback.bind(this); + } + + enabled() { + this.patch = ContextMenu.patch("user-settings-cog", this.callback); + } + + disabled() { + this.patch?.(); + } + + callback(retVal) { + const items = Settings.collections.map(c => this.buildCollectionMenu(c)); + items.push({label: Strings.panels.updates, action: () => {this.openCategory("updates");}}); + if (Settings.get("settings", "customcss", "customcss")) items.push({label: Strings.panels.customcss, action: () => {this.openCategory("customcss");}}); + items.push(this.buildAddonMenu(Strings.panels.plugins, pluginManager)); + items.push(this.buildAddonMenu(Strings.panels.themes, themeManager)); + retVal?.props?.children?.props?.children?.[0].push(ContextMenu.buildItem({type: "separator"})); + retVal?.props?.children?.props?.children?.[0].push(ContextMenu.buildItem({type: "submenu", label: "BetterDiscord", items: items})); + } + + buildCollectionMenu(collection) { + return { + type: "submenu", + label: collection.name, + action: () => {this.openCategory(collection.name);}, + items: collection.settings.map(category => { + return { + type: "submenu", + label: category.name, + action: () => {this.openCategory(collection.name);}, + items: category.settings.filter(s => s.type === "switch" && !s.hidden && s.id !== this.id).map(setting => { + return { + type: "toggle", + label: setting.name, + disabled: setting.disabled, + active: Settings.get(collection.id, category.id, setting.id), + action: () => Settings.set(collection.id, category.id, setting.id, !Settings.get(collection.id, category.id, setting.id)) + }; + }) + }; + }) + }; + } + + /** + * + * @param {string} label + * @param {import("../../modules/addonmanager").default} manager + * @returns + */ + buildAddonMenu(label, manager) { + const names = manager.addonList.map(a => a.name || a.getName()).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); + return { + type: "submenu", + label: label, + action: () => {this.openCategory(label.toLowerCase());}, + items: names.map(name => { + return { + type: "toggle", + label: name, + disabled: manager.getAddon(name)?.partial ?? false, + active: manager.isEnabled(name), + action: () => {manager.toggleAddon(name);} + }; + }) + }; + } + + async openCategory(id) { + ContextMenu.close(); + UserSettingsWindow?.open?.(id); + } +}; \ No newline at end of file diff --git a/renderer/src/data/settings.js b/renderer/src/data/settings.js index f2eea77e..96a1dfdc 100644 --- a/renderer/src/data/settings.js +++ b/renderer/src/data/settings.js @@ -6,7 +6,8 @@ export default [ settings: [ {type: "switch", id: "voiceDisconnect", value: false}, {type: "switch", id: "showToasts", value: true}, - {type: "switch", id: "mediaKeys", value: false} + {type: "switch", id: "mediaKeys", value: false}, + {type: "switch", id: "bdContextMenu", value: true} ] }, {