diff --git a/src/config/setting.js b/src/config/setting.js index e214e32..da7bdda 100644 --- a/src/config/setting.js +++ b/src/config/setting.js @@ -33,6 +33,7 @@ export const DEFAULT_CSPLIST = ["https://github.com"]; // 禁用CSP名单 // 同步设置 export const OPT_SYNCTYPE_WORKER = "KISS-Worker"; export const OPT_SYNCTYPE_WEBDAV = "WebDAV"; +export const OPT_SYNCTOKEN_PERFIX = "kt_"; export const OPT_SYNCTYPE_ALL = [OPT_SYNCTYPE_WORKER, OPT_SYNCTYPE_WEBDAV]; export const DEFAULT_SYNC = { syncType: OPT_SYNCTYPE_WORKER, // 同步方式 diff --git a/src/views/Options/SyncSetting.js b/src/views/Options/SyncSetting.js index b896639..d260596 100644 --- a/src/views/Options/SyncSetting.js +++ b/src/views/Options/SyncSetting.js @@ -7,18 +7,22 @@ import Alert from "@mui/material/Alert"; import Link from "@mui/material/Link"; import MenuItem from "@mui/material/MenuItem"; import LoadingButton from "@mui/lab/LoadingButton"; +import Button from "@mui/material/Button"; import { URL_KISS_WORKER, OPT_SYNCTYPE_ALL, OPT_SYNCTYPE_WORKER, OPT_SYNCTYPE_WEBDAV, + OPT_SYNCTOKEN_PERFIX, } from "../../config"; import { useState } from "react"; import { syncSettingAndRules } from "../../libs/sync"; import { useAlert } from "../../hooks/Alert"; -import SyncIcon from "@mui/icons-material/Sync"; import { useSetting } from "../../hooks/Setting"; import { kissLog } from "../../libs/log"; +import SyncIcon from "@mui/icons-material/Sync"; +import ContentCopyIcon from '@mui/icons-material/ContentCopy'; +import ContentPasteIcon from '@mui/icons-material/ContentPaste'; export default function SyncSetting() { const i18n = useI18n(); @@ -50,6 +54,57 @@ export default function SyncSetting() { } }; + const handleGenerateShareString = async () => { + try { + const base64Config = btoa(JSON.stringify({ + syncType: syncType, + syncUrl: syncUrl, + syncUser: syncUser, + syncKey: syncKey, + })); + const shareString = `${OPT_SYNCTOKEN_PERFIX}${base64Config}`; + await navigator.clipboard.writeText(shareString); + console.debug("Share string copied to clipboard", shareString); + } catch (error) { + console.error("Failed to copy share string to clipboard", error); + } + }; + + const handleImportFromClipboard = async () => { + try { + const text = await navigator.clipboard.readText(); + console.debug('read_clipboard', text) + if (text.startsWith(OPT_SYNCTOKEN_PERFIX)) { + const base64Config = text.slice(OPT_SYNCTOKEN_PERFIX.length); + const jsonString = atob(base64Config); + const updatedConfig = JSON.parse(jsonString); + + if (!OPT_SYNCTYPE_ALL.includes(updatedConfig.syncType)) { + console.error('error syncType', updatedConfig.syncType) + return; + } + + if ( + updatedConfig.syncUrl + ) { + updateSync({ + syncType: updatedConfig.syncType, + syncUrl: updatedConfig.syncUrl, + syncUser: updatedConfig.syncUser, + syncKey: updatedConfig.syncKey, + }); + } else { + console.error("Invalid config structure"); + } + } else { + console.error("Invalid share string", text); + } + } catch (error) { + console.error("Failed to read from clipboard or parse JSON", error); + } + }; + + if (!sync) { return; } @@ -133,6 +188,22 @@ export default function SyncSetting() { > {i18n("sync_now")} + +