fix data sync
This commit is contained in:
@@ -33,6 +33,7 @@ If you also like a little more simplicity, welcome to pick it up.
|
|||||||
- [ ] DeepL
|
- [ ] DeepL
|
||||||
- [ ] Upload to app Store
|
- [ ] Upload to app Store
|
||||||
- [x] Open source
|
- [x] Open source
|
||||||
|
- [x] Data Synchronization Function
|
||||||
|
|
||||||
### Guide
|
### Guide
|
||||||
|
|
||||||
@@ -42,3 +43,7 @@ cd kiss-translator
|
|||||||
yarn
|
yarn
|
||||||
yarn dist
|
yarn dist
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Data Sync
|
||||||
|
|
||||||
|
Goto: [https://github.com/fishjar/kiss-worker](https://github.com/fishjar/kiss-worker)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
- [ ] DeepL
|
- [ ] DeepL
|
||||||
- [ ] 上架应用市场
|
- [ ] 上架应用市场
|
||||||
- [x] 开放源代码
|
- [x] 开放源代码
|
||||||
|
- [x] 数据同步功能
|
||||||
|
|
||||||
### 指引
|
### 指引
|
||||||
|
|
||||||
@@ -42,3 +43,7 @@ cd kiss-translator
|
|||||||
yarn
|
yarn
|
||||||
yarn dist
|
yarn dist
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 数据同步
|
||||||
|
|
||||||
|
移步: [https://github.com/fishjar/kiss-worker](https://github.com/fishjar/kiss-worker)
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
import { fetchPolyfill } from "../libs/fetch";
|
|
||||||
import {
|
|
||||||
KV_HEADER_KEY,
|
|
||||||
KV_RULES_KEY,
|
|
||||||
KV_SETTING_KEY,
|
|
||||||
STOKEY_RULES,
|
|
||||||
STOKEY_SETTING,
|
|
||||||
STOKEY_RULES_UPDATE_AT,
|
|
||||||
} from "../config";
|
|
||||||
import { getSetting, getRules } from "../libs";
|
|
||||||
import storage from "../libs/storage";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步数据
|
|
||||||
* @param {*} param0
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
const apiSyncData = async ({ key, value, updateAt }) => {
|
|
||||||
const { syncUrl, syncKey } = await getSetting();
|
|
||||||
if (!syncUrl || !syncKey) {
|
|
||||||
console.log("data sync should set the api and key");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return fetchPolyfill(syncUrl, {
|
|
||||||
headers: {
|
|
||||||
"Content-type": "application/json",
|
|
||||||
[KV_HEADER_KEY]: syncKey,
|
|
||||||
},
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({ key, value, updateAt }),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步rules
|
|
||||||
* @param {*} value
|
|
||||||
* @param {*} updateAt
|
|
||||||
*/
|
|
||||||
export const apiSyncRules = async (value, updateAt) => {
|
|
||||||
const res = await apiSyncData({
|
|
||||||
key: KV_RULES_KEY,
|
|
||||||
value,
|
|
||||||
updateAt,
|
|
||||||
});
|
|
||||||
console.log("res", res);
|
|
||||||
if (res && res.updateAt > updateAt) {
|
|
||||||
await storage.setObj(STOKEY_RULES, res.value);
|
|
||||||
await storage.setObj(STOKEY_RULES_UPDATE_AT, res.updateAt);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步setting
|
|
||||||
* @param {*} value
|
|
||||||
* @param {*} updateAt
|
|
||||||
*/
|
|
||||||
export const apiSyncSetting = async (value, updateAt) => {
|
|
||||||
const res = await apiSyncData({
|
|
||||||
key: KV_SETTING_KEY,
|
|
||||||
value,
|
|
||||||
updateAt,
|
|
||||||
});
|
|
||||||
console.log("res", res);
|
|
||||||
if (res && res.updateAt > updateAt) {
|
|
||||||
await storage.setObj(STOKEY_SETTING, res.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 同步全部数据
|
|
||||||
*/
|
|
||||||
export const apiSyncAll = async () => {
|
|
||||||
const setting = await getSetting();
|
|
||||||
const rules = await getRules();
|
|
||||||
const settingUpdateAt = setting.updateAt;
|
|
||||||
const rulesUpdateAt = (await storage.getObj(STOKEY_RULES_UPDATE_AT)) || 1;
|
|
||||||
await apiSyncSetting(setting, settingUpdateAt);
|
|
||||||
await apiSyncRules(rules, rulesUpdateAt);
|
|
||||||
};
|
|
||||||
@@ -8,9 +8,27 @@ import {
|
|||||||
OPT_LANGS_SPECIAL,
|
OPT_LANGS_SPECIAL,
|
||||||
PROMPT_PLACE_FROM,
|
PROMPT_PLACE_FROM,
|
||||||
PROMPT_PLACE_TO,
|
PROMPT_PLACE_TO,
|
||||||
|
KV_HEADER_KEY,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import { getSetting, detectLang } from "../libs";
|
import { getSetting, detectLang } from "../libs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步数据
|
||||||
|
* @param {*} url
|
||||||
|
* @param {*} key
|
||||||
|
* @param {*} data
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const apiSyncData = async (url, key, data) =>
|
||||||
|
fetchPolyfill(url, {
|
||||||
|
headers: {
|
||||||
|
"Content-type": "application/json",
|
||||||
|
[KV_HEADER_KEY]: key,
|
||||||
|
},
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 谷歌翻译
|
* 谷歌翻译
|
||||||
* @param {*} text
|
* @param {*} text
|
||||||
|
|||||||
@@ -4,14 +4,16 @@ import {
|
|||||||
MSG_FETCH_LIMIT,
|
MSG_FETCH_LIMIT,
|
||||||
DEFAULT_SETTING,
|
DEFAULT_SETTING,
|
||||||
DEFAULT_RULES,
|
DEFAULT_RULES,
|
||||||
|
DEFAULT_SYNC,
|
||||||
STOKEY_SETTING,
|
STOKEY_SETTING,
|
||||||
STOKEY_RULES,
|
STOKEY_RULES,
|
||||||
|
STOKEY_SYNC,
|
||||||
CACHE_NAME,
|
CACHE_NAME,
|
||||||
} from "./config";
|
} from "./config";
|
||||||
import { fetchData, setFetchLimit } from "./libs/fetch";
|
import { fetchData, setFetchLimit } from "./libs/fetch";
|
||||||
import storage from "./libs/storage";
|
import storage from "./libs/storage";
|
||||||
import { getSetting } from "./libs";
|
import { getSetting } from "./libs";
|
||||||
import { apiSyncAll } from "./apis/data";
|
import { syncAll } from "./libs/sync";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件安装
|
* 插件安装
|
||||||
@@ -20,6 +22,7 @@ browser.runtime.onInstalled.addListener(() => {
|
|||||||
console.log("onInstalled");
|
console.log("onInstalled");
|
||||||
storage.trySetObj(STOKEY_SETTING, DEFAULT_SETTING);
|
storage.trySetObj(STOKEY_SETTING, DEFAULT_SETTING);
|
||||||
storage.trySetObj(STOKEY_RULES, DEFAULT_RULES);
|
storage.trySetObj(STOKEY_RULES, DEFAULT_RULES);
|
||||||
|
storage.trySetObj(STOKEY_SYNC, DEFAULT_SYNC);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,11 +32,7 @@ browser.runtime.onStartup.addListener(async () => {
|
|||||||
console.log("onStartup");
|
console.log("onStartup");
|
||||||
|
|
||||||
// 同步数据
|
// 同步数据
|
||||||
try {
|
await syncAll();
|
||||||
await apiSyncAll();
|
|
||||||
} catch (err) {
|
|
||||||
console.log("[sync all]", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清除缓存
|
// 清除缓存
|
||||||
const { clearCache } = await getSetting();
|
const { clearCache } = await getSetting();
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ export const I18N = {
|
|||||||
zh: `规则设置`,
|
zh: `规则设置`,
|
||||||
en: `Rules Setting`,
|
en: `Rules Setting`,
|
||||||
},
|
},
|
||||||
|
sync_setting: {
|
||||||
|
zh: `同步设置`,
|
||||||
|
en: `Sync Setting`,
|
||||||
|
},
|
||||||
about: {
|
about: {
|
||||||
zh: `关于`,
|
zh: `关于`,
|
||||||
en: `About`,
|
en: `About`,
|
||||||
@@ -94,9 +98,13 @@ export const I18N = {
|
|||||||
zh: `添加`,
|
zh: `添加`,
|
||||||
en: `Add`,
|
en: `Add`,
|
||||||
},
|
},
|
||||||
advanced_warn: {
|
sync_warn: {
|
||||||
zh: `如不明白,谨慎修改!不同的浏览器,选择器规则不一定通用。`,
|
zh: `数据同步功能只是按修改时间简单覆盖,谨慎使用!`,
|
||||||
en: `If you don't understand, modify it carefully! Different browsers, the selector rules are not necessarily universal.`,
|
en: `The data synchronization function is simply overwritten according to the modification time, use it with caution!`,
|
||||||
|
},
|
||||||
|
about_sync_api: {
|
||||||
|
zh: `查看关于数据同步接口部署`,
|
||||||
|
en: `View About Data Synchronization Interface Deployment`,
|
||||||
},
|
},
|
||||||
style_none: {
|
style_none: {
|
||||||
zh: `无`,
|
zh: `无`,
|
||||||
@@ -139,8 +147,8 @@ export const I18N = {
|
|||||||
en: `Multiple URLs can be separated by English commas ","`,
|
en: `Multiple URLs can be separated by English commas ","`,
|
||||||
},
|
},
|
||||||
selector_helper: {
|
selector_helper: {
|
||||||
zh: `遵循CSS选择器规则,但不同浏览器,可能支持不同,有些不同的写法。`,
|
zh: `遵循CSS选择器规则,但不同浏览器,有些不同的写法。`,
|
||||||
en: `Follow the CSS selector rules, but different browsers may support different, and some have different ways of writing.`,
|
en: `Follow the CSS selector rules, but different browsers have some different ways of writing.`,
|
||||||
},
|
},
|
||||||
translate_switch: {
|
translate_switch: {
|
||||||
zh: `开启翻译`,
|
zh: `开启翻译`,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export const APP_LCNAME = APP_NAME.toLowerCase();
|
|||||||
export const STOKEY_MSAUTH = `${APP_NAME}_msauth`;
|
export const STOKEY_MSAUTH = `${APP_NAME}_msauth`;
|
||||||
export const STOKEY_SETTING = `${APP_NAME}_setting`;
|
export const STOKEY_SETTING = `${APP_NAME}_setting`;
|
||||||
export const STOKEY_RULES = `${APP_NAME}_rules`;
|
export const STOKEY_RULES = `${APP_NAME}_rules`;
|
||||||
export const STOKEY_RULES_UPDATE_AT = `${APP_NAME}_rules_update_at`;
|
export const STOKEY_SYNC = `${APP_NAME}_sync`;
|
||||||
|
|
||||||
export const KV_HEADER_KEY = "X-KISS-PSK";
|
export const KV_HEADER_KEY = "X-KISS-PSK";
|
||||||
export const KV_RULES_KEY = "KT_RULES";
|
export const KV_RULES_KEY = "KT_RULES";
|
||||||
@@ -26,6 +26,7 @@ export const THEME_LIGHT = "light";
|
|||||||
export const THEME_DARK = "dark";
|
export const THEME_DARK = "dark";
|
||||||
|
|
||||||
export const URL_APP_HOMEPAGE = "https://github.com/fishjar/kiss-translator";
|
export const URL_APP_HOMEPAGE = "https://github.com/fishjar/kiss-translator";
|
||||||
|
export const URL_KISS_WORKER = "https://github.com/fishjar/kiss-worker";
|
||||||
export const URL_RAW_PREFIX =
|
export const URL_RAW_PREFIX =
|
||||||
"https://raw.githubusercontent.com/fishjar/kiss-translator/master";
|
"https://raw.githubusercontent.com/fishjar/kiss-translator/master";
|
||||||
export const URL_MICROSOFT_AUTH = "https://edge.microsoft.com/translate/auth";
|
export const URL_MICROSOFT_AUTH = "https://edge.microsoft.com/translate/auth";
|
||||||
@@ -135,9 +136,6 @@ export const DEFAULT_SETTING = {
|
|||||||
openaiKey: "",
|
openaiKey: "",
|
||||||
openaiModel: "gpt-4",
|
openaiModel: "gpt-4",
|
||||||
openaiPrompt: `You will be provided with a sentence in ${PROMPT_PLACE_FROM}, and your task is to translate it into ${PROMPT_PLACE_TO}.`,
|
openaiPrompt: `You will be provided with a sentence in ${PROMPT_PLACE_FROM}, and your task is to translate it into ${PROMPT_PLACE_TO}.`,
|
||||||
syncUrl: "", // 数据同步接口
|
|
||||||
syncKey: "", // 数据同步密钥
|
|
||||||
updateAt: 1, // 更新时间
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_RULES = [
|
export const DEFAULT_RULES = [
|
||||||
@@ -151,3 +149,12 @@ export const DEFAULT_RULES = [
|
|||||||
|
|
||||||
export const TRANS_MIN_LENGTH = 5; // 最短翻译长度
|
export const TRANS_MIN_LENGTH = 5; // 最短翻译长度
|
||||||
export const TRANS_MAX_LENGTH = 5000; // 最长翻译长度
|
export const TRANS_MAX_LENGTH = 5000; // 最长翻译长度
|
||||||
|
|
||||||
|
export const DEFAULT_SYNC = {
|
||||||
|
syncUrl: "", // 数据同步接口
|
||||||
|
syncKey: "", // 数据同步密钥
|
||||||
|
settingUpdateAt: 0,
|
||||||
|
settingSyncAt: 0,
|
||||||
|
rulesUpdateAt: 0,
|
||||||
|
rulesSyncAt: 0,
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import {
|
|||||||
OPT_STYLE_ALL,
|
OPT_STYLE_ALL,
|
||||||
OPT_LANGS_FROM,
|
OPT_LANGS_FROM,
|
||||||
OPT_LANGS_TO,
|
OPT_LANGS_TO,
|
||||||
STOKEY_RULES_UPDATE_AT,
|
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import storage from "../libs/storage";
|
import storage from "../libs/storage";
|
||||||
import { useStorages } from "./Storage";
|
import { useStorages } from "./Storage";
|
||||||
import { matchValue } from "../libs/utils";
|
import { matchValue } from "../libs/utils";
|
||||||
import { apiSyncRules } from "../apis/data";
|
import { syncRules } from "../libs/sync";
|
||||||
|
import { useSync } from "./Sync";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 匹配规则增删改查 hook
|
* 匹配规则增删改查 hook
|
||||||
@@ -18,13 +18,14 @@ import { apiSyncRules } from "../apis/data";
|
|||||||
export function useRules() {
|
export function useRules() {
|
||||||
const storages = useStorages();
|
const storages = useStorages();
|
||||||
const list = storages?.[STOKEY_RULES] || [];
|
const list = storages?.[STOKEY_RULES] || [];
|
||||||
|
const sync = useSync();
|
||||||
|
|
||||||
const update = async (rules) => {
|
const update = async (rules) => {
|
||||||
const now = Date.now();
|
const updateAt = sync.opt?.rulesUpdateAt ? Date.now() : 0;
|
||||||
await storage.setObj(STOKEY_RULES, rules);
|
await storage.setObj(STOKEY_RULES, rules);
|
||||||
await storage.setObj(STOKEY_RULES_UPDATE_AT, now);
|
await sync.update({ rulesUpdateAt: updateAt });
|
||||||
try {
|
try {
|
||||||
await apiSyncRules(rules, now);
|
await syncRules();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log("[sync rules]", err);
|
console.log("[sync rules]", err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useCallback } from "react";
|
|
||||||
import { STOKEY_SETTING } from "../config";
|
import { STOKEY_SETTING } from "../config";
|
||||||
import storage from "../libs/storage";
|
import storage from "../libs/storage";
|
||||||
import { useStorages } from "./Storage";
|
import { useStorages } from "./Storage";
|
||||||
|
import { useSync } from "./Sync";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置hook
|
* 设置hook
|
||||||
@@ -17,7 +17,10 @@ export function useSetting() {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export function useSettingUpdate() {
|
export function useSettingUpdate() {
|
||||||
return useCallback(async (obj) => {
|
const sync = useSync();
|
||||||
await storage.putObj(STOKEY_SETTING, { ...obj, updateAt: Date.now() });
|
return async (obj) => {
|
||||||
}, []);
|
const updateAt = sync.opt?.settingUpdateAt ? Date.now() : 0;
|
||||||
|
await storage.putObj(STOKEY_SETTING, obj);
|
||||||
|
await sync.update({ settingUpdateAt: updateAt });
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import {
|
|||||||
STOKEY_SETTING,
|
STOKEY_SETTING,
|
||||||
STOKEY_RULES,
|
STOKEY_RULES,
|
||||||
STOKEY_MSAUTH,
|
STOKEY_MSAUTH,
|
||||||
|
STOKEY_SYNC,
|
||||||
DEFAULT_SETTING,
|
DEFAULT_SETTING,
|
||||||
DEFAULT_RULES,
|
DEFAULT_RULES,
|
||||||
STOKEY_RULES_UPDATE_AT,
|
DEFAULT_SYNC,
|
||||||
} from "../config";
|
} from "../config";
|
||||||
import storage from "../libs/storage";
|
import storage from "../libs/storage";
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ export const defaultStorage = {
|
|||||||
[STOKEY_MSAUTH]: null,
|
[STOKEY_MSAUTH]: null,
|
||||||
[STOKEY_SETTING]: DEFAULT_SETTING,
|
[STOKEY_SETTING]: DEFAULT_SETTING,
|
||||||
[STOKEY_RULES]: DEFAULT_RULES,
|
[STOKEY_RULES]: DEFAULT_RULES,
|
||||||
[STOKEY_RULES_UPDATE_AT]: 1,
|
[STOKEY_SYNC]: DEFAULT_SYNC,
|
||||||
};
|
};
|
||||||
|
|
||||||
const StoragesContext = createContext(null);
|
const StoragesContext = createContext(null);
|
||||||
|
|||||||
20
src/hooks/Sync.js
Normal file
20
src/hooks/Sync.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { useCallback } from "react";
|
||||||
|
import { STOKEY_SYNC } from "../config";
|
||||||
|
import storage from "../libs/storage";
|
||||||
|
import { useStorages } from "./Storage";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sync hook
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
74
src/libs/sync.js
Normal file
74
src/libs/sync.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import {
|
||||||
|
STOKEY_SYNC,
|
||||||
|
DEFAULT_SYNC,
|
||||||
|
KV_SETTING_KEY,
|
||||||
|
KV_RULES_KEY,
|
||||||
|
STOKEY_SETTING,
|
||||||
|
STOKEY_RULES,
|
||||||
|
} from "../config";
|
||||||
|
import storage from "../libs/storage";
|
||||||
|
import { getSetting, getRules } from ".";
|
||||||
|
import { apiSyncData } from "../apis";
|
||||||
|
|
||||||
|
const loadOpt = async () => (await storage.getObj(STOKEY_SYNC)) || DEFAULT_SYNC;
|
||||||
|
|
||||||
|
export const syncSetting = async () => {
|
||||||
|
const { syncUrl, syncKey, settingUpdateAt } = await loadOpt();
|
||||||
|
if (!syncUrl || !syncKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const setting = await getSetting();
|
||||||
|
const res = await apiSyncData(syncUrl, syncKey, {
|
||||||
|
key: KV_SETTING_KEY,
|
||||||
|
value: setting,
|
||||||
|
updateAt: settingUpdateAt,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res && res.updateAt > settingUpdateAt) {
|
||||||
|
await storage.putObj(STOKEY_SYNC, {
|
||||||
|
settingUpdateAt: res.updateAt,
|
||||||
|
settingSyncAt: res.updateAt,
|
||||||
|
});
|
||||||
|
await storage.setObj(STOKEY_SETTING, res.value);
|
||||||
|
} else {
|
||||||
|
await storage.putObj(STOKEY_SYNC, {
|
||||||
|
settingSyncAt: res.updateAt,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const syncRules = async () => {
|
||||||
|
const { syncUrl, syncKey, rulesUpdateAt } = await loadOpt();
|
||||||
|
if (!syncUrl || !syncKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rules = await getRules();
|
||||||
|
const res = await apiSyncData(syncUrl, syncKey, {
|
||||||
|
key: KV_RULES_KEY,
|
||||||
|
value: rules,
|
||||||
|
updateAt: rulesUpdateAt,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res && res.updateAt > rulesUpdateAt) {
|
||||||
|
await storage.putObj(STOKEY_SYNC, {
|
||||||
|
rulesUpdateAt: res.updateAt,
|
||||||
|
rulesSyncAt: res.updateAt,
|
||||||
|
});
|
||||||
|
await storage.setObj(STOKEY_RULES, res.value);
|
||||||
|
} else {
|
||||||
|
await storage.putObj(STOKEY_SYNC, {
|
||||||
|
rulesSyncAt: res.updateAt,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const syncAll = async () => {
|
||||||
|
try {
|
||||||
|
await syncSetting();
|
||||||
|
await syncRules();
|
||||||
|
} catch (err) {
|
||||||
|
console.log("[sync all]", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -6,6 +6,7 @@ import Box from "@mui/material/Box";
|
|||||||
import Navigator from "./Navigator";
|
import Navigator from "./Navigator";
|
||||||
import Header from "./Header";
|
import Header from "./Header";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import { useTheme } from "@mui/material/styles";
|
||||||
|
import { syncAll } from "../../libs/sync";
|
||||||
|
|
||||||
export default function Layout() {
|
export default function Layout() {
|
||||||
const navWidth = 256;
|
const navWidth = 256;
|
||||||
@@ -20,6 +21,7 @@ export default function Layout() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
syncAll();
|
||||||
}, [location]);
|
}, [location]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import SettingsIcon from "@mui/icons-material/Settings";
|
|||||||
import InfoIcon from "@mui/icons-material/Info";
|
import InfoIcon from "@mui/icons-material/Info";
|
||||||
import DesignServicesIcon from "@mui/icons-material/DesignServices";
|
import DesignServicesIcon from "@mui/icons-material/DesignServices";
|
||||||
import { useI18n } from "../../hooks/I18n";
|
import { useI18n } from "../../hooks/I18n";
|
||||||
|
import SyncIcon from "@mui/icons-material/Sync";
|
||||||
|
|
||||||
function LinkItem({ label, url, icon }) {
|
function LinkItem({ label, url, icon }) {
|
||||||
const match = useMatch(url);
|
const match = useMatch(url);
|
||||||
@@ -35,6 +36,12 @@ export default function Navigator(props) {
|
|||||||
url: "/rules",
|
url: "/rules",
|
||||||
icon: <DesignServicesIcon />,
|
icon: <DesignServicesIcon />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "sync",
|
||||||
|
label: i18n("sync_setting"),
|
||||||
|
url: "/sync",
|
||||||
|
icon: <SyncIcon />,
|
||||||
|
},
|
||||||
{ id: "about", label: i18n("about"), url: "/about", icon: <InfoIcon /> },
|
{ id: "about", label: i18n("about"), url: "/about", icon: <InfoIcon /> },
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
OPT_STYLE_ALL,
|
OPT_STYLE_ALL,
|
||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { useState, useRef } from "react";
|
import { useState, useRef } from "react";
|
||||||
import Alert from "@mui/material/Alert";
|
|
||||||
import { useI18n } from "../../hooks/I18n";
|
import { useI18n } from "../../hooks/I18n";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Accordion from "@mui/material/Accordion";
|
import Accordion from "@mui/material/Accordion";
|
||||||
@@ -354,8 +353,6 @@ export default function Rules() {
|
|||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Stack spacing={3}>
|
<Stack spacing={3}>
|
||||||
<Alert severity="warning">{i18n("advanced_warn")}</Alert>
|
|
||||||
|
|
||||||
<Stack direction="row" spacing={2}>
|
<Stack direction="row" spacing={2}>
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
|
|||||||
@@ -9,22 +9,12 @@ import { useSetting, useSettingUpdate } from "../../hooks/Setting";
|
|||||||
import { limitNumber } 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 { apiSyncAll } from "../../apis/data";
|
|
||||||
import { useCallback } from "react";
|
|
||||||
|
|
||||||
export default function Settings() {
|
export default function Settings() {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
const setting = useSetting();
|
const setting = useSetting();
|
||||||
const updateSetting = useSettingUpdate();
|
const updateSetting = useSettingUpdate();
|
||||||
|
|
||||||
const handleSyncBlur = useCallback(async () => {
|
|
||||||
try {
|
|
||||||
await apiSyncAll();
|
|
||||||
} catch (err) {
|
|
||||||
console.log("sync data", err);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (!setting) {
|
if (!setting) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -38,8 +28,6 @@ export default function Settings() {
|
|||||||
openaiModel,
|
openaiModel,
|
||||||
openaiPrompt,
|
openaiPrompt,
|
||||||
clearCache,
|
clearCache,
|
||||||
syncUrl,
|
|
||||||
syncKey,
|
|
||||||
} = setting;
|
} = setting;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -148,31 +136,6 @@ export default function Settings() {
|
|||||||
minRows={2}
|
minRows={2}
|
||||||
maxRows={10}
|
maxRows={10}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
|
||||||
size="small"
|
|
||||||
label={i18n("data_sync_url")}
|
|
||||||
defaultValue={syncUrl}
|
|
||||||
onChange={(e) => {
|
|
||||||
updateSetting({
|
|
||||||
syncUrl: e.target.value,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
onBlur={handleSyncBlur}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextField
|
|
||||||
size="small"
|
|
||||||
type="password"
|
|
||||||
label={i18n("data_sync_key")}
|
|
||||||
defaultValue={syncKey}
|
|
||||||
onChange={(e) => {
|
|
||||||
updateSetting({
|
|
||||||
syncKey: e.target.value,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
onBlur={handleSyncBlur}
|
|
||||||
/>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
59
src/views/Options/SyncSetting.js
Normal file
59
src/views/Options/SyncSetting.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import Stack from "@mui/material/Stack";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
import { useI18n } from "../../hooks/I18n";
|
||||||
|
import { useSync } from "../../hooks/Sync";
|
||||||
|
import { syncAll } from "../../libs/sync";
|
||||||
|
import Alert from "@mui/material/Alert";
|
||||||
|
import Link from "@mui/material/Link";
|
||||||
|
import { URL_KISS_WORKER } from "../../config";
|
||||||
|
|
||||||
|
export default function SyncSetting() {
|
||||||
|
const i18n = useI18n();
|
||||||
|
const sync = useSync();
|
||||||
|
|
||||||
|
if (!sync.opt) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { syncUrl, syncKey } = sync.opt;
|
||||||
|
const handleSyncBlur = () => {
|
||||||
|
syncAll();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Stack spacing={3}>
|
||||||
|
<Alert severity="warning">{i18n("sync_warn")}</Alert>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
size="small"
|
||||||
|
label={i18n("data_sync_url")}
|
||||||
|
defaultValue={syncUrl}
|
||||||
|
onChange={(e) => {
|
||||||
|
sync.update({
|
||||||
|
syncUrl: e.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onBlur={handleSyncBlur}
|
||||||
|
helperText={
|
||||||
|
<Link href={URL_KISS_WORKER}>{i18n("about_sync_api")}</Link>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextField
|
||||||
|
size="small"
|
||||||
|
type="password"
|
||||||
|
label={i18n("data_sync_key")}
|
||||||
|
defaultValue={syncKey}
|
||||||
|
onChange={(e) => {
|
||||||
|
sync.update({
|
||||||
|
syncKey: e.target.value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
onBlur={handleSyncBlur}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import About from "./About";
|
|||||||
import Rules from "./Rules";
|
import Rules from "./Rules";
|
||||||
import Setting from "./Setting";
|
import Setting from "./Setting";
|
||||||
import Layout from "./Layout";
|
import Layout from "./Layout";
|
||||||
|
import SyncSetting from "./SyncSetting";
|
||||||
|
|
||||||
export default function Options() {
|
export default function Options() {
|
||||||
return (
|
return (
|
||||||
@@ -10,6 +11,7 @@ export default function Options() {
|
|||||||
<Route path="/" element={<Layout />}>
|
<Route path="/" element={<Layout />}>
|
||||||
<Route index element={<Setting />} />
|
<Route index element={<Setting />} />
|
||||||
<Route path="rules" element={<Rules />} />
|
<Route path="rules" element={<Rules />} />
|
||||||
|
<Route path="sync" element={<SyncSetting />} />
|
||||||
<Route path="about" element={<About />} />
|
<Route path="about" element={<About />} />
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|||||||
Reference in New Issue
Block a user