diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 3abc7a681..a6496440f 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -159,6 +159,13 @@ export default definePlugin({ match: /(\i)\.buildLayout\(\)(?=\.map)/, replace: "$self.buildLayout($1)" } + }, + { + find: "getWebUserSettingFromSection", + replacement: { + match: /new Map\(\[(?=\[.{0,10}\.ACCOUNT,.{0,10}\.ACCOUNT_PANEL)/, + replace: "new Map([...$self.getSettingsSectionMappings()," + } } ], @@ -190,6 +197,22 @@ export default definePlugin({ }); }, + getSettingsSectionMappings() { + return [ + ["EquicordSettings", "equicord_main_panel"], + ["EquicordPlugins", "equicord_plugins_panel"], + ["EquicordThemes", "equicord_themes_panel"], + ["EquicordUpdater", "equicord_updater_panel"], + ["EquicordChangelog", "equicord_changelog_panel"], + ["EquicordCloud", "equicord_cloud_panel"], + ["EquicordBackupAndRestore", "equicord_backup_restore_panel"], + ["EquicordPatchHelper", "equicord_patch_helper_panel"], + ["EquicordDiscordIcons", "equicord_icon_viewer"], + ["EquicordThemeLibrary", "equicord_theme_library"], + ["EquicordIRememberYou", "equicord_i_remember_you"], + ]; + }, + buildLayout(originalLayoutBuilder: SettingsLayoutBuilder) { const layout = originalLayoutBuilder.buildLayout(); if (originalLayoutBuilder.key !== "$Root") return layout; @@ -199,7 +222,7 @@ export default definePlugin({ const { buildEntry } = this; - const vencordEntries: SettingsLayoutNode[] = [ + const equicordEntries: SettingsLayoutNode[] = [ buildEntry({ key: "equicord_main", title: "Equicord", @@ -266,11 +289,11 @@ export default definePlugin({ }) ].filter(isTruthy); - const vencordSection: SettingsLayoutNode = { + const equicordSection: SettingsLayoutNode = { key: "equicord_section", type: LayoutTypes.SECTION, useLabel: () => "Equicord", - buildLayout: () => vencordEntries + buildLayout: () => equicordEntries }; const { settingsLocation } = settings.store; @@ -293,7 +316,7 @@ export default definePlugin({ idx += 1; } - layout.splice(idx, 0, vencordSection); + layout.splice(idx, 0, equicordSection); return layout; }, @@ -351,7 +374,7 @@ export default definePlugin({ className: "vc-cloud", }, { - section: "settings/tabsSync", + section: "EquicordBackupAndRestore", label: "Backup & Restore", searchableTitles: ["Backup & Restore"], element: BackupAndRestoreTab, diff --git a/src/plugins/betterSettings/fullHeightContext.css b/src/plugins/betterSettings/fullHeightContext.css new file mode 100644 index 000000000..97069dc9c --- /dev/null +++ b/src/plugins/betterSettings/fullHeightContext.css @@ -0,0 +1,10 @@ +/* + * Discord has dumb max height logic for their context menus. + * If a context menu is at the bottom of the screen, its submenus are capped to its max height and can't even grow upwards + * We unset the variable they use to cap height. This allows submenus to grow as tall as they want + */ + +#user-settings-cog, +[aria-activedescendant^="user-settings-cog"] { + --reference-position-layer-max-height: initial !important; +} \ No newline at end of file diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 4744359d2..9c6fafd63 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -5,16 +5,17 @@ */ import { definePluginSettings } from "@api/Settings"; -import { classNameFactory } from "@api/Styles"; +import { classNameFactory, disableStyle, enableStyle } from "@api/Styles"; import { buildPluginMenuEntries, buildThemeMenuEntries } from "@equicordplugins/equicordToolbox/menu"; import { Devs } from "@utils/constants"; -import { getIntlMessage } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { waitFor } from "@webpack"; import { ComponentDispatch, FocusLock, Menu, useEffect, useRef } from "@webpack/common"; import type { HTMLAttributes, ReactElement } from "react"; +import fullHeightStyle from "./fullHeightContext.css?managed"; + type SettingsEntry = { section: string, label: string; }; const cl = classNameFactory(""); @@ -42,6 +43,11 @@ const settings = definePluginSettings({ } }); +interface TransformedSettingsEntry { + section: string; + items: SettingsEntry[]; +} + interface LayerProps extends HTMLAttributes { mode: "SHOWN" | "HIDDEN"; baseLayer?: boolean; @@ -81,6 +87,15 @@ export default definePlugin({ authors: [Devs.Kyuuhachi], settings, + start() { + if (settings.store.organizeMenu) + enableStyle(fullHeightStyle); + }, + + stop() { + disableStyle(fullHeightStyle); + }, + patches: [ { find: "this.renderArtisanalHack()", @@ -124,8 +139,8 @@ export default definePlugin({ find: "#{intl::USER_SETTINGS_ACTIONS_MENU_LABEL}", replacement: [ { - match: /=\[\];if\((\i)(?=\.forEach)/, - replace: "=$self.wrapMap([]);if($self.transformSettingsEntries($1)", + match: /=\[\];if\((\i)(?=\.forEach.{0,100}"logout"!==\i.{0,30}(\i)\.get\(\i\))/, + replace: "=$self.wrapMap([]);if($self.transformSettingsEntries($1,$2)", predicate: () => settings.store.organizeMenu }, { @@ -154,36 +169,34 @@ export default definePlugin({ return ; }, - transformSettingsEntries(list: SettingsEntry[]) { - const items = [{ label: null as string | null, items: [] as SettingsEntry[] }]; + transformSettingsEntries(list: SettingsEntry[], keyMap: Map) { + const items = [] as TransformedSettingsEntry[]; for (const item of list) { if (item.section === "HEADER") { - items.push({ label: item.label, items: [] }); - } else if (item.section === "DIVIDER") { - items.push({ label: getIntlMessage("OTHER_OPTIONS"), items: [] }); - } else { - items.at(-1)!.items.push(item); + keyMap.set(item.label, item.label); + items.push({ section: item.label, items: [] }); + } else if (item.section !== "DIVIDER" && keyMap.has(item.section)) { + items.at(-1)?.items.push(item); } } return items; }, - wrapMap(toWrap: any[]) { - const otherOptions = getIntlMessage("OTHER_OPTIONS"); + wrapMap(toWrap: TransformedSettingsEntry[]) { // @ts-expect-error toWrap.map = function (render: (item: SettingsEntry) => ReactElement) { return this - .filter(a => a.items.length > 0 && a.label !== otherOptions) - .map(({ label, items }) => { + .filter(a => a.items.length > 0) + .map(({ section, items }) => { const children = items.map(render); - if (label) { + if (section) { return ( {children}