diff --git a/.env b/.env index 9985bd8..ee45e88 100644 --- a/.env +++ b/.env @@ -11,9 +11,9 @@ REACT_APP_OPTIONSPAGE_DEV=http://localhost:3000/options.html REACT_APP_LOGOURL=https://fishjar.github.io/kiss-translator/images/logo192.png -REACT_APP_RULESURL=https://fishjar.github.io/kiss-rules/kiss-rules.json -REACT_APP_RULESURL_ON=https://fishjar.github.io/kiss-rules/kiss-rules-on.json -REACT_APP_RULESURL_OFF=https://fishjar.github.io/kiss-rules/kiss-rules-off.json +REACT_APP_RULESURL=https://fishjar.github.io/kiss-rules/kiss-rules_v2.json +REACT_APP_RULESURL_ON=https://fishjar.github.io/kiss-rules/kiss-rules-on_v2.json +REACT_APP_RULESURL_OFF=https://fishjar.github.io/kiss-rules/kiss-rules-off_v2.json REACT_APP_USERSCRIPT_DOWNLOADURL=https://fishjar.github.io/kiss-translator/kiss-translator.user.js REACT_APP_USERSCRIPT_IOS_DOWNLOADURL=https://fishjar.github.io/kiss-translator/kiss-translator-ios-safari.user.js diff --git a/src/config/app.js b/src/config/app.js index 234322e..2c8d4ee 100644 --- a/src/config/app.js +++ b/src/config/app.js @@ -7,5 +7,7 @@ export const APP_CONSTS = { boxID: `${APP_LCNAME}-box`, }; +export const APP_VERSION = process.env.REACT_APP_VERSION.split("."); + export const THEME_LIGHT = "light"; export const THEME_DARK = "dark"; diff --git a/src/config/i18n.js b/src/config/i18n.js index 74284b5..4a18f45 100644 --- a/src/config/i18n.js +++ b/src/config/i18n.js @@ -1402,4 +1402,9 @@ export const I18N = { en: `Whether to pre-initialize`, zh_TW: `是否預初始化`, }, + export_old: { + zh: `导出旧版`, + en: `Export old version`, + zh_TW: `匯出舊版`, + }, }; diff --git a/src/config/storage.js b/src/config/storage.js index 59423d1..b5e5227 100644 --- a/src/config/storage.js +++ b/src/config/storage.js @@ -1,16 +1,18 @@ -import { APP_NAME } from "./app"; +import { APP_NAME, APP_VERSION } from "./app"; -export const KV_RULES_KEY = "kiss-rules.json"; +export const KV_RULES_KEY = `kiss-rules_v${APP_VERSION[0]}.json`; export const KV_WORDS_KEY = "kiss-words.json"; -export const KV_RULES_SHARE_KEY = "kiss-rules-share.json"; -export const KV_SETTING_KEY = "kiss-setting.json"; +export const KV_RULES_SHARE_KEY = `kiss-rules-share_v${APP_VERSION[0]}.json`; +export const KV_SETTING_KEY = `kiss-setting_v${APP_VERSION[0]}.json`; export const KV_SALT_SYNC = "KISS-Translator-SYNC"; export const KV_SALT_SHARE = "KISS-Translator-SHARE"; export const STOKEY_MSAUTH = `${APP_NAME}_msauth`; export const STOKEY_BDAUTH = `${APP_NAME}_bdauth`; -export const STOKEY_SETTING = `${APP_NAME}_setting`; -export const STOKEY_RULES = `${APP_NAME}_rules`; +export const STOKEY_SETTING_OLD = `${APP_NAME}_setting`; +export const STOKEY_RULES_OLD = `${APP_NAME}_rules`; +export const STOKEY_SETTING = `${APP_NAME}_setting_v${APP_VERSION[0]}`; +export const STOKEY_RULES = `${APP_NAME}_rules_v${APP_VERSION[0]}`; export const STOKEY_WORDS = `${APP_NAME}_words`; export const STOKEY_SYNC = `${APP_NAME}_sync`; export const STOKEY_FAB = `${APP_NAME}_fab`; diff --git a/src/hooks/Alert.js b/src/hooks/Alert.js index 12e0684..817dd54 100644 --- a/src/hooks/Alert.js +++ b/src/hooks/Alert.js @@ -1,4 +1,11 @@ -import { createContext, useContext, useState, forwardRef } from "react"; +import { + createContext, + useContext, + useState, + forwardRef, + useCallback, + useMemo, +} from "react"; import Snackbar from "@mui/material/Snackbar"; import MuiAlert from "@mui/material/Alert"; @@ -18,32 +25,37 @@ export function AlertProvider({ children }) { const horizontal = "center"; const [open, setOpen] = useState(false); const [severity, setSeverity] = useState("info"); - const [message, setMessage] = useState(""); + const [message, setMessage] = useState(null); - const showAlert = (msg, type) => { + const showAlert = useCallback((msg, type) => { setOpen(true); setMessage(msg); setSeverity(type); - }; + }, []); - const handleClose = (_, reason) => { + const handleClose = useCallback((_, reason) => { if (reason === "clickaway") { return; } setOpen(false); - }; + }, []); - const error = (msg) => showAlert(msg, "error"); - const warning = (msg) => showAlert(msg, "warning"); - const info = (msg) => showAlert(msg, "info"); - const success = (msg) => showAlert(msg, "success"); + const value = useMemo( + () => ({ + error: (msg) => showAlert(msg, "error"), + warning: (msg) => showAlert(msg, "warning"), + info: (msg) => showAlert(msg, "info"), + success: (msg) => showAlert(msg, "success"), + }), + [showAlert] + ); return ( - + {children} diff --git a/src/libs/storage.js b/src/libs/storage.js index 9aefd7d..9db06fe 100644 --- a/src/libs/storage.js +++ b/src/libs/storage.js @@ -1,6 +1,8 @@ import { STOKEY_SETTING, + STOKEY_SETTING_OLD, STOKEY_RULES, + STOKEY_RULES_OLD, STOKEY_WORDS, STOKEY_FAB, STOKEY_SYNC, @@ -60,7 +62,12 @@ async function trySetObj(key, obj) { async function getObj(key) { const val = await get(key); - return val && JSON.parse(val); + try { + return JSON.parse(val); + } catch (err) { + kissLog("parse json: ", key); + } + return null; } async function putObj(key, obj) { @@ -86,6 +93,7 @@ export const storage = { * 设置信息 */ export const getSetting = () => getObj(STOKEY_SETTING); +export const getSettingOld = () => getObj(STOKEY_SETTING_OLD); export const getSettingWithDefault = async () => ({ ...DEFAULT_SETTING, ...((await getSetting()) || {}), @@ -97,6 +105,7 @@ export const putSetting = (obj) => putObj(STOKEY_SETTING, obj); * 规则列表 */ export const getRules = () => getObj(STOKEY_RULES); +export const getRulesOld = () => getObj(STOKEY_RULES_OLD); export const getRulesWithDefault = async () => (await getRules()) || DEFAULT_RULES; export const setRules = (val) => setObj(STOKEY_RULES, val); diff --git a/src/views/Options/Rules.js b/src/views/Options/Rules.js index ae5936b..58c839a 100644 --- a/src/views/Options/Rules.js +++ b/src/views/Options/Rules.js @@ -45,7 +45,11 @@ import { loadOrFetchSubRules } from "../../libs/subRules"; import { useAlert } from "../../hooks/Alert"; import { syncShareRules } from "../../libs/sync"; import { debounce } from "../../libs/utils"; -import { delSubRules, getSyncWithDefault } from "../../libs/storage"; +import { + delSubRules, + getSyncWithDefault, + getRulesOld, +} from "../../libs/storage"; import OwSubRule from "./OwSubRule"; import ClearAllIcon from "@mui/icons-material/ClearAll"; import HelpButton from "./HelpButton"; @@ -901,6 +905,11 @@ function UserRules({ subRules, rules }) { text={i18n("export")} fileName={`kiss-rules_${Date.now()}.json`} /> + JSON.stringify(await getRulesOld(), null, 2)} + text={i18n("export_old")} + fileName={`kiss-rules_v1_${Date.now()}.json`} + /> { try { @@ -1000,6 +1010,12 @@ function SubRulesItem({ await updateDataCache(url); } catch (err) { kissLog("sync sub rules", err); + alert.error( + <> +

Sync Error:

+
{err.message}
+ + ); } finally { setLoading(false); } diff --git a/src/views/Options/Setting.js b/src/views/Options/Setting.js index 7ff4892..82e0382 100644 --- a/src/views/Options/Setting.js +++ b/src/views/Options/Setting.js @@ -32,6 +32,7 @@ import { sendBgMsg } from "../../libs/msg"; import { kissLog } from "../../libs/log"; import UploadButton from "./UploadButton"; import DownloadButton from "./DownloadButton"; +import { getSettingOld } from "../../libs/storage"; function ShortcutItem({ action, label }) { const { shortcut, setShortcut } = useShortcut(action); @@ -137,6 +138,13 @@ export default function Settings() { text={i18n("export")} fileName={`kiss-setting_${Date.now()}.json`} /> + + JSON.stringify(await getSettingOld(), null, 2) + } + text={i18n("export_old")} + fileName={`kiss-setting_v1_${Date.now()}.json`} + /> diff --git a/src/views/Options/SyncSetting.js b/src/views/Options/SyncSetting.js index ef23103..65980d0 100644 --- a/src/views/Options/SyncSetting.js +++ b/src/views/Options/SyncSetting.js @@ -189,7 +189,7 @@ export default function SyncSetting() {