From 97f8d4d5154d566568fc475d6aaba5db07399b2b Mon Sep 17 00:00:00 2001 From: Lewis Crichton Date: Fri, 7 Apr 2023 01:27:18 +0100 Subject: feat: Cloud settings sync (#505) Co-authored-by: Ven --- src/components/VencordSettings/CloudTab.tsx | 164 ++++++++++++++++++++++ src/components/VencordSettings/index.tsx | 4 +- src/components/VencordSettings/settingsStyles.css | 11 ++ 3 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 src/components/VencordSettings/CloudTab.tsx (limited to 'src/components/VencordSettings') 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 . +*/ + +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 ( + + + Synchronize your settings to the cloud. This allows easy synchronization across multiple devices with + minimal effort. + + { cloud.settingsSync = v; }} + > + Settings Sync + +
+ + + {({ onMouseLeave, onMouseEnter }) => ( + + )} + + +
+
+ ); +} + +function CloudTab() { + const settings = useSettings(["cloud.authenticated", "cloud.url"]); + + return ( + <> + + + Vencord comes with a cloud integration that adds goodies like settings sync across devices. + It respects your privacy, and + the source code is AGPL 3.0 licensed so you + can host it yourself. + + { 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 + + Backend URL + + Which backend to use when using cloud integrations. + + { settings.cloud.url = v; settings.cloud.authenticated = false; deauthorizeCloud(); }} + validate={validateUrl} + /> + + + + + + ); +} + +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 = { VencordPlugins: { name: "Plugins", component: () => }, VencordThemes: { name: "Themes", component: () => }, VencordUpdater: { name: "Updater" }, // Only show updater if IS_WEB is false - VencordSettingsSync: { name: "Backup & Restore", component: () => }, + VencordCloud: { name: "Cloud", component: () => }, + VencordSettingsSync: { name: "Backup & Restore", component: () => } }; if (!IS_WEB) SettingsTabs.VencordUpdater.component = () => 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); +} -- cgit