diff options
author | Lewis Crichton <lewi@lewisakura.moe> | 2023-04-07 01:27:18 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-07 02:27:18 +0200 |
commit | 97f8d4d5154d566568fc475d6aaba5db07399b2b (patch) | |
tree | feafd22c26bdfc37a2d787e60f52bec94e777636 /src/components | |
parent | 2672dea8e361e8216b9459ac5dac97d36a47e412 (diff) | |
download | Vencord-97f8d4d5154d566568fc475d6aaba5db07399b2b.tar.gz Vencord-97f8d4d5154d566568fc475d6aaba5db07399b2b.tar.bz2 Vencord-97f8d4d5154d566568fc475d6aaba5db07399b2b.zip |
feat: Cloud settings sync (#505)
Co-authored-by: Ven <vendicated@riseup.net>
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/VencordSettings/CloudTab.tsx | 164 | ||||
-rw-r--r-- | src/components/VencordSettings/index.tsx | 4 | ||||
-rw-r--r-- | src/components/VencordSettings/settingsStyles.css | 11 |
3 files changed, 178 insertions, 1 deletions
diff --git a/src/components/VencordSettings/CloudTab.tsx b/src/components/VencordSettings/CloudTab.tsx new file mode 100644 index 0000000..3452cef --- /dev/null +++ b/src/components/VencordSettings/CloudTab.tsx @@ -0,0 +1,164 @@ +/* + * 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 <https://www.gnu.org/licenses/>. +*/ + +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"; + +function validateUrl(url: string) { + try { + new URL(url); + return true; + } catch { + return "Invalid URL"; + } +} + +async function eraseAllData() { + const res = await fetch(new URL("/v1/", getCloudUrl()), { + method: "DELETE", + headers: new Headers({ + Authorization: await getCloudAuth() + }) + }); + + if (!res.ok) { + cloudLogger.error(`Failed to erase data, API returned ${res.status}`); + showNotification({ + title: "Cloud Integrations", + body: `Could not erase all data (API returned ${res.status}), please contact support.`, + color: "var(--red-360)" + }); + return; + } + + Settings.cloud.authenticated = false; + await deauthorizeCloud(); + + showNotification({ + title: "Cloud Integrations", + body: "Successfully erased all data.", + color: "var(--green-360)" + }); +} + +function SettingsSyncSection() { + const { cloud } = useSettings(["cloud.authenticated", "cloud.settingsSync"]); + const sectionEnabled = cloud.authenticated && cloud.settingsSync; + + return ( + <Forms.FormSection title="Settings Sync" className={Margins.top16}> + <Forms.FormText variant="text-md/normal" className={Margins.bottom20}> + Synchronize your settings to the cloud. This allows easy synchronization across multiple devices with + minimal effort. + </Forms.FormText> + <Switch + key="cloud-sync" + disabled={!cloud.authenticated} + value={cloud.settingsSync} + onChange={v => { cloud.settingsSync = v; }} + > + Settings Sync + </Switch> + <div className="vc-cloud-settings-sync-grid"> + <Button + size={Button.Sizes.SMALL} + disabled={!sectionEnabled} + onClick={() => putCloudSettings()} + >Sync to Cloud</Button> + <Tooltip text="This will overwrite your local settings with the ones on the cloud. Use wisely!"> + {({ onMouseLeave, onMouseEnter }) => ( + <Button + onMouseLeave={onMouseLeave} + onMouseEnter={onMouseEnter} + size={Button.Sizes.SMALL} + color={Button.Colors.RED} + disabled={!sectionEnabled} + onClick={() => getCloudSettings(true, true)} + >Sync from Cloud</Button> + )} + </Tooltip> + <Button + size={Button.Sizes.SMALL} + color={Button.Colors.RED} + disabled={!sectionEnabled} + onClick={() => deleteCloudSettings()} + >Delete Cloud Settings</Button> + </div> + </Forms.FormSection> + ); +} + +function CloudTab() { + const settings = useSettings(["cloud.authenticated", "cloud.url"]); + + return ( + <> + <Forms.FormSection title="Cloud Settings" className={Margins.top16}> + <Forms.FormText variant="text-md/normal" className={Margins.bottom20}> + Vencord comes with a cloud integration that adds goodies like settings sync across devices. + It <Link href="https://vencord.dev/cloud/privacy">respects your privacy</Link>, and + the <Link href="https://github.com/Vencord/Backend">source code</Link> is AGPL 3.0 licensed so you + can host it yourself. + </Forms.FormText> + <Switch + key="backend" + value={settings.cloud.authenticated} + onChange={v => { v && authorizeCloud(); if (!v) settings.cloud.authenticated = v; }} + note="This will request authorization if you have not yet set up cloud integrations." + > + Enable Cloud Integrations + </Switch> + <Forms.FormTitle tag="h5">Backend URL</Forms.FormTitle> + <Forms.FormText className={Margins.bottom8}> + Which backend to use when using cloud integrations. + </Forms.FormText> + <CheckedTextInput + key="backendUrl" + value={settings.cloud.url} + onChange={v => { settings.cloud.url = v; settings.cloud.authenticated = false; deauthorizeCloud(); }} + validate={validateUrl} + /> + <Button + className={Margins.top8} + size={Button.Sizes.MEDIUM} + color={Button.Colors.RED} + disabled={!settings.cloud.authenticated} + onClick={() => Alerts.show({ + title: "Are you sure?", + body: "Once your data is erased, we cannot recover it. There's no going back!", + onConfirm: eraseAllData, + confirmText: "Erase it!", + confirmColor: "vc-cloud-erase-data-danger-btn", + cancelText: "Nevermind" + })} + >Erase All Data</Button> + <Forms.FormDivider className={Margins.top16} /> + </Forms.FormSection > + <SettingsSyncSection /> + </> + ); +} + +export default ErrorBoundary.wrap(CloudTab); diff --git a/src/components/VencordSettings/index.tsx b/src/components/VencordSettings/index.tsx index cd6ce60..c15944c 100644 --- a/src/components/VencordSettings/index.tsx +++ b/src/components/VencordSettings/index.tsx @@ -24,6 +24,7 @@ import { handleComponentFailed } from "@components/handleComponentFailed"; 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"; @@ -45,7 +46,8 @@ const SettingsTabs: Record<string, SettingsTab> = { VencordPlugins: { name: "Plugins", component: () => <PluginsTab /> }, VencordThemes: { name: "Themes", component: () => <ThemesTab /> }, VencordUpdater: { name: "Updater" }, // Only show updater if IS_WEB is false - VencordSettingsSync: { name: "Backup & Restore", component: () => <BackupRestoreTab /> }, + VencordCloud: { name: "Cloud", component: () => <CloudTab /> }, + VencordSettingsSync: { name: "Backup & Restore", component: () => <BackupRestoreTab /> } }; if (!IS_WEB) SettingsTabs.VencordUpdater.component = () => Updater && <Updater />; diff --git a/src/components/VencordSettings/settingsStyles.css b/src/components/VencordSettings/settingsStyles.css index 709c823..ebc112c 100644 --- a/src/components/VencordSettings/settingsStyles.css +++ b/src/components/VencordSettings/settingsStyles.css @@ -46,3 +46,14 @@ padding: 0.5em; border: 1px solid var(--background-modifier-accent); } + +.vc-cloud-settings-sync-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 1em; +} + +.vc-cloud-erase-data-danger-btn { + color: var(--white-500); + background-color: var(--button-danger-background); +} |