diff --git a/src/apis/index.js b/src/apis/index.js
index eef30e5..55ac733 100644
--- a/src/apis/index.js
+++ b/src/apis/index.js
@@ -33,13 +33,12 @@ export const apiSyncData = async (url, key, data, isBg = false) =>
});
/**
- * 下载订阅规则
+ * 下载数据
* @param {*} url
* @param {*} isBg
* @returns
*/
-export const apiFetchRules = (url, isBg = false) =>
- fetchPolyfill(url, { isBg });
+export const apiFetch = (url, isBg = false) => fetchPolyfill(url, { isBg });
/**
* 谷歌翻译
diff --git a/src/config/i18n.js b/src/config/i18n.js
index 802634d..94c3b32 100644
--- a/src/config/i18n.js
+++ b/src/config/i18n.js
@@ -441,9 +441,9 @@ export const I18N = {
zh: `数据同步密钥`,
en: `Data Sync Key`,
},
- data_sync_test: {
- zh: `数据同步测试`,
- en: `Data Sync Test`,
+ sync_now: {
+ zh: `立即同步`,
+ en: `Sync Now`,
},
sync_success: {
zh: `同步成功!`,
diff --git a/src/libs/storage.js b/src/libs/storage.js
index abdc6e5..5a42c58 100644
--- a/src/libs/storage.js
+++ b/src/libs/storage.js
@@ -5,6 +5,7 @@ import {
STOKEY_SYNC,
STOKEY_MSAUTH,
STOKEY_RULESCACHE_PREFIX,
+ STOKEY_WEBFIXCACHE_PREFIX,
DEFAULT_SETTING,
DEFAULT_RULES,
DEFAULT_SYNC,
@@ -104,6 +105,14 @@ export const delSubRules = (url) => del(STOKEY_RULESCACHE_PREFIX + url);
export const setSubRules = (url, val) =>
setObj(STOKEY_RULESCACHE_PREFIX + url, val);
+/**
+ * 修复站点
+ */
+export const getWebfix = (url) => getObj(STOKEY_WEBFIXCACHE_PREFIX + url);
+export const getWebfixWithDefault = async () => (await getWebfix()) || [];
+export const setWebfix = (url, val) =>
+ setObj(STOKEY_WEBFIXCACHE_PREFIX + url, val);
+
/**
* fab位置
*/
diff --git a/src/libs/subRules.js b/src/libs/subRules.js
index b537edb..6dc5bef 100644
--- a/src/libs/subRules.js
+++ b/src/libs/subRules.js
@@ -6,7 +6,7 @@ import {
getSubRules,
updateSetting,
} from "./storage";
-import { apiFetchRules } from "../apis";
+import { apiFetch } from "../apis";
import { checkRules } from "./rules";
import { isAllchar } from "./utils";
@@ -16,7 +16,7 @@ import { isAllchar } from "./utils";
* @returns
*/
export const syncSubRules = async (url, isBg = false) => {
- const res = await apiFetchRules(url, isBg);
+ const res = await apiFetch(url, isBg);
const rules = checkRules(res).filter(
({ pattern }) => !isAllchar(pattern, GLOBAL_KEY)
);
diff --git a/src/libs/webfix.js b/src/libs/webfix.js
index d629615..26c0ccd 100644
--- a/src/libs/webfix.js
+++ b/src/libs/webfix.js
@@ -1,4 +1,11 @@
import { isMatch } from "./utils";
+import { getWebfix, setWebfix } from "./storage";
+import { apiFetch } from "../apis";
+
+/**
+ * 修复程序类型
+ */
+const WEBFIX_BR = "br";
/**
* 需要修复的站点列表
@@ -7,18 +14,18 @@ import { isMatch } from "./utils";
* - rootSlector 需要监听的选择器,可留空
* - fixer 修复函数,可针对不同网址,选用不同修复函数
*/
-export const sites = [
+const DEFAULT_SITES = [
{
pattern: "www.phoronix.com",
selector: ".content",
rootSlector: "",
- fixer: brFixer,
+ fixer: WEBFIX_BR,
},
{
pattern: "t.me/s/*",
selector: ".tgme_widget_message_text",
rootSlector: ".tgme_channel_history",
- fixer: brFixer,
+ fixer: WEBFIX_BR,
},
];
@@ -80,6 +87,13 @@ function brFixer(node) {
node.innerHTML = html;
}
+/**
+ * 修复程序映射
+ */
+const fixerMap = {
+ [WEBFIX_BR]: brFixer,
+};
+
/**
* 查找、监听节点,并执行修复函数
* @param {*} selector
@@ -108,19 +122,51 @@ function run(selector, fixer, rootSlector) {
});
}
+/**
+ * 同步远程数据
+ * @param {*} url
+ * @returns
+ */
+export const syncWebfix = async (url) => {
+ const sites = await apiFetch(url);
+ await setWebfix(url, sites);
+ return sites;
+};
+
+/**
+ * 从缓存或远程加载修复站点
+ * @param {*} url
+ * @returns
+ */
+export const loadOrFetchWebfix = async (url) => {
+ try {
+ let sites = await getWebfix(url);
+ if (sites?.length) {
+ return sites;
+ }
+ return syncWebfix(url);
+ } catch (err) {
+ console.log("[load webfix]", err.message);
+ return DEFAULT_SITES;
+ }
+};
+
/**
* 匹配站点
*/
-export function webfix(href, { injectWebfix }) {
+export async function webfix(href, { injectWebfix }) {
try {
if (!injectWebfix) {
return;
}
+ const sites = await loadOrFetchWebfix(process.env.REACT_APP_WEBFIXURL);
for (var i = 0; i < sites.length; i++) {
var site = sites[i];
if (isMatch(href, site.pattern)) {
- run(site.selector, site.fixer, site.rootSlector);
+ if (fixerMap[site.fixer]) {
+ run(site.selector, fixerMap[site.fixer], site.rootSlector);
+ }
break;
}
}
diff --git a/src/views/Options/SyncSetting.js b/src/views/Options/SyncSetting.js
index 0ffefbe..a028fec 100644
--- a/src/views/Options/SyncSetting.js
+++ b/src/views/Options/SyncSetting.js
@@ -87,7 +87,7 @@ export default function SyncSetting() {
onClick={handleSyncTest}
startIcon={}
>
- {i18n("data_sync_test")}
+ {i18n("sync_now")}
{loading && }
diff --git a/src/views/Options/Webfix.js b/src/views/Options/Webfix.js
index 6f2ce3d..c715a2a 100644
--- a/src/views/Options/Webfix.js
+++ b/src/views/Options/Webfix.js
@@ -1,6 +1,6 @@
import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
-import { useState } from "react";
+import { useEffect, useState } from "react";
import { useI18n } from "../../hooks/I18n";
import Typography from "@mui/material/Typography";
import Accordion from "@mui/material/Accordion";
@@ -9,13 +9,17 @@ import AccordionDetails from "@mui/material/AccordionDetails";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import Alert from "@mui/material/Alert";
import Box from "@mui/material/Box";
-import { sites as webfixSites } from "../../libs/webfix";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";
import { useSetting } from "../../hooks/Setting";
+import CircularProgress from "@mui/material/CircularProgress";
+import { syncWebfix, loadOrFetchWebfix } from "../../libs/webfix";
+import Button from "@mui/material/Button";
+import SyncIcon from "@mui/icons-material/Sync";
+import { useAlert } from "../../hooks/Alert";
function ApiFields({ site }) {
- const { selector, rootSlector } = site;
+ const { selector, rootSlector, fixer } = site;
return (
+
);
}
@@ -56,33 +67,90 @@ function ApiAccordion({ site }) {
}
export default function Webfix() {
+ const [loading, setLoading] = useState(false);
+ const [sites, setSites] = useState([]);
const i18n = useI18n();
+ const alert = useAlert();
const { setting, updateSetting } = useSetting();
+
+ const handleSyncTest = async (e) => {
+ e.preventDefault();
+ try {
+ setLoading(true);
+ await syncWebfix(process.env.REACT_APP_WEBFIXURL);
+ alert.success(i18n("sync_success"));
+ } catch (err) {
+ console.log("[sync webfix]", err);
+ alert.error(i18n("sync_failed"));
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ (async () => {
+ try {
+ setLoading(true);
+ const sites = await loadOrFetchWebfix(process.env.REACT_APP_WEBFIXURL);
+ setSites(sites);
+ } catch (err) {
+ console.log("[load webfix]", err.message);
+ } finally {
+ setLoading(false);
+ }
+ })();
+ }, []);
+
return (
{i18n("patch_setting_help")}
- {
- updateSetting({
- injectWebfix: !setting.injectWebfix,
- });
- }}
- />
- }
- label={i18n("inject_webfix")}
- />
+
+ }
+ >
+ {i18n("sync_now")}
+
+ {
+ updateSetting({
+ injectWebfix: !setting.injectWebfix,
+ });
+ }}
+ />
+ }
+ label={i18n("inject_webfix")}
+ />
+
-
- {webfixSites.map((site) => (
-
- ))}
-
+ {setting.injectWebfix && (
+
+ {loading ? (
+
+
+
+ ) : (
+ sites.map((site) => (
+
+ ))
+ )}
+
+ )}
);