dev......
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import { fetchPolyfill } from "../libs/fetch";
|
import { fetchPolyfill } from "../libs/fetch";
|
||||||
import {
|
import {
|
||||||
GLOBAL_KEY,
|
|
||||||
OPT_TRANS_GOOGLE,
|
OPT_TRANS_GOOGLE,
|
||||||
OPT_TRANS_MICROSOFT,
|
OPT_TRANS_MICROSOFT,
|
||||||
OPT_TRANS_OPENAI,
|
OPT_TRANS_OPENAI,
|
||||||
@@ -11,9 +10,8 @@ import {
|
|||||||
PROMPT_PLACE_TO,
|
PROMPT_PLACE_TO,
|
||||||
KV_SALT_SYNC,
|
KV_SALT_SYNC,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import { detectLang } from "../libs/browser";
|
import { detectLang } from "../libs";
|
||||||
import { sha256 } from "../libs/utils";
|
import { sha256 } from "../libs/utils";
|
||||||
import { checkRules } from "../libs/rules";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同步数据
|
* 同步数据
|
||||||
@@ -39,13 +37,8 @@ export const apiSyncData = async (url, key, data, isBg = false) =>
|
|||||||
* @param {*} isBg
|
* @param {*} isBg
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const apiFetchRules = async (url, isBg = false) => {
|
export const apiFetchRules = (url, isBg = false) =>
|
||||||
const res = await fetchPolyfill(url, { isBg });
|
fetchPolyfill(url, { isBg });
|
||||||
const rules = checkRules(res).filter(
|
|
||||||
(rule) => rule.pattern.replaceAll(GLOBAL_KEY, "") !== ""
|
|
||||||
);
|
|
||||||
return rules;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 谷歌翻译
|
* 谷歌翻译
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ export const DEFAULT_SUBRULES_LIST = [
|
|||||||
selected: true,
|
selected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: "https://fishjar.github.io/kiss-translator/kiss-translator-rules.json",
|
url: process.env.REACT_APP_RULESURL2,
|
||||||
selected: false,
|
selected: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function useDarkMode() {
|
|||||||
|
|
||||||
const toggleDarkMode = useCallback(async () => {
|
const toggleDarkMode = useCallback(async () => {
|
||||||
await updateSetting({ darkMode: !darkMode });
|
await updateSetting({ darkMode: !darkMode });
|
||||||
}, [darkMode]);
|
}, [darkMode, updateSetting]);
|
||||||
|
|
||||||
return { darkMode, toggleDarkMode };
|
return { darkMode, toggleDarkMode };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function useRules() {
|
|||||||
await updateSync({ rulesUpdateAt: updateAt });
|
await updateSync({ rulesUpdateAt: updateAt });
|
||||||
trySyncRules();
|
trySyncRules();
|
||||||
},
|
},
|
||||||
[rulesUpdateAt]
|
[rulesUpdateAt, save, updateSync]
|
||||||
);
|
);
|
||||||
|
|
||||||
const add = useCallback(
|
const add = useCallback(
|
||||||
@@ -87,39 +87,3 @@ export function useRules() {
|
|||||||
|
|
||||||
return { list, add, del, put, merge };
|
return { list, add, del, put, merge };
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 订阅规则
|
|
||||||
// * @returns
|
|
||||||
// */
|
|
||||||
// export function useSubrules() {
|
|
||||||
// const setting = useSetting();
|
|
||||||
// const updateSetting = useSettingUpdate();
|
|
||||||
// const list = setting?.subrulesList || DEFAULT_SUBRULES_LIST;
|
|
||||||
|
|
||||||
// const select = async (url) => {
|
|
||||||
// const subrulesList = [...list];
|
|
||||||
// subrulesList.forEach((item) => {
|
|
||||||
// if (item.url === url) {
|
|
||||||
// item.selected = true;
|
|
||||||
// } else {
|
|
||||||
// item.selected = false;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// await updateSetting({ subrulesList });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const add = async (url) => {
|
|
||||||
// const subrulesList = [...list];
|
|
||||||
// subrulesList.push({ url });
|
|
||||||
// await updateSetting({ subrulesList });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const del = async (url) => {
|
|
||||||
// let subrulesList = [...list];
|
|
||||||
// subrulesList = subrulesList.filter((item) => item.url !== url);
|
|
||||||
// await updateSetting({ subrulesList });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// return { list, select, add, del };
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function SettingProvider({ children }) {
|
|||||||
await updateSync({ settingUpdateAt: updateAt });
|
await updateSync({ settingUpdateAt: updateAt });
|
||||||
trySyncSetting();
|
trySyncSetting();
|
||||||
},
|
},
|
||||||
[settingUpdateAt]
|
[settingUpdateAt, update, updateSync]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -45,35 +45,3 @@ export function SettingProvider({ children }) {
|
|||||||
export function useSetting() {
|
export function useSetting() {
|
||||||
return useContext(SettingContext);
|
return useContext(SettingContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
// export function useSetting() {
|
|
||||||
// const [setting,setSeting]= useState(null);
|
|
||||||
// useEffect(()=>{
|
|
||||||
// (async ()=>{
|
|
||||||
// const
|
|
||||||
// })()
|
|
||||||
// },[])
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 设置hook
|
|
||||||
// * @returns
|
|
||||||
// */
|
|
||||||
// export function useSetting() {
|
|
||||||
// const storages = useStorages();
|
|
||||||
// return storages?.[STOKEY_SETTING];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 更新设置
|
|
||||||
// * @returns
|
|
||||||
// */
|
|
||||||
// export function useSettingUpdate() {
|
|
||||||
// const sync = useSync();
|
|
||||||
// return async (obj) => {
|
|
||||||
// const updateAt = sync.opt?.settingUpdateAt ? Date.now() : 0;
|
|
||||||
// await storage.putObj(STOKEY_SETTING, obj);
|
|
||||||
// await sync.update({ settingUpdateAt: updateAt });
|
|
||||||
// trySyncSetting();
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -33,83 +33,3 @@ export function useStorage(key, defaultVal = null) {
|
|||||||
|
|
||||||
return { data, save, update, remove };
|
return { data, save, update, remove };
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 默认配置
|
|
||||||
// */
|
|
||||||
// export const defaultStorage = {
|
|
||||||
// [STOKEY_SETTING]: DEFAULT_SETTING,
|
|
||||||
// [STOKEY_RULES]: DEFAULT_RULES,
|
|
||||||
// [STOKEY_SYNC]: DEFAULT_SYNC,
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const activeKeys = Object.keys(defaultStorage);
|
|
||||||
|
|
||||||
// const StoragesContext = createContext(null);
|
|
||||||
|
|
||||||
// export function StoragesProvider({ children }) {
|
|
||||||
// const [storages, setStorages] = useState(null);
|
|
||||||
|
|
||||||
// const handleChanged = (changes) => {
|
|
||||||
// if (isWeb || isGm) {
|
|
||||||
// const { key, oldValue, newValue } = changes;
|
|
||||||
// changes = {
|
|
||||||
// [key]: {
|
|
||||||
// oldValue,
|
|
||||||
// newValue,
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// const newStorages = {};
|
|
||||||
// Object.entries(changes)
|
|
||||||
// .filter(
|
|
||||||
// ([key, { oldValue, newValue }]) =>
|
|
||||||
// activeKeys.includes(key) && oldValue !== newValue
|
|
||||||
// )
|
|
||||||
// .forEach(([key, { newValue }]) => {
|
|
||||||
// newStorages[key] = JSON.parse(newValue);
|
|
||||||
// });
|
|
||||||
// if (Object.keys(newStorages).length !== 0) {
|
|
||||||
// setStorages((pre) => ({ ...pre, ...newStorages }));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// // 首次从storage同步配置到内存
|
|
||||||
// (async () => {
|
|
||||||
// const curStorages = {};
|
|
||||||
// for (const key of activeKeys) {
|
|
||||||
// const val = await storage.get(key);
|
|
||||||
// if (val) {
|
|
||||||
// curStorages[key] = JSON.parse(val);
|
|
||||||
// } else {
|
|
||||||
// await storage.setObj(key, defaultStorage[key]);
|
|
||||||
// curStorages[key] = defaultStorage[key];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// setStorages(curStorages);
|
|
||||||
// })();
|
|
||||||
|
|
||||||
// // 监听storage,并同步到内存中
|
|
||||||
// storage.onChanged(handleChanged);
|
|
||||||
|
|
||||||
// // 解除监听
|
|
||||||
// return () => {
|
|
||||||
// if (isExt) {
|
|
||||||
// browser.storage.onChanged.removeListener(handleChanged);
|
|
||||||
// } else {
|
|
||||||
// window.removeEventListener("storage", handleChanged);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// }, []);
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <StoragesContext.Provider value={storages}>
|
|
||||||
// {children}
|
|
||||||
// </StoragesContext.Provider>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export function useStorages() {
|
|
||||||
// return useContext(StoragesContext);
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,47 +1,81 @@
|
|||||||
import { DEFAULT_SUBRULES_LIST } from "../config";
|
import { DEFAULT_SUBRULES_LIST } from "../config";
|
||||||
import { useSetting } from "./Setting";
|
import { useSetting } from "./Setting";
|
||||||
import { useCallback } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
|
import { loadOrFetchSubRules } from "../libs/subRules";
|
||||||
|
import { delSubRules } from "../libs/storage";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订阅规则
|
* 订阅规则
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function useSubRules() {
|
export function useSubRules() {
|
||||||
const { data: setting, update: updateSetting } = useSetting();
|
const [loading, setLoading] = useState(false);
|
||||||
const list = setting?.subRulesList || DEFAULT_SUBRULES_LIST;
|
const [selectedRules, setSelectedRules] = useState([]);
|
||||||
|
const { setting, updateSetting } = useSetting();
|
||||||
|
const list = setting?.subrulesList || DEFAULT_SUBRULES_LIST;
|
||||||
|
|
||||||
const select = useCallback(
|
const selectedSub = useMemo(() => list.find((item) => item.selected), [list]);
|
||||||
|
const selectedUrl = selectedSub.url;
|
||||||
|
|
||||||
|
const selectSub = useCallback(
|
||||||
async (url) => {
|
async (url) => {
|
||||||
const subRulesList = [...list];
|
const subrulesList = [...list];
|
||||||
subRulesList.forEach((item) => {
|
subrulesList.forEach((item) => {
|
||||||
if (item.url === url) {
|
if (item.url === url) {
|
||||||
item.selected = true;
|
item.selected = true;
|
||||||
} else {
|
} else {
|
||||||
item.selected = false;
|
item.selected = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await updateSetting({ subRulesList });
|
await updateSetting({ subrulesList });
|
||||||
},
|
},
|
||||||
[list]
|
[list, updateSetting]
|
||||||
);
|
);
|
||||||
|
|
||||||
const add = useCallback(
|
const addSub = useCallback(
|
||||||
async (url) => {
|
async (url) => {
|
||||||
const subRulesList = [...list];
|
const subrulesList = [...list];
|
||||||
subRulesList.push({ url, selected: false });
|
subrulesList.push({ url, selected: false });
|
||||||
await updateSetting({ subRulesList });
|
await updateSetting({ subrulesList });
|
||||||
},
|
},
|
||||||
[list]
|
[list, updateSetting]
|
||||||
);
|
);
|
||||||
|
|
||||||
const del = useCallback(
|
const delSub = useCallback(
|
||||||
async (url) => {
|
async (url) => {
|
||||||
let subRulesList = [...list];
|
let subrulesList = [...list];
|
||||||
subRulesList = subRulesList.filter((item) => item.url !== url);
|
subrulesList = subrulesList.filter((item) => item.url !== url);
|
||||||
await updateSetting({ subRulesList });
|
await updateSetting({ subrulesList });
|
||||||
|
await delSubRules(url);
|
||||||
},
|
},
|
||||||
[list]
|
[list, updateSetting]
|
||||||
);
|
);
|
||||||
|
|
||||||
return { list, select, add, del };
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
if (selectedUrl) {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const rules = await loadOrFetchSubRules(selectedUrl);
|
||||||
|
setSelectedRules(rules);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("[loadOrFetchSubRules]", err);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [selectedUrl]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
subList: list,
|
||||||
|
selectSub,
|
||||||
|
addSub,
|
||||||
|
delSub,
|
||||||
|
selectedSub,
|
||||||
|
selectedUrl,
|
||||||
|
selectedRules,
|
||||||
|
setSelectedRules,
|
||||||
|
loading,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,3 @@ export function useSync() {
|
|||||||
const { data, update } = useStorage(STOKEY_SYNC, DEFAULT_SYNC);
|
const { data, update } = useStorage(STOKEY_SYNC, DEFAULT_SYNC);
|
||||||
return { sync: data, updateSync: update };
|
return { sync: data, updateSync: update };
|
||||||
}
|
}
|
||||||
// export function useSync() {
|
|
||||||
// const storages = useStorages();
|
|
||||||
// const opt = storages?.[STOKEY_SYNC];
|
|
||||||
// const update = useCallback(async (obj) => {
|
|
||||||
// await storage.putObj(STOKEY_SYNC, obj);
|
|
||||||
// }, []);
|
|
||||||
// return {
|
|
||||||
// opt,
|
|
||||||
// update,
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { detectLang } from "../libs/browser";
|
import { detectLang } from "../libs";
|
||||||
import { apiTranslate } from "../apis";
|
import { apiTranslate } from "../apis";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import storage from "./storage";
|
import { getMsauth, setMsauth } from "./storage";
|
||||||
import { STOKEY_MSAUTH, URL_MICROSOFT_AUTH } from "../config";
|
import { URL_MICROSOFT_AUTH } from "../config";
|
||||||
import { fetchData } from "./fetch";
|
import { fetchData } from "./fetch";
|
||||||
|
|
||||||
const parseMSToken = (token) => {
|
const parseMSToken = (token) => {
|
||||||
@@ -26,9 +26,9 @@ const _msAuth = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查询storage缓存
|
// 查询storage缓存
|
||||||
const res = (await storage.getObj(STOKEY_MSAUTH)) || {};
|
const res = await getMsauth();
|
||||||
token = res.token;
|
token = res?.token;
|
||||||
exp = res.exp;
|
exp = res?.exp;
|
||||||
if (token && exp * 1000 > now + 1000) {
|
if (token && exp * 1000 > now + 1000) {
|
||||||
return [token, exp];
|
return [token, exp];
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ const _msAuth = () => {
|
|||||||
// 缓存没有或失效,查询接口
|
// 缓存没有或失效,查询接口
|
||||||
token = await fetchData(URL_MICROSOFT_AUTH);
|
token = await fetchData(URL_MICROSOFT_AUTH);
|
||||||
exp = parseMSToken(token);
|
exp = parseMSToken(token);
|
||||||
await storage.setObj(STOKEY_MSAUTH, { token, exp });
|
await setMsauth({ token, exp });
|
||||||
return [token, exp];
|
return [token, exp];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,21 +13,3 @@ function _browser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const browser = _browser();
|
export const browser = _browser();
|
||||||
// export const client = process.env.REACT_APP_CLIENT;
|
|
||||||
// export const isExt = CLIENT_EXTS.includes(client);
|
|
||||||
// export const isGm = client === CLIENT_USERSCRIPT;
|
|
||||||
// export const isWeb = client === CLIENT_WEB;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本地语言识别
|
|
||||||
* @param {*} q
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export const detectLang = async (q) => {
|
|
||||||
try {
|
|
||||||
const res = await browser?.i18n?.detectLanguage(q);
|
|
||||||
return res?.languages?.[0]?.language;
|
|
||||||
} catch (err) {
|
|
||||||
console.log("[detect lang]", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { CACHE_NAME } from "../config";
|
import { CACHE_NAME } from "../config";
|
||||||
|
import { browser } from "./browser";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除缓存数据
|
* 清除缓存数据
|
||||||
@@ -10,3 +11,17 @@ export const tryClearCaches = async () => {
|
|||||||
console.log("[clean caches]", err.message);
|
console.log("[clean caches]", err.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地语言识别
|
||||||
|
* @param {*} q
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const detectLang = async (q) => {
|
||||||
|
try {
|
||||||
|
const res = await browser?.i18n?.detectLanguage(q);
|
||||||
|
return res?.languages?.[0]?.language;
|
||||||
|
} catch (err) {
|
||||||
|
console.log("[detect lang]", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,12 +1,3 @@
|
|||||||
import {
|
|
||||||
getSyncWithDefault,
|
|
||||||
updateSync,
|
|
||||||
getSubRulesWithDefault,
|
|
||||||
getSubRules,
|
|
||||||
delSubRules,
|
|
||||||
setSubRules,
|
|
||||||
} from "./storage";
|
|
||||||
import { fetchPolyfill } from "./fetch";
|
|
||||||
import { matchValue, type, isMatch } from "./utils";
|
import { matchValue, type, isMatch } from "./utils";
|
||||||
import {
|
import {
|
||||||
GLOBAL_KEY,
|
GLOBAL_KEY,
|
||||||
@@ -17,8 +8,7 @@ import {
|
|||||||
GLOBLA_RULE,
|
GLOBLA_RULE,
|
||||||
DEFAULT_SUBRULES_LIST,
|
DEFAULT_SUBRULES_LIST,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
|
import { loadOrFetchSubRules } from "./subRules";
|
||||||
// import { syncOpt } from "./sync";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据href匹配规则
|
* 根据href匹配规则
|
||||||
@@ -36,7 +26,7 @@ export const matchRule = async (
|
|||||||
try {
|
try {
|
||||||
const selectedSub = subrulesList.find((item) => item.selected);
|
const selectedSub = subrulesList.find((item) => item.selected);
|
||||||
if (selectedSub?.url) {
|
if (selectedSub?.url) {
|
||||||
const subRules = await loadSubRules(selectedSub.url);
|
const subRules = await loadOrFetchSubRules(selectedSub.url);
|
||||||
rules.splice(-1, 0, ...subRules);
|
rules.splice(-1, 0, ...subRules);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -123,19 +113,3 @@ export const checkRules = (rules) => {
|
|||||||
|
|
||||||
return rules;
|
return rules;
|
||||||
};
|
};
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 订阅规则的本地缓存
|
|
||||||
// */
|
|
||||||
// export const rulesCache = {
|
|
||||||
// fetch: async (url, isBg = false) => {
|
|
||||||
// const res = await fetchPolyfill(url, { isBg });
|
|
||||||
// const rules = checkRules(res).filter(
|
|
||||||
// (rule) => rule.pattern.replaceAll(GLOBAL_KEY, "") !== ""
|
|
||||||
// );
|
|
||||||
// return rules;
|
|
||||||
// },
|
|
||||||
// set: (url, rules) => setSubRules(url, rules),
|
|
||||||
// get: (url) => getSubRulesWithDefault(url),
|
|
||||||
// del: (url) => delSubRules(url),
|
|
||||||
// };
|
|
||||||
|
|||||||
@@ -10,32 +10,16 @@ import {
|
|||||||
DEFAULT_SYNC,
|
DEFAULT_SYNC,
|
||||||
BUILTIN_RULES,
|
BUILTIN_RULES,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import { browser, isExt, isGm } from "./client";
|
import { isExt, isGm } from "./client";
|
||||||
// import { APP_NAME } from "../config/app";
|
import { browser } from "./browser";
|
||||||
|
|
||||||
async function set(key, val) {
|
async function set(key, val) {
|
||||||
if (isExt) {
|
if (isExt) {
|
||||||
await browser.storage.local.set({ [key]: val });
|
await browser.storage.local.set({ [key]: val });
|
||||||
} else if (isGm) {
|
} else if (isGm) {
|
||||||
// const oldValue = await (window.KISS_GM || GM).getValue(key);
|
|
||||||
await (window.KISS_GM || GM).setValue(key, val);
|
await (window.KISS_GM || GM).setValue(key, val);
|
||||||
// window.dispatchEvent(
|
|
||||||
// new StorageEvent("storage", {
|
|
||||||
// key,
|
|
||||||
// oldValue,
|
|
||||||
// newValue: val,
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
} else {
|
} else {
|
||||||
// const oldValue = window.localStorage.getItem(key);
|
|
||||||
window.localStorage.setItem(key, val);
|
window.localStorage.setItem(key, val);
|
||||||
// window.dispatchEvent(
|
|
||||||
// new StorageEvent("storage", {
|
|
||||||
// key,
|
|
||||||
// oldValue,
|
|
||||||
// newValue: val,
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,25 +38,9 @@ async function del(key) {
|
|||||||
if (isExt) {
|
if (isExt) {
|
||||||
await browser.storage.local.remove([key]);
|
await browser.storage.local.remove([key]);
|
||||||
} else if (isGm) {
|
} else if (isGm) {
|
||||||
// const oldValue = await (window.KISS_GM || GM).getValue(key);
|
|
||||||
await (window.KISS_GM || GM).deleteValue(key);
|
await (window.KISS_GM || GM).deleteValue(key);
|
||||||
// window.dispatchEvent(
|
|
||||||
// new StorageEvent("storage", {
|
|
||||||
// key,
|
|
||||||
// oldValue,
|
|
||||||
// newValue: null,
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
} else {
|
} else {
|
||||||
// const oldValue = window.localStorage.getItem(key);
|
|
||||||
window.localStorage.removeItem(key);
|
window.localStorage.removeItem(key);
|
||||||
// window.dispatchEvent(
|
|
||||||
// new StorageEvent("storage", {
|
|
||||||
// key,
|
|
||||||
// oldValue,
|
|
||||||
// newValue: null,
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,18 +64,6 @@ async function putObj(key, obj) {
|
|||||||
await setObj(key, { ...cur, ...obj });
|
await setObj(key, { ...cur, ...obj });
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 监听storage事件
|
|
||||||
// * @param {*} handleChanged
|
|
||||||
// */
|
|
||||||
// function onChanged(handleChanged) {
|
|
||||||
// if (isExt) {
|
|
||||||
// browser.storage.onChanged.addListener(handleChanged);
|
|
||||||
// } else {
|
|
||||||
// window.addEventListener("storage", handleChanged);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对storage的封装
|
* 对storage的封装
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import { getSyncWithDefault, updateSync } from "./storage";
|
import { GLOBAL_KEY } from "../config";
|
||||||
|
import {
|
||||||
|
getSyncWithDefault,
|
||||||
|
updateSync,
|
||||||
|
setSubRules,
|
||||||
|
getSubRules,
|
||||||
|
} from "./storage";
|
||||||
import { apiFetchRules } from "../apis";
|
import { apiFetchRules } from "../apis";
|
||||||
|
import { checkRules } from "./rules";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同步订阅规则
|
* 同步订阅规则
|
||||||
@@ -7,9 +14,12 @@ import { apiFetchRules } from "../apis";
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const syncSubRules = async (url, isBg = false) => {
|
export const syncSubRules = async (url, isBg = false) => {
|
||||||
const rules = await apiFetchRules(url, isBg);
|
const res = await apiFetchRules(url, isBg);
|
||||||
|
const rules = checkRules(res).filter(
|
||||||
|
(rule) => rule.pattern.replaceAll(GLOBAL_KEY, "") !== ""
|
||||||
|
);
|
||||||
if (rules.length > 0) {
|
if (rules.length > 0) {
|
||||||
await rulesCache.set(url, rules);
|
await setSubRules(url, rules);
|
||||||
}
|
}
|
||||||
return rules;
|
return rules;
|
||||||
};
|
};
|
||||||
@@ -54,7 +64,7 @@ export const trySyncAllSubRules = async ({ subrulesList }, isBg = false) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const loadOrFetchSubRules = async (url) => {
|
export const loadOrFetchSubRules = async (url) => {
|
||||||
const rules = await apiFetchRules(url);
|
const rules = await getSubRules(url);
|
||||||
if (rules?.length) {
|
if (rules?.length) {
|
||||||
return rules;
|
return rules;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,20 @@
|
|||||||
import {
|
import {
|
||||||
STOKEY_SYNC,
|
|
||||||
DEFAULT_SYNC,
|
|
||||||
KV_SETTING_KEY,
|
KV_SETTING_KEY,
|
||||||
KV_RULES_KEY,
|
KV_RULES_KEY,
|
||||||
KV_RULES_SHARE_KEY,
|
KV_RULES_SHARE_KEY,
|
||||||
STOKEY_SETTING,
|
|
||||||
STOKEY_RULES,
|
|
||||||
KV_SALT_SHARE,
|
KV_SALT_SHARE,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import { storage, getSyncWithDefault, updateSync } from "../libs/storage";
|
import {
|
||||||
import { getSetting, getRules } from ".";
|
getSyncWithDefault,
|
||||||
|
updateSync,
|
||||||
|
getSettingWithDefault,
|
||||||
|
getRulesWithDefault,
|
||||||
|
setSetting,
|
||||||
|
setRules,
|
||||||
|
} from "./storage";
|
||||||
import { apiSyncData } from "../apis";
|
import { apiSyncData } from "../apis";
|
||||||
import { sha256 } from "./utils";
|
import { sha256 } from "./utils";
|
||||||
|
|
||||||
// /**
|
|
||||||
// * 同步相关数据
|
|
||||||
// */
|
|
||||||
// export const syncOpt = {
|
|
||||||
// load: async () => (await storage.getObj(STOKEY_SYNC)) || DEFAULT_SYNC,
|
|
||||||
// update: async (obj) => {
|
|
||||||
// await storage.putObj(STOKEY_SYNC, obj);
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同步设置
|
* 同步设置
|
||||||
* @returns
|
* @returns
|
||||||
@@ -33,7 +25,7 @@ const syncSetting = async (isBg = false) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const setting = await getSetting();
|
const setting = await getSettingWithDefault();
|
||||||
const res = await apiSyncData(
|
const res = await apiSyncData(
|
||||||
syncUrl,
|
syncUrl,
|
||||||
syncKey,
|
syncKey,
|
||||||
@@ -50,7 +42,7 @@ const syncSetting = async (isBg = false) => {
|
|||||||
settingUpdateAt: res.updateAt,
|
settingUpdateAt: res.updateAt,
|
||||||
settingSyncAt: res.updateAt,
|
settingSyncAt: res.updateAt,
|
||||||
});
|
});
|
||||||
await storage.setObj(STOKEY_SETTING, res.value);
|
await setSetting(res.value);
|
||||||
} else {
|
} else {
|
||||||
await updateSync({ settingSyncAt: res.updateAt });
|
await updateSync({ settingSyncAt: res.updateAt });
|
||||||
}
|
}
|
||||||
@@ -74,7 +66,7 @@ const syncRules = async (isBg = false) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rules = await getRules();
|
const rules = await getRulesWithDefault();
|
||||||
const res = await apiSyncData(
|
const res = await apiSyncData(
|
||||||
syncUrl,
|
syncUrl,
|
||||||
syncKey,
|
syncKey,
|
||||||
@@ -91,7 +83,7 @@ const syncRules = async (isBg = false) => {
|
|||||||
rulesUpdateAt: res.updateAt,
|
rulesUpdateAt: res.updateAt,
|
||||||
rulesSyncAt: res.updateAt,
|
rulesSyncAt: res.updateAt,
|
||||||
});
|
});
|
||||||
await storage.setObj(STOKEY_RULES, res.value);
|
await setRules(res.value);
|
||||||
} else {
|
} else {
|
||||||
await updateSync({ rulesSyncAt: res.updateAt });
|
await updateSync({ rulesSyncAt: res.updateAt });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
import Content from "../views/Content";
|
import Content from "../views/Content";
|
||||||
import { fetchUpdate, fetchClear } from "./fetch";
|
import { fetchUpdate, fetchClear } from "./fetch";
|
||||||
import { debounce } from "./utils";
|
import { debounce } from "./utils";
|
||||||
import { isExt } from "./client";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 翻译类
|
* 翻译类
|
||||||
@@ -102,6 +101,10 @@ export class Translator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get setting() {
|
||||||
|
return this._setting;
|
||||||
|
}
|
||||||
|
|
||||||
get rule() {
|
get rule() {
|
||||||
// console.log("get rule", this._rule);
|
// console.log("get rule", this._rule);
|
||||||
return this._rule;
|
return this._rule;
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ import ReactDOM from "react-dom/client";
|
|||||||
import Action from "./views/Action";
|
import Action from "./views/Action";
|
||||||
import createCache from "@emotion/cache";
|
import createCache from "@emotion/cache";
|
||||||
import { CacheProvider } from "@emotion/react";
|
import { CacheProvider } from "@emotion/react";
|
||||||
import { getSetting, getRules, matchRule, getFab } from "./libs";
|
import { getSettingWithDefault, getRulesWithDefault, getFabWithDefault } from "./libs/storage";
|
||||||
import { Translator } from "./libs/translator";
|
import { Translator } from "./libs/translator";
|
||||||
import { trySyncAllSubRules } from "./libs/subRules";
|
import { trySyncAllSubRules } from "./libs/subRules";
|
||||||
import { isGm } from "./libs/client";
|
import { isGm } from "./libs/client";
|
||||||
import { MSG_TRANS_TOGGLE, MSG_TRANS_PUTRULE } from "./config";
|
import { MSG_TRANS_TOGGLE, MSG_TRANS_PUTRULE } from "./config";
|
||||||
import { isIframe } from "./libs/iframe";
|
import { isIframe } from "./libs/iframe";
|
||||||
import { handlePing, injectScript } from "./libs/gm";
|
import { handlePing, injectScript } from "./libs/gm";
|
||||||
|
import { matchRule } from "./libs/rules";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 入口函数
|
* 入口函数
|
||||||
@@ -36,8 +37,8 @@ const init = async () => {
|
|||||||
|
|
||||||
// 翻译页面
|
// 翻译页面
|
||||||
const href = isIframe ? document.referrer : document.location.href;
|
const href = isIframe ? document.referrer : document.location.href;
|
||||||
const setting = await getSetting();
|
const setting = await getSettingWithDefault();
|
||||||
const rules = await getRules();
|
const rules = await getRulesWithDefault();
|
||||||
const rule = await matchRule(rules, href, setting);
|
const rule = await matchRule(rules, href, setting);
|
||||||
const translator = new Translator(rule, setting);
|
const translator = new Translator(rule, setting);
|
||||||
|
|
||||||
@@ -59,7 +60,7 @@ const init = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 浮球按钮
|
// 浮球按钮
|
||||||
const fab = await getFab();
|
const fab = await getFabWithDefault();
|
||||||
const $action = document.createElement("div");
|
const $action = document.createElement("div");
|
||||||
$action.setAttribute("id", "kiss-translator");
|
$action.setAttribute("id", "kiss-translator");
|
||||||
document.body.parentElement.appendChild($action);
|
document.body.parentElement.appendChild($action);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import MenuItem from "@mui/material/MenuItem";
|
|||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
import FileDownloadIcon from "@mui/icons-material/FileDownload";
|
import FileDownloadIcon from "@mui/icons-material/FileDownload";
|
||||||
import FileUploadIcon from "@mui/icons-material/FileUpload";
|
import FileUploadIcon from "@mui/icons-material/FileUpload";
|
||||||
import { useSetting, useSettingUpdate } from "../../hooks/Setting";
|
import { useSetting } from "../../hooks/Setting";
|
||||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||||
import Switch from "@mui/material/Switch";
|
import Switch from "@mui/material/Switch";
|
||||||
import Tabs from "@mui/material/Tabs";
|
import Tabs from "@mui/material/Tabs";
|
||||||
@@ -35,11 +35,13 @@ import DeleteIcon from "@mui/icons-material/Delete";
|
|||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import ShareIcon from "@mui/icons-material/Share";
|
import ShareIcon from "@mui/icons-material/Share";
|
||||||
import SyncIcon from "@mui/icons-material/Sync";
|
import SyncIcon from "@mui/icons-material/Sync";
|
||||||
import { useSubrules } from "../../hooks/Rules";
|
import { useSubRules } from "../../hooks/SubRules";
|
||||||
import { rulesCache, loadSubRules, syncSubRules } from "../../libs/rules";
|
import { syncSubRules } from "../../libs/subRules";
|
||||||
|
import { loadOrFetchSubRules } from "../../libs/subRules";
|
||||||
import { useAlert } from "../../hooks/Alert";
|
import { useAlert } from "../../hooks/Alert";
|
||||||
import { syncOpt, syncShareRules } from "../../libs/sync";
|
import { syncShareRules } from "../../libs/sync";
|
||||||
import { debounce } from "../../libs/utils";
|
import { debounce } from "../../libs/utils";
|
||||||
|
import { delSubRules, getSyncWithDefault } from "../../libs/storage";
|
||||||
|
|
||||||
function RuleFields({ rule, rules, setShow, setKeyword }) {
|
function RuleFields({ rule, rules, setShow, setKeyword }) {
|
||||||
const initFormValues = rule || { ...DEFAULT_RULE, transOpen: "true" };
|
const initFormValues = rule || { ...DEFAULT_RULE, transOpen: "true" };
|
||||||
@@ -409,12 +411,12 @@ function UploadButton({ onChange, text }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ShareButton({ rules, injectRules, selectedSub }) {
|
function ShareButton({ rules, injectRules, selectedUrl }) {
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const handleClick = async () => {
|
const handleClick = async () => {
|
||||||
try {
|
try {
|
||||||
const { syncUrl, syncKey } = await syncOpt.load();
|
const { syncUrl, syncKey } = await getSyncWithDefault();
|
||||||
if (!syncUrl || !syncKey) {
|
if (!syncUrl || !syncKey) {
|
||||||
alert.warning(i18n("error_sync_setting"));
|
alert.warning(i18n("error_sync_setting"));
|
||||||
return;
|
return;
|
||||||
@@ -422,7 +424,7 @@ function ShareButton({ rules, injectRules, selectedSub }) {
|
|||||||
|
|
||||||
const shareRules = [...rules.list];
|
const shareRules = [...rules.list];
|
||||||
if (injectRules) {
|
if (injectRules) {
|
||||||
const subRules = await loadSubRules(selectedSub?.url);
|
const subRules = await loadOrFetchSubRules(selectedUrl);
|
||||||
shareRules.splice(-1, 0, ...subRules);
|
shareRules.splice(-1, 0, ...subRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,19 +453,15 @@ function ShareButton({ rules, injectRules, selectedSub }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function UserRules() {
|
function UserRules({ subRules }) {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const rules = useRules();
|
const rules = useRules();
|
||||||
const [showAdd, setShowAdd] = useState(false);
|
const [showAdd, setShowAdd] = useState(false);
|
||||||
const setting = useSetting();
|
const { setting, updateSetting } = useSetting();
|
||||||
const updateSetting = useSettingUpdate();
|
|
||||||
const subrules = useSubrules();
|
|
||||||
const [subRules, setSubRules] = useState([]);
|
|
||||||
const [keyword, setKeyword] = useState("");
|
const [keyword, setKeyword] = useState("");
|
||||||
|
|
||||||
const selectedSub = subrules.list.find((item) => item.selected);
|
|
||||||
|
|
||||||
const injectRules = !!setting?.injectRules;
|
const injectRules = !!setting?.injectRules;
|
||||||
|
const { selectedUrl, selectedRules } = subRules;
|
||||||
|
|
||||||
const handleImport = (e) => {
|
const handleImport = (e) => {
|
||||||
const file = e.target.files[0];
|
const file = e.target.files[0];
|
||||||
@@ -493,19 +491,6 @@ function UserRules() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
if (selectedSub?.url) {
|
|
||||||
try {
|
|
||||||
const rules = await loadSubRules(selectedSub?.url);
|
|
||||||
setSubRules(rules);
|
|
||||||
} catch (err) {
|
|
||||||
console.log("[load rules]", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [selectedSub?.url]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!showAdd) {
|
if (!showAdd) {
|
||||||
setKeyword("");
|
setKeyword("");
|
||||||
@@ -514,7 +499,13 @@ function UserRules() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing={3}>
|
<Stack spacing={3}>
|
||||||
<Stack direction="row" alignItems="center" spacing={2} useFlexGap flexWrap="wrap">
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
alignItems="center"
|
||||||
|
spacing={2}
|
||||||
|
useFlexGap
|
||||||
|
flexWrap="wrap"
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
@@ -536,7 +527,7 @@ function UserRules() {
|
|||||||
<ShareButton
|
<ShareButton
|
||||||
rules={rules}
|
rules={rules}
|
||||||
injectRules={injectRules}
|
injectRules={injectRules}
|
||||||
selectedSub={selectedSub}
|
selectedUrl={selectedUrl}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
@@ -572,7 +563,7 @@ function UserRules() {
|
|||||||
|
|
||||||
{injectRules && (
|
{injectRules && (
|
||||||
<Box>
|
<Box>
|
||||||
{subRules
|
{selectedRules
|
||||||
.filter(
|
.filter(
|
||||||
(rule) =>
|
(rule) =>
|
||||||
rule.pattern.includes(keyword) || keyword.includes(rule.pattern)
|
rule.pattern.includes(keyword) || keyword.includes(rule.pattern)
|
||||||
@@ -586,13 +577,13 @@ function UserRules() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SubRulesItem({ index, url, selectedUrl, subrules, setRules }) {
|
function SubRulesItem({ index, url, selectedUrl, delSub, setSelectedRules }) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const handleDel = async () => {
|
const handleDel = async () => {
|
||||||
try {
|
try {
|
||||||
await subrules.del(url);
|
await delSub(url);
|
||||||
await rulesCache.del(url);
|
await delSubRules(url);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("[del subrules]", err);
|
console.log("[del subrules]", err);
|
||||||
}
|
}
|
||||||
@@ -603,7 +594,7 @@ function SubRulesItem({ index, url, selectedUrl, subrules, setRules }) {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const rules = await syncSubRules(url);
|
const rules = await syncSubRules(url);
|
||||||
if (rules.length > 0 && url === selectedUrl) {
|
if (rules.length > 0 && url === selectedUrl) {
|
||||||
setRules(rules);
|
setSelectedRules(rules);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("[sync sub rules]", err);
|
console.log("[sync sub rules]", err);
|
||||||
@@ -633,7 +624,7 @@ function SubRulesItem({ index, url, selectedUrl, subrules, setRules }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SubRulesEdit({ subrules }) {
|
function SubRulesEdit({ subList, addSub }) {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const [inputText, setInputText] = useState("");
|
const [inputText, setInputText] = useState("");
|
||||||
const [inputError, setInputError] = useState("");
|
const [inputError, setInputError] = useState("");
|
||||||
@@ -656,7 +647,7 @@ function SubRulesEdit({ subrules }) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subrules.list.find((item) => item.url === url)) {
|
if (subList.find((item) => item.url === url)) {
|
||||||
setInputError(i18n("error_duplicate_values"));
|
setInputError(i18n("error_duplicate_values"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -667,7 +658,7 @@ function SubRulesEdit({ subrules }) {
|
|||||||
if (rules.length === 0) {
|
if (rules.length === 0) {
|
||||||
throw new Error("empty rules");
|
throw new Error("empty rules");
|
||||||
}
|
}
|
||||||
await subrules.add(url);
|
await addSub(url);
|
||||||
setShowInput(false);
|
setShowInput(false);
|
||||||
setInputText("");
|
setInputText("");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -735,47 +726,36 @@ function SubRulesEdit({ subrules }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SubRules() {
|
function SubRules({ subRules }) {
|
||||||
const [loading, setLoading] = useState(false);
|
const {
|
||||||
const [rules, setRules] = useState([]);
|
subList,
|
||||||
const subrules = useSubrules();
|
selectSub,
|
||||||
const selectedSub = subrules.list.find((item) => item.selected);
|
addSub,
|
||||||
|
delSub,
|
||||||
|
selectedUrl,
|
||||||
|
selectedRules,
|
||||||
|
setSelectedRules,
|
||||||
|
loading,
|
||||||
|
} = subRules;
|
||||||
|
|
||||||
const handleSelect = (e) => {
|
const handleSelect = (e) => {
|
||||||
const url = e.target.value;
|
const url = e.target.value;
|
||||||
subrules.select(url);
|
selectSub(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
if (selectedSub?.url) {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
|
|
||||||
const rules = await loadSubRules(selectedSub?.url);
|
|
||||||
setRules(rules);
|
|
||||||
} catch (err) {
|
|
||||||
console.log("[load rules]", err);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}, [selectedSub?.url]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack spacing={3}>
|
<Stack spacing={3}>
|
||||||
<SubRulesEdit subrules={subrules} />
|
<SubRulesEdit subList={subList} addSub={addSub} />
|
||||||
|
|
||||||
<RadioGroup value={selectedSub?.url} onChange={handleSelect}>
|
<RadioGroup value={selectedUrl} onChange={handleSelect}>
|
||||||
{subrules.list.map((item, index) => (
|
{subList.map((item, index) => (
|
||||||
<SubRulesItem
|
<SubRulesItem
|
||||||
key={item.url}
|
key={item.url}
|
||||||
url={item.url}
|
url={item.url}
|
||||||
index={index}
|
index={index}
|
||||||
selectedUrl={selectedSub?.url}
|
selectedUrl={selectedUrl}
|
||||||
subrules={subrules}
|
delSub={delSub}
|
||||||
setRules={setRules}
|
setSelectedRules={setSelectedRules}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
@@ -786,7 +766,9 @@ function SubRules() {
|
|||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
</center>
|
</center>
|
||||||
) : (
|
) : (
|
||||||
rules.map((rule) => <RuleAccordion key={rule.pattern} rule={rule} />)
|
selectedRules.map((rule) => (
|
||||||
|
<RuleAccordion key={rule.pattern} rule={rule} />
|
||||||
|
))
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -796,6 +778,7 @@ function SubRules() {
|
|||||||
export default function Rules() {
|
export default function Rules() {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const [activeTab, setActiveTab] = useState(0);
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
|
const subRules = useSubRules();
|
||||||
|
|
||||||
const handleTabChange = (e, newValue) => {
|
const handleTabChange = (e, newValue) => {
|
||||||
setActiveTab(newValue);
|
setActiveTab(newValue);
|
||||||
@@ -816,8 +799,12 @@ export default function Rules() {
|
|||||||
<Tab label={i18n("subscribe_rules")} />
|
<Tab label={i18n("subscribe_rules")} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
<div hidden={activeTab !== 0}>{activeTab === 0 && <UserRules />}</div>
|
<div hidden={activeTab !== 0}>
|
||||||
<div hidden={activeTab !== 1}>{activeTab === 1 && <SubRules />}</div>
|
{activeTab === 0 && <UserRules subRules={subRules} />}
|
||||||
|
</div>
|
||||||
|
<div hidden={activeTab !== 1}>
|
||||||
|
{activeTab === 1 && <SubRules subRules={subRules} />}
|
||||||
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,18 +6,15 @@ import MenuItem from "@mui/material/MenuItem";
|
|||||||
import FormControl from "@mui/material/FormControl";
|
import FormControl from "@mui/material/FormControl";
|
||||||
import Select from "@mui/material/Select";
|
import Select from "@mui/material/Select";
|
||||||
import { useSetting } from "../../hooks/Setting";
|
import { useSetting } from "../../hooks/Setting";
|
||||||
import { limitNumber, debounce } from "../../libs/utils";
|
import { limitNumber } from "../../libs/utils";
|
||||||
import { useI18n } from "../../hooks/I18n";
|
import { useI18n } from "../../hooks/I18n";
|
||||||
import { UI_LANGS } from "../../config";
|
import { UI_LANGS } from "../../config";
|
||||||
import { useMemo } from "react";
|
|
||||||
|
|
||||||
export default function Settings() {
|
export default function Settings() {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const { setting, updateSetting } = useSetting();
|
const { setting, updateSetting } = useSetting();
|
||||||
|
|
||||||
const handleChange = useMemo(
|
const handleChange = (e) => {
|
||||||
() =>
|
|
||||||
debounce((e) => {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
let { name, value } = e.target;
|
let { name, value } = e.target;
|
||||||
switch (name) {
|
switch (name) {
|
||||||
@@ -38,9 +35,7 @@ export default function Settings() {
|
|||||||
updateSetting({
|
updateSetting({
|
||||||
[name]: value,
|
[name]: value,
|
||||||
});
|
});
|
||||||
}, 500),
|
};
|
||||||
[updateSetting]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!setting) {
|
if (!setting) {
|
||||||
return;
|
return;
|
||||||
@@ -84,7 +79,7 @@ export default function Settings() {
|
|||||||
label={i18n("fetch_limit")}
|
label={i18n("fetch_limit")}
|
||||||
type="number"
|
type="number"
|
||||||
name="fetchLimit"
|
name="fetchLimit"
|
||||||
defaultValue={fetchLimit}
|
value={fetchLimit}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -93,7 +88,7 @@ export default function Settings() {
|
|||||||
label={i18n("fetch_interval")}
|
label={i18n("fetch_interval")}
|
||||||
type="number"
|
type="number"
|
||||||
name="fetchInterval"
|
name="fetchInterval"
|
||||||
defaultValue={fetchInterval}
|
value={fetchInterval}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -102,7 +97,7 @@ export default function Settings() {
|
|||||||
label={i18n("min_translate_length")}
|
label={i18n("min_translate_length")}
|
||||||
type="number"
|
type="number"
|
||||||
name="minLength"
|
name="minLength"
|
||||||
defaultValue={minLength}
|
value={minLength}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -111,7 +106,7 @@ export default function Settings() {
|
|||||||
label={i18n("max_translate_length")}
|
label={i18n("max_translate_length")}
|
||||||
type="number"
|
type="number"
|
||||||
name="maxLength"
|
name="maxLength"
|
||||||
defaultValue={maxLength}
|
value={maxLength}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -132,7 +127,7 @@ export default function Settings() {
|
|||||||
size="small"
|
size="small"
|
||||||
label={i18n("google_api")}
|
label={i18n("google_api")}
|
||||||
name="googleUrl"
|
name="googleUrl"
|
||||||
defaultValue={googleUrl}
|
value={googleUrl}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -140,7 +135,7 @@ export default function Settings() {
|
|||||||
size="small"
|
size="small"
|
||||||
label={i18n("openai_api")}
|
label={i18n("openai_api")}
|
||||||
name="openaiUrl"
|
name="openaiUrl"
|
||||||
defaultValue={openaiUrl}
|
value={openaiUrl}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -149,7 +144,7 @@ export default function Settings() {
|
|||||||
type="password"
|
type="password"
|
||||||
label={i18n("openai_key")}
|
label={i18n("openai_key")}
|
||||||
name="openaiKey"
|
name="openaiKey"
|
||||||
defaultValue={openaiKey}
|
value={openaiKey}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -157,7 +152,7 @@ export default function Settings() {
|
|||||||
size="small"
|
size="small"
|
||||||
label={i18n("openai_model")}
|
label={i18n("openai_model")}
|
||||||
name="openaiModel"
|
name="openaiModel"
|
||||||
defaultValue={openaiModel}
|
value={openaiModel}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -165,7 +160,7 @@ export default function Settings() {
|
|||||||
size="small"
|
size="small"
|
||||||
label={i18n("openai_prompt")}
|
label={i18n("openai_prompt")}
|
||||||
name="openaiPrompt"
|
name="openaiPrompt"
|
||||||
defaultValue={openaiPrompt}
|
value={openaiPrompt}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
multiline
|
multiline
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import { useSync } from "../../hooks/Sync";
|
|||||||
import Alert from "@mui/material/Alert";
|
import Alert from "@mui/material/Alert";
|
||||||
import Link from "@mui/material/Link";
|
import Link from "@mui/material/Link";
|
||||||
import { URL_KISS_WORKER } from "../../config";
|
import { URL_KISS_WORKER } from "../../config";
|
||||||
import { debounce } from "../../libs/utils";
|
import { useState } from "react";
|
||||||
import { useMemo, useState } from "react";
|
|
||||||
import { syncAll } from "../../libs/sync";
|
import { syncAll } from "../../libs/sync";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { useAlert } from "../../hooks/Alert";
|
import { useAlert } from "../../hooks/Alert";
|
||||||
@@ -16,22 +15,17 @@ import CircularProgress from "@mui/material/CircularProgress";
|
|||||||
|
|
||||||
export default function SyncSetting() {
|
export default function SyncSetting() {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const sync = useSync();
|
const { sync, updateSync } = useSync();
|
||||||
const alert = useAlert();
|
const alert = useAlert();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const handleChange = useMemo(
|
const handleChange = async (e) => {
|
||||||
() =>
|
|
||||||
debounce(async (e) => {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target;
|
||||||
await sync.update({
|
await updateSync({
|
||||||
[name]: value,
|
[name]: value,
|
||||||
});
|
});
|
||||||
// trySyncAll();
|
};
|
||||||
}, 500),
|
|
||||||
[sync]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSyncTest = async (e) => {
|
const handleSyncTest = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -47,11 +41,7 @@ export default function SyncSetting() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!sync.opt) {
|
const { syncUrl, syncKey } = sync;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { syncUrl, syncKey } = sync.opt;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
@@ -62,7 +52,7 @@ export default function SyncSetting() {
|
|||||||
size="small"
|
size="small"
|
||||||
label={i18n("data_sync_url")}
|
label={i18n("data_sync_url")}
|
||||||
name="syncUrl"
|
name="syncUrl"
|
||||||
defaultValue={syncUrl}
|
value={syncUrl}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
helperText={
|
helperText={
|
||||||
<Link href={URL_KISS_WORKER}>{i18n("about_sync_api")}</Link>
|
<Link href={URL_KISS_WORKER}>{i18n("about_sync_api")}</Link>
|
||||||
@@ -74,11 +64,17 @@ export default function SyncSetting() {
|
|||||||
type="password"
|
type="password"
|
||||||
label={i18n("data_sync_key")}
|
label={i18n("data_sync_key")}
|
||||||
name="syncKey"
|
name="syncKey"
|
||||||
defaultValue={syncKey}
|
value={syncKey}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Stack direction="row" alignItems="center" spacing={2} useFlexGap flexWrap="wrap">
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
alignItems="center"
|
||||||
|
spacing={2}
|
||||||
|
useFlexGap
|
||||||
|
flexWrap="wrap"
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
|
|||||||
Reference in New Issue
Block a user