From 5c5b009c4180b73603a9c3a6c6663f889a2e2062 Mon Sep 17 00:00:00 2001 From: V Date: Fri, 12 May 2023 01:40:43 +0200 Subject: [PATCH] Settings: Fix resetting scroll/search when getting a ping (#1106) --- src/Vencord.ts | 3 - src/api/index.ts | 5 + src/components/PluginSettings/index.tsx | 19 ++-- ...RestoreTab.tsx => BackupAndRestoreTab.tsx} | 11 ++- src/components/VencordSettings/CloudTab.tsx | 9 +- .../PatchHelperTab.tsx} | 13 ++- src/components/VencordSettings/PluginsTab.tsx | 5 +- src/components/VencordSettings/ThemesTab.tsx | 15 +-- .../{Updater.tsx => UpdaterTab.tsx} | 14 +-- src/components/VencordSettings/VencordTab.tsx | 9 +- src/components/VencordSettings/index.tsx | 96 ------------------- .../VencordSettings/settingsStyles.css | 2 - src/components/VencordSettings/shared.tsx | 51 ++++++++++ src/components/index.ts | 21 ---- src/plugins/settings.tsx | 20 ++-- 15 files changed, 110 insertions(+), 183 deletions(-) rename src/components/VencordSettings/{BackupRestoreTab.tsx => BackupAndRestoreTab.tsx} (89%) rename src/components/{PatchHelper.tsx => VencordSettings/PatchHelperTab.tsx} (96%) rename src/components/VencordSettings/{Updater.tsx => UpdaterTab.tsx} (95%) delete mode 100644 src/components/VencordSettings/index.tsx create mode 100644 src/components/VencordSettings/shared.tsx delete mode 100644 src/components/index.ts diff --git a/src/Vencord.ts b/src/Vencord.ts index 76719e570..a05ec5383 100644 --- a/src/Vencord.ts +++ b/src/Vencord.ts @@ -37,8 +37,6 @@ import { checkForUpdates, update, UpdateLogger } from "./utils/updater"; import { onceReady } from "./webpack"; import { SettingsRouter } from "./webpack/common"; -export let Components: any; - async function syncSettings() { if ( Settings.cloud.settingsSync && // if it's enabled @@ -65,7 +63,6 @@ async function syncSettings() { async function init() { await onceReady; startAllPlugins(); - Components = await import("./components"); syncSettings(); diff --git a/src/api/index.ts b/src/api/index.ts index ba2978ee6..f2c47e559 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -28,6 +28,7 @@ import * as $MessagePopover from "./MessagePopover"; import * as $Notices from "./Notices"; import * as $Notifications from "./Notifications"; import * as $ServerList from "./ServerList"; +import * as $Settings from "./Settings"; import * as $SettingsStore from "./SettingsStore"; import * as $Styles from "./Styles"; @@ -86,6 +87,10 @@ export const MessageDecorations = $MessageDecorations; * An API allowing you to add components to member list users, in both DM's and servers */ export const MemberListDecorators = $MemberListDecorators; +/** + * An API allowing you to persist data + */ +export const Settings = $Settings; /** * An API allowing you to read, manipulate and automatically update components based on Discord settings */ diff --git a/src/components/PluginSettings/index.tsx b/src/components/PluginSettings/index.tsx index 3fb9bb445..8ccc74073 100644 --- a/src/components/PluginSettings/index.tsx +++ b/src/components/PluginSettings/index.tsx @@ -20,20 +20,18 @@ import "./styles.css"; import * as DataStore from "@api/DataStore"; import { showNotice } from "@api/Notices"; -import { useSettings } from "@api/Settings"; +import { Settings, useSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; -import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; -import { handleComponentFailed } from "@components/handleComponentFailed"; import { Badge } from "@components/PluginSettings/components"; import PluginModal from "@components/PluginSettings/PluginModal"; import { Switch } from "@components/Switch"; +import { SettingsTab } from "@components/VencordSettings/shared"; import { ChangeList } from "@utils/ChangeList"; import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { openModalLazy } from "@utils/modal"; -import { onlyOnce } from "@utils/onlyOnce"; import { LazyComponent, useAwaiter } from "@utils/react"; import { Plugin } from "@utils/types"; import { findByCode, findByPropsLazy } from "@webpack"; @@ -96,7 +94,7 @@ interface PluginCardProps extends React.HTMLProps { } function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, onMouseLeave, isNew }: PluginCardProps) { - const settings = useSettings([`plugins.${plugin.name}.enabled`]).plugins[plugin.name]; + const settings = Settings.plugins[plugin.name]; const isEnabled = () => settings.enabled ?? false; @@ -179,7 +177,7 @@ enum SearchStatus { DISABLED } -export default ErrorBoundary.wrap(function PluginSettings() { +export default function PluginSettings() { const settings = useSettings(); const changes = React.useMemo(() => new ChangeList(), []); @@ -303,7 +301,7 @@ export default ErrorBoundary.wrap(function PluginSettings() { } return ( - + @@ -342,12 +340,9 @@ export default ErrorBoundary.wrap(function PluginSettings() {
{requiredPlugins}
-
+ ); -}, { - message: "Failed to render the Plugin Settings. If this persists, try using the installer to reinstall!", - onError: onlyOnce(handleComponentFailed), -}); +} function makeDependencyList(deps: string[]) { return ( diff --git a/src/components/VencordSettings/BackupRestoreTab.tsx b/src/components/VencordSettings/BackupAndRestoreTab.tsx similarity index 89% rename from src/components/VencordSettings/BackupRestoreTab.tsx rename to src/components/VencordSettings/BackupAndRestoreTab.tsx index 173747026..a9a1c9fec 100644 --- a/src/components/VencordSettings/BackupRestoreTab.tsx +++ b/src/components/VencordSettings/BackupAndRestoreTab.tsx @@ -16,16 +16,17 @@ * along with this program. If not, see . */ -import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { downloadSettingsBackup, uploadSettingsBackup } from "@utils/settingsSync"; -import { Button, Card, Forms, Text } from "@webpack/common"; +import { Button, Card, Text } from "@webpack/common"; + +import { SettingsTab, wrapTab } from "./shared"; function BackupRestoreTab() { return ( - + Warning @@ -59,8 +60,8 @@ function BackupRestoreTab() { Export Settings - + ); } -export default ErrorBoundary.wrap(BackupRestoreTab); +export default wrapTab(BackupRestoreTab, "Backup & Restore"); diff --git a/src/components/VencordSettings/CloudTab.tsx b/src/components/VencordSettings/CloudTab.tsx index 5e48a72d3..77e5298b5 100644 --- a/src/components/VencordSettings/CloudTab.tsx +++ b/src/components/VencordSettings/CloudTab.tsx @@ -19,13 +19,14 @@ import { showNotification } from "@api/Notifications"; import { Settings, useSettings } from "@api/Settings"; import { CheckedTextInput } from "@components/CheckedTextInput"; -import ErrorBoundary from "@components/ErrorBoundary"; import { Link } from "@components/Link"; import { authorizeCloud, cloudLogger, deauthorizeCloud, getCloudAuth, getCloudUrl } from "@utils/cloud"; import { Margins } from "@utils/margins"; import { deleteCloudSettings, getCloudSettings, putCloudSettings } from "@utils/settingsSync"; import { Alerts, Button, Forms, Switch, Tooltip } from "@webpack/common"; +import { SettingsTab, wrapTab } from "./shared"; + function validateUrl(url: string) { try { new URL(url); @@ -114,7 +115,7 @@ function CloudTab() { const settings = useSettings(["cloud.authenticated", "cloud.url"]); return ( - <> + Vencord comes with a cloud integration that adds goodies like settings sync across devices. @@ -157,8 +158,8 @@ function CloudTab() { - + ); } -export default ErrorBoundary.wrap(CloudTab); +export default wrapTab(CloudTab, "Cloud"); diff --git a/src/components/PatchHelper.tsx b/src/components/VencordSettings/PatchHelperTab.tsx similarity index 96% rename from src/components/PatchHelper.tsx rename to src/components/VencordSettings/PatchHelperTab.tsx index 6c95a8a2c..d5bd94ce1 100644 --- a/src/components/PatchHelper.tsx +++ b/src/components/VencordSettings/PatchHelperTab.tsx @@ -16,16 +16,16 @@ * along with this program. If not, see . */ +import { CheckedTextInput } from "@components/CheckedTextInput"; import { debounce } from "@utils/debounce"; import { Margins } from "@utils/margins"; import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches"; import { makeCodeblock } from "@utils/text"; import { ReplaceFn } from "@utils/types"; import { search } from "@webpack"; -import { Button, Clipboard, Forms, Parser, React, Switch, Text, TextInput } from "@webpack/common"; +import { Button, Clipboard, Forms, Parser, React, Switch, TextInput } from "@webpack/common"; -import { CheckedTextInput } from "./CheckedTextInput"; -import ErrorBoundary from "./ErrorBoundary"; +import { SettingsTab, wrapTab } from "./shared"; // Do not include diff in non dev builds (side effects import) if (IS_DEV) { @@ -258,8 +258,7 @@ function PatchHelper() { } return ( - - Patch Helper + find Clipboard.copy(code)}>Copy to Clipboard )} - + ); } -export default IS_DEV ? ErrorBoundary.wrap(PatchHelper) : null; +export default IS_DEV ? wrapTab(PatchHelper, "PatchHelper") : null; diff --git a/src/components/VencordSettings/PluginsTab.tsx b/src/components/VencordSettings/PluginsTab.tsx index 04b5dc26f..6a320959f 100644 --- a/src/components/VencordSettings/PluginsTab.tsx +++ b/src/components/VencordSettings/PluginsTab.tsx @@ -16,7 +16,8 @@ * along with this program. If not, see . */ -import ErrorBoundary from "@components/ErrorBoundary"; import PluginSettings from "@components/PluginSettings"; -export default ErrorBoundary.wrap(PluginSettings); +import { wrapTab } from "./shared"; + +export default wrapTab(PluginSettings, "Plugins"); diff --git a/src/components/VencordSettings/ThemesTab.tsx b/src/components/VencordSettings/ThemesTab.tsx index 75fea349f..79ddc5099 100644 --- a/src/components/VencordSettings/ThemesTab.tsx +++ b/src/components/VencordSettings/ThemesTab.tsx @@ -17,13 +17,14 @@ */ import { useSettings } from "@api/Settings"; -import ErrorBoundary from "@components/ErrorBoundary"; import { Link } from "@components/Link"; import { Margins } from "@utils/margins"; import { useAwaiter } from "@utils/react"; import { findLazy } from "@webpack"; import { Card, Forms, React, TextArea } from "@webpack/common"; +import { SettingsTab, wrapTab } from "./shared"; + const TextAreaProps = findLazy(m => typeof m.textarea === "string"); function Validator({ link }: { link: string; }) { @@ -74,8 +75,8 @@ function Validators({ themeLinks }: { themeLinks: string[]; }) { ); } -export default ErrorBoundary.wrap(function () { - const settings = useSettings(); +function ThemesTab() { + const settings = useSettings(["themeLinks"]); const [themeText, setThemeText] = React.useState(settings.themeLinks.join("\n")); function onBlur() { @@ -89,7 +90,7 @@ export default ErrorBoundary.wrap(function () { } return ( - <> + Paste links to .theme.css files here One link per line @@ -124,6 +125,8 @@ export default ErrorBoundary.wrap(function () { onBlur={onBlur} /> - + ); -}); +} + +export default wrapTab(ThemesTab, "Themes"); diff --git a/src/components/VencordSettings/Updater.tsx b/src/components/VencordSettings/UpdaterTab.tsx similarity index 95% rename from src/components/VencordSettings/Updater.tsx rename to src/components/VencordSettings/UpdaterTab.tsx index 9345d272d..4d0b86c95 100644 --- a/src/components/VencordSettings/Updater.tsx +++ b/src/components/VencordSettings/UpdaterTab.tsx @@ -17,21 +17,20 @@ */ import { useSettings } from "@api/Settings"; -import ErrorBoundary from "@components/ErrorBoundary"; import { ErrorCard } from "@components/ErrorCard"; import { Flex } from "@components/Flex"; -import { handleComponentFailed } from "@components/handleComponentFailed"; import { Link } from "@components/Link"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { relaunch } from "@utils/native"; -import { onlyOnce } from "@utils/onlyOnce"; import { useAwaiter } from "@utils/react"; import { changes, checkForUpdates, getRepo, isNewer, update, updateError, UpdateLogger } from "@utils/updater"; import { Alerts, Button, Card, Forms, Parser, React, Switch, Toasts } from "@webpack/common"; import gitHash from "~git-hash"; +import { SettingsTab, wrapTab } from "./shared"; + function withDispatcher(dispatcher: React.Dispatch>, action: () => any) { return async () => { dispatcher(true); @@ -199,7 +198,7 @@ function Updater() { }; return ( - + Updater Settings Updates {isNewer ? : } - + ); } -export default IS_WEB ? null : ErrorBoundary.wrap(Updater, { - message: "Failed to render the Updater. If this persists, try using the installer to reinstall!", - onError: onlyOnce(handleComponentFailed), -}); +export default IS_WEB ? null : wrapTab(Updater, "Updater"); diff --git a/src/components/VencordSettings/VencordTab.tsx b/src/components/VencordSettings/VencordTab.tsx index 8c71821dd..1502bfabd 100644 --- a/src/components/VencordSettings/VencordTab.tsx +++ b/src/components/VencordSettings/VencordTab.tsx @@ -21,7 +21,6 @@ import { openNotificationLogModal } from "@api/Notifications/notificationLog"; import { Settings, useSettings } from "@api/Settings"; import { classNameFactory } from "@api/Styles"; import DonateButton from "@components/DonateButton"; -import ErrorBoundary from "@components/ErrorBoundary"; import { ErrorCard } from "@components/ErrorCard"; import { Margins } from "@utils/margins"; import { identity } from "@utils/misc"; @@ -29,6 +28,8 @@ import { relaunch, showItemInFolder } from "@utils/native"; import { useAwaiter } from "@utils/react"; import { Button, Card, Forms, React, Select, Slider, Switch } from "@webpack/common"; +import { SettingsTab, wrapTab } from "./shared"; + const cl = classNameFactory("vc-settings-"); const DEFAULT_DONATE_IMAGE = "https://cdn.discordapp.com/emojis/1026533090627174460.png"; @@ -97,7 +98,7 @@ function VencordSettings() { ]; return ( - + @@ -153,7 +154,7 @@ function VencordSettings() { {typeof Notification !== "undefined" && } - + ); } @@ -263,4 +264,4 @@ function DonateCard({ image }: DonateCardProps) { ); } -export default ErrorBoundary.wrap(VencordSettings); +export default wrapTab(VencordSettings, "Vencord Settings"); diff --git a/src/components/VencordSettings/index.tsx b/src/components/VencordSettings/index.tsx deleted file mode 100644 index 6d65aa165..000000000 --- a/src/components/VencordSettings/index.tsx +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import "./settingsStyles.css"; - -import { classNameFactory } from "@api/Styles"; -import ErrorBoundary from "@components/ErrorBoundary"; -import { handleComponentFailed } from "@components/handleComponentFailed"; -import { isMobile } from "@utils/misc"; -import { onlyOnce } from "@utils/onlyOnce"; -import { Forms, SettingsRouter, TabBar, Text } from "@webpack/common"; - -import BackupRestoreTab from "./BackupRestoreTab"; -import CloudTab from "./CloudTab"; -import PluginsTab from "./PluginsTab"; -import ThemesTab from "./ThemesTab"; -import Updater from "./Updater"; -import VencordSettings from "./VencordTab"; - -const cl = classNameFactory("vc-settings-"); - -interface SettingsProps { - tab: string; -} - -interface SettingsTab { - name: string; - component?: React.ComponentType; -} - -const SettingsTabs: Record = { - VencordSettings: { name: "Vencord", component: () => }, - VencordPlugins: { name: "Plugins", component: () => }, - VencordThemes: { name: "Themes", component: () => }, - VencordUpdater: { name: "Updater" }, // Only show updater if IS_WEB is false - VencordCloud: { name: "Cloud", component: () => }, - VencordSettingsSync: { name: "Backup & Restore", component: () => } -}; - -if (!IS_WEB) SettingsTabs.VencordUpdater.component = () => Updater && ; - -function Settings(props: SettingsProps) { - const { tab = "VencordSettings" } = props; - - const CurrentTab = SettingsTabs[tab]?.component ?? null; - if (isMobile) { - return CurrentTab && ; - } - - return - Vencord Settings - - - {Object.entries(SettingsTabs).map(([key, { name, component }]) => { - if (!component) return null; - return - {name} - ; - })} - - - {CurrentTab && } - ; -} - -const onError = onlyOnce(handleComponentFailed); - -export default function (props: SettingsProps) { - return - - ; -} diff --git a/src/components/VencordSettings/settingsStyles.css b/src/components/VencordSettings/settingsStyles.css index 3652756fc..f7d75e6c7 100644 --- a/src/components/VencordSettings/settingsStyles.css +++ b/src/components/VencordSettings/settingsStyles.css @@ -29,14 +29,12 @@ .vc-settings-card { padding: 1em; margin-bottom: 1em; - margin-top: 1em; } .vc-backup-restore-card { background-color: var(--info-warning-background); border-color: var(--info-warning-foreground); color: var(--info-warning-text); - margin-top: 0; } .vc-settings-theme-links { diff --git a/src/components/VencordSettings/shared.tsx b/src/components/VencordSettings/shared.tsx new file mode 100644 index 000000000..0d3910dfb --- /dev/null +++ b/src/components/VencordSettings/shared.tsx @@ -0,0 +1,51 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import "./settingsStyles.css"; + +import ErrorBoundary from "@components/ErrorBoundary"; +import { handleComponentFailed } from "@components/handleComponentFailed"; +import { Margins } from "@utils/margins"; +import { onlyOnce } from "@utils/onlyOnce"; +import { Forms, Text } from "@webpack/common"; +import type { ComponentType, PropsWithChildren } from "react"; + +export function SettingsTab({ title, children }: PropsWithChildren<{ title: string; }>) { + return ( + + + {title} + + + {children} + + ); +} + +const onError = onlyOnce(handleComponentFailed); + +export function wrapTab(component: ComponentType, tab: string) { + return ErrorBoundary.wrap(component, { + message: `Failed to render the ${tab} tab. If this issue persists, try using the installer to reinstall!`, + onError, + }); +} diff --git a/src/components/index.ts b/src/components/index.ts deleted file mode 100644 index 3ee53b02c..000000000 --- a/src/components/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -export { default as PatchHelper } from "./PatchHelper"; -export { default as PluginSettings } from "./PluginSettings"; -export { default as VencordSettings } from "./VencordSettings"; diff --git a/src/plugins/settings.tsx b/src/plugins/settings.tsx index c1dd315c8..2201ece1b 100644 --- a/src/plugins/settings.tsx +++ b/src/plugins/settings.tsx @@ -18,17 +18,13 @@ import { addContextMenuPatch } from "@api/ContextMenu"; import { Settings } from "@api/Settings"; -import PatchHelper from "@components/PatchHelper"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; -import { LazyComponent } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; -import { SettingsRouter } from "@webpack/common"; +import { React, SettingsRouter } from "@webpack/common"; import gitHash from "~git-hash"; -const SettingsComponent = LazyComponent(() => require("../components/VencordSettings").default); - export default definePlugin({ name: "Settings", description: "Adds Settings UI and debug info", @@ -95,37 +91,37 @@ export default definePlugin({ { section: "VencordSettings", label: "Vencord", - element: () => + element: require("@components/VencordSettings/VencordTab").default }, { section: "VencordPlugins", label: "Plugins", - element: () => , + element: require("@components/VencordSettings/PluginsTab").default, }, { section: "VencordThemes", label: "Themes", - element: () => , + element: require("@components/VencordSettings/ThemesTab").default, }, !IS_WEB && { section: "VencordUpdater", label: "Updater", - element: () => , + element: require("@components/VencordSettings/UpdaterTab").default, }, { section: "VencordCloud", label: "Cloud", - element: () => , + element: require("@components/VencordSettings/CloudTab").default, }, { section: "VencordSettingsSync", label: "Backup & Restore", - element: () => , + element: require("@components/VencordSettings/BackupAndRestoreTab").default, }, IS_DEV && { section: "VencordPatchHelper", label: "Patch Helper", - element: PatchHelper!, + element: require("@components/VencordSettings/PatchHelperTab").default, }, IS_VENCORD_DESKTOP && { section: "VencordDesktop",