From 6b55dee9fbba1a54cbe2ba1f2067e2d14190ab93 Mon Sep 17 00:00:00 2001 From: megumin Date: Fri, 25 Nov 2022 22:38:55 +0000 Subject: feat(settings): new settings design (#261) --- .../VencordSettings/BackupRestoreTab.tsx | 69 +++++++ src/components/VencordSettings/PluginsTab.tsx | 22 +++ src/components/VencordSettings/Updater.tsx | 216 +++++++++++++++++++++ src/components/VencordSettings/VencordTab.tsx | 134 +++++++++++++ src/components/VencordSettings/index.tsx | 84 ++++++++ src/components/VencordSettings/settingsStyles.css | 23 +++ 6 files changed, 548 insertions(+) create mode 100644 src/components/VencordSettings/BackupRestoreTab.tsx create mode 100644 src/components/VencordSettings/PluginsTab.tsx create mode 100644 src/components/VencordSettings/Updater.tsx create mode 100644 src/components/VencordSettings/VencordTab.tsx create mode 100644 src/components/VencordSettings/index.tsx create mode 100644 src/components/VencordSettings/settingsStyles.css (limited to 'src/components/VencordSettings') diff --git a/src/components/VencordSettings/BackupRestoreTab.tsx b/src/components/VencordSettings/BackupRestoreTab.tsx new file mode 100644 index 0000000..ce0bdaa --- /dev/null +++ b/src/components/VencordSettings/BackupRestoreTab.tsx @@ -0,0 +1,69 @@ +/* + * 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 { downloadSettingsBackup, uploadSettingsBackup } from "../../utils/settingsSync"; +import { Button, Card, Forms, Margins, Text } from "../../webpack/common"; +import ErrorBoundary from "../ErrorBoundary"; +import { Flex } from "../Flex"; + +function BackupRestoreTab() { + return ( + + + + Warning + Importing a settings file will overwrite your current settings. + + + + You can import and export your Vencord settings as a JSON file. + This allows you to easily transfer your settings to another device, + or recover your settings after reinstalling Vencord or Discord. + + + Settings Export contains: +
    +
  • — Custom QuickCSS
  • +
  • — Plugin Settings
  • +
+
+ + + + +
+ ); +} + +export default ErrorBoundary.wrap(BackupRestoreTab); diff --git a/src/components/VencordSettings/PluginsTab.tsx b/src/components/VencordSettings/PluginsTab.tsx new file mode 100644 index 0000000..0c89686 --- /dev/null +++ b/src/components/VencordSettings/PluginsTab.tsx @@ -0,0 +1,22 @@ +/* + * 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 ErrorBoundary from "../ErrorBoundary"; +import PluginSettings from "../PluginSettings"; + +export default ErrorBoundary.wrap(PluginSettings); diff --git a/src/components/VencordSettings/Updater.tsx b/src/components/VencordSettings/Updater.tsx new file mode 100644 index 0000000..8f2b75b --- /dev/null +++ b/src/components/VencordSettings/Updater.tsx @@ -0,0 +1,216 @@ +/* + * 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 gitHash from "~git-hash"; + +import { classes, useAwaiter } from "../../utils/misc"; +import { changes, checkForUpdates, getRepo, isNewer, rebuild, update, updateError, UpdateLogger } from "../../utils/updater"; +import { Alerts, Button, Card, Forms, Margins, Parser, React, Toasts } from "../../webpack/common"; +import ErrorBoundary from "../ErrorBoundary"; +import { ErrorCard } from "../ErrorCard"; +import { Flex } from "../Flex"; +import { handleComponentFailed } from "../handleComponentFailed"; +import { Link } from "../Link"; + +function withDispatcher(dispatcher: React.Dispatch>, action: () => any) { + return async () => { + dispatcher(true); + try { + await action(); + } catch (e: any) { + UpdateLogger.error("Failed to update", e); + if (!e) { + var err = "An unknown error occurred (error is undefined).\nPlease try again."; + } else if (e.code && e.cmd) { + const { code, path, cmd, stderr } = e; + + if (code === "ENOENT") + var err = `Command \`${path}\` not found.\nPlease install it and try again`; + else { + var err = `An error occured while running \`${cmd}\`:\n`; + err += stderr || `Code \`${code}\`. See the console for more info`; + } + + } else { + var err = "An unknown error occurred. See the console for more info."; + } + Alerts.show({ + title: "Oops!", + body: ( + + {err.split("\n").map(line =>
{Parser.parse(line)}
)} +
+ ) + }); + } + finally { + dispatcher(false); + } + }; +} + +interface CommonProps { + repo: string; + repoPending: boolean; +} + +function Changes({ updates, repo, repoPending }: CommonProps & { updates: typeof changes; }) { + return ( + + {updates.map(({ hash, author, message }) => ( +
+ + {hash} + + {message} - {author} +
+ ))} +
+ ); +} + +function Updatable(props: CommonProps) { + const [updates, setUpdates] = React.useState(changes); + const [isChecking, setIsChecking] = React.useState(false); + const [isUpdating, setIsUpdating] = React.useState(false); + + const isOutdated = (updates?.length ?? 0) > 0; + + return ( + <> + {!updates && updateError ? ( + <> + Failed to check updates. Check the console for more info + +

{updateError.stderr || updateError.stdout || "An unknown error occurred"}

+
+ + ) : ( + + {isOutdated ? `There are ${updates.length} Updates` : "Up to Date!"} + + )} + + {isOutdated && } + + + {isOutdated && } + + + + ); +} + +function Newer(props: CommonProps) { + return ( + <> + + Your local copy has more recent commits. Please stash or reset them. + + + + ); +} + +function Updater() { + const [repo, err, repoPending] = useAwaiter(getRepo, "Loading..."); + + React.useEffect(() => { + if (err) + UpdateLogger.error("Failed to retrieve repo", err); + }, [err]); + + const commonProps: CommonProps = { + repo, + repoPending + }; + + return ( + + Repo + + {repoPending ? repo : err ? "Failed to retrieve - check console" : ( + + {repo.split("/").slice(-2).join("/")} + + )} ({gitHash}) + + + + 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: handleComponentFailed, +}); diff --git a/src/components/VencordSettings/VencordTab.tsx b/src/components/VencordSettings/VencordTab.tsx new file mode 100644 index 0000000..94add5e --- /dev/null +++ b/src/components/VencordSettings/VencordTab.tsx @@ -0,0 +1,134 @@ +/* + * 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 { useSettings } from "../../api/settings"; +import IpcEvents from "../../utils/IpcEvents"; +import { useAwaiter } from "../../utils/misc"; +import { Button, Card, Forms, React, Switch } from "../../webpack/common"; +import DonateButton from "../DonateButton"; +import ErrorBoundary from "../ErrorBoundary"; + +const st = (style: string) => `vcSettings${style}`; + +function VencordSettings() { + const [settingsDir, , settingsDirPending] = useAwaiter(() => VencordNative.ipc.invoke(IpcEvents.GET_SETTINGS_DIR), "Loading..."); + const settings = useSettings(); + + return ( + + + + + {IS_WEB ? ( + + ) : ( + + + + + + + )} + + + + + + + settings.useQuickCss = v} + note="Loads styles from your QuickCss file"> + Use QuickCss + + {!IS_WEB && ( + + settings.enableReactDevtools = v} + note="Requires a full restart"> + Enable React Developer Tools + + settings.notifyAboutUpdates = v} + note="Shows a Toast on StartUp"> + Get notified about new Updates + + + )} + + + + ); +} + + + +function DonateCard() { + return ( + +
+ Support the Project + + Please consider supporting the Development of Vencord by donating! + + +
+ +
+ ); +} + +export default ErrorBoundary.wrap(VencordSettings); diff --git a/src/components/VencordSettings/index.tsx b/src/components/VencordSettings/index.tsx new file mode 100644 index 0000000..3701897 --- /dev/null +++ b/src/components/VencordSettings/index.tsx @@ -0,0 +1,84 @@ +/* + * 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 cssText from "~fileContent/settingsStyles.css"; + +import { lazyWebpack } from "../../utils/misc"; +import { filters } from "../../webpack"; +import { Forms, React, Router, Text } from "../../webpack/common"; +import ErrorBoundary from "../ErrorBoundary"; +import BackupRestoreTab from "./BackupRestoreTab"; +import PluginsTab from "./PluginsTab"; +import Updater from "./Updater"; +import VencordSettings from "./VencordTab"; + +const style = document.createElement("style"); +style.textContent = cssText; +document.head.appendChild(style); + +const st = (style: string) => `vcSettings${style}`; + +const TabBar = lazyWebpack(filters.byCode('[role="tab"][aria-disabled="false"]')); + +interface SettingsProps { + tab: string; +} + +const SettingsTabs = { + VencordSettings: { name: "Vencord", component: () => }, + VencordPlugins: { name: "Plugins", component: () => }, + VencordThemes: { name: "Themes", component: () => Coming soon to a Vencord near you! }, + VencordUpdater: { name: "Updater", component: () => Updater ? : null }, + VencordSettingsSync: { name: "Backup & Restore", component: () => }, +}; + + +function Settings(props: SettingsProps) { + const { tab = "VencordSettings" } = props; + + const CurrentTab = SettingsTabs[tab]?.component ?? null; + + return + Vencord Settings + + + {Object.entries(SettingsTabs).map(([key, { name }]) => { + return + {name} + ; + })} + + + + ; +} + +export default function (props: SettingsProps) { + return + + ; +} diff --git a/src/components/VencordSettings/settingsStyles.css b/src/components/VencordSettings/settingsStyles.css new file mode 100644 index 0000000..e90ef14 --- /dev/null +++ b/src/components/VencordSettings/settingsStyles.css @@ -0,0 +1,23 @@ +.vcSettingsTabBar { + margin-top: 20px; + margin-bottom: -2px; + border-bottom: 2px solid var(--background-modifier-accent); +} + +.vcSettingsTabBarItem { + margin-right: 32px; + padding-bottom: 16px; + margin-bottom: -2px; +} + +.vcSettingsQuickActionCard { + padding: 1em; + display: flex; + gap: 1em; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + flex-grow: 1; + flex-direction: row; + margin-bottom: 1em; +} -- cgit