优化细节

This commit is contained in:
王一之 2025-04-27 18:02:57 +08:00
parent e1a890a400
commit a26f1c5014
13 changed files with 234 additions and 118 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "scriptcat", "name": "scriptcat",
"version": "0.17.0-alpha.2", "version": "0.17.0-alpha.4",
"description": "脚本猫,一个可以执行用户脚本的浏览器扩展,万物皆可脚本化,让你的浏览器可以做更多的事情!", "description": "脚本猫,一个可以执行用户脚本的浏览器扩展,万物皆可脚本化,让你的浏览器可以做更多的事情!",
"author": "CodFrm", "author": "CodFrm",
"license": "GPLv3", "license": "GPLv3",

View File

@ -113,7 +113,6 @@ function renameField() {
if (subscribe.length) { if (subscribe.length) {
await Promise.all( await Promise.all(
subscribe.map((s: Subscribe) => { subscribe.map((s: Subscribe) => {
console.log("1234", s);
const { url, name, code, author, scripts, metadata, status, createtime, updatetime, checktime } = s; const { url, name, code, author, scripts, metadata, status, createtime, updatetime, checktime } = s;
return subscribeDAO.save({ return subscribeDAO.save({
url, url,

View File

@ -23,6 +23,7 @@ export default class ContentRuntime {
// 转发给inject // 转发给inject
return sendMessage(this.msg, "inject/runtime/valueUpdate", data); return sendMessage(this.msg, "inject/runtime/valueUpdate", data);
}); });
forwardMessage("serviceWorker", "script/isInstalled", this.server, this.extSend);
forwardMessage( forwardMessage(
"serviceWorker", "serviceWorker",
"runtime/gmApi", "runtime/gmApi",

View File

@ -4,6 +4,8 @@ import ExecScript, { ValueUpdateData } from "./exec_script";
import { addStyle, ScriptFunc } from "./utils"; import { addStyle, ScriptFunc } from "./utils";
import { getStorageName } from "@App/pkg/utils/utils"; import { getStorageName } from "@App/pkg/utils/utils";
import { EmitEventRequest } from "../service_worker/runtime"; import { EmitEventRequest } from "../service_worker/runtime";
import { ExternalWhitelist } from "@App/app/const";
import { sendMessage } from "@Packages/message/client";
export class InjectRuntime { export class InjectRuntime {
execList: ExecScript[] = []; execList: ExecScript[] = [];
@ -44,6 +46,40 @@ export class InjectRuntime {
val.valueUpdate(data); val.valueUpdate(data);
}); });
}); });
// 注入允许外部调用
this.externalMessage();
}
externalMessage() {
// 对外接口白名单
let msg = this.msg;
for (let i = 0; i < ExternalWhitelist.length; i += 1) {
if (window.location.host.endsWith(ExternalWhitelist[i])) {
// 注入
(<{ external: any }>(<unknown>window)).external = window.external || {};
(<
{
external: {
Scriptcat: {
isInstalled: (name: string, namespace: string, callback: any) => void;
};
};
}
>(<unknown>window)).external.Scriptcat = {
async isInstalled(name: string, namespace: string, callback: any) {
const resp = await sendMessage(msg, "content/script/isInstalled", {
name,
namespace,
});
callback(resp);
},
};
(<{ external: { Tampermonkey: any } }>(<unknown>window)).external.Tampermonkey = (<
{ external: { Scriptcat: any } }
>(<unknown>window)).external.Scriptcat;
break;
}
}
} }
execScript(script: ScriptRunResouce, scriptFunc: ScriptFunc) { execScript(script: ScriptRunResouce, scriptFunc: ScriptFunc) {

View File

@ -9,6 +9,8 @@ import { PopupService } from "./popup";
import { SystemConfig } from "@App/pkg/config/config"; import { SystemConfig } from "@App/pkg/config/config";
import { SynchronizeService } from "./synchronize"; import { SynchronizeService } from "./synchronize";
import { SubscribeService } from "./subscribe"; import { SubscribeService } from "./subscribe";
import { ExtServer, ExtVersion } from "@App/app/const";
import { systemConfig } from "@App/pages/store/global";
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode"; export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
@ -78,8 +80,17 @@ export default class ServiceWorkerManager {
case "checkSubscribeUpdate": case "checkSubscribeUpdate":
subscribe.checkSubscribeUpdate(); subscribe.checkSubscribeUpdate();
break; break;
case "checkUpdate":
// 检查扩展更新
this.checkUpdate();
break;
} }
}); });
// 8小时检查一次扩展更新
chrome.alarms.create("checkUpdate", {
delayInMinutes: 0,
periodInMinutes: 8 * 60,
});
// 监听配置变化 // 监听配置变化
this.mq.subscribe("systemConfigChange", (msg) => { this.mq.subscribe("systemConfigChange", (msg) => {
@ -96,4 +107,18 @@ export default class ServiceWorkerManager {
synchronize.cloudSyncConfigChange(config); synchronize.cloudSyncConfigChange(config);
}); });
} }
checkUpdate() {
fetch(`${ExtServer}api/v1/system/version?version=${ExtVersion}`)
.then((resp) => resp.json())
.then((resp: { data: { notice: string; version: string } }) => {
systemConfig.getCheckUpdate().then((items) => {
if (items.notice !== resp.data.notice) {
systemConfig.setCheckUpdate(Object.assign(resp.data, { isRead: false }));
} else {
systemConfig.setCheckUpdate(Object.assign(resp.data, { isRead: items.isRead }));
}
});
});
}
} }

View File

@ -15,7 +15,7 @@ import { subscribeScriptDelete, subscribeScriptEnable, subscribeScriptInstall }
import { ScriptService } from "./script"; import { ScriptService } from "./script";
import { runScript, stopScript } from "../offscreen/client"; import { runScript, stopScript } from "../offscreen/client";
import { getRunAt } from "./utils"; import { getRunAt } from "./utils";
import { randomString } from "@App/pkg/utils/utils"; import { isUserScriptsAvailable, randomString } from "@App/pkg/utils/utils";
import Cache from "@App/app/cache"; import Cache from "@App/app/cache";
import { dealPatternMatches, UrlMatch } from "@App/pkg/utils/match"; import { dealPatternMatches, UrlMatch } from "@App/pkg/utils/match";
import { ExtensionContentMessageSend } from "@Packages/message/extension_message"; import { ExtensionContentMessageSend } from "@Packages/message/extension_message";
@ -70,6 +70,11 @@ export class RuntimeService {
this.group.on("runScript", this.runScript.bind(this)); this.group.on("runScript", this.runScript.bind(this));
this.group.on("pageLoad", this.pageLoad.bind(this)); this.group.on("pageLoad", this.pageLoad.bind(this));
// 检查是否开启了开发者模式
if(!isUserScriptsAvailable()){
// 未开启加上警告引导
}
// 读取inject.js注入页面 // 读取inject.js注入页面
this.registerInjectScript(); this.registerInjectScript();
// 监听脚本开启 // 监听脚本开启

View File

@ -21,6 +21,7 @@ import { ResourceService } from "./resource";
import { ValueService } from "./value"; import { ValueService } from "./value";
import { compileScriptCode } from "../content/utils"; import { compileScriptCode } from "../content/utils";
import { SystemConfig } from "@App/pkg/config/config"; import { SystemConfig } from "@App/pkg/config/config";
import i18n from "@App/locales/locales";
export class ScriptService { export class ScriptService {
logger: Logger; logger: Logger;
@ -59,50 +60,59 @@ export class ScriptService {
// 读取脚本url内容, 进行安装 // 读取脚本url内容, 进行安装
const logger = this.logger.with({ url: targetUrl }); const logger = this.logger.with({ url: targetUrl });
logger.debug("install script"); logger.debug("install script");
this.openInstallPageByUrl(targetUrl, "user").catch((e) => { this.openInstallPageByUrl(targetUrl, "user")
logger.error("install script error", Logger.E(e)); .catch((e) => {
// 如果打开失败, 则重定向到安装页 logger.error("install script error", Logger.E(e));
chrome.scripting.executeScript({ // 不再重定向当前url
target: { tabId: req.tabId }, chrome.declarativeNetRequest.updateDynamicRules(
func: function () { {
history.back(); removeRuleIds: [2],
}, addRules: [
}); {
// 并不再重定向当前url id: 2,
chrome.declarativeNetRequest.updateDynamicRules( priority: 1,
{ action: {
removeRuleIds: [2], type: chrome.declarativeNetRequest.RuleActionType.ALLOW,
addRules: [ },
{ condition: {
id: 2, regexFilter: targetUrl,
priority: 1, resourceTypes: [chrome.declarativeNetRequest.ResourceType.MAIN_FRAME],
action: { requestMethods: [chrome.declarativeNetRequest.RequestMethod.GET],
type: chrome.declarativeNetRequest.RuleActionType.ALLOW, },
}, },
condition: { ],
regexFilter: targetUrl, },
resourceTypes: [chrome.declarativeNetRequest.ResourceType.MAIN_FRAME], () => {
requestMethods: [chrome.declarativeNetRequest.RequestMethod.GET], if (chrome.runtime.lastError) {
}, console.error(chrome.runtime.lastError);
}, }
],
},
() => {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError);
} }
} );
); })
}); .finally(() => {
// 回退到到安装页
chrome.scripting.executeScript({
target: { tabId: req.tabId },
func: function () {
history.back();
},
});
});
}, },
{ {
urls: [ urls: [
"https://docs.scriptcat.org/docs/script_installation", "https://docs.scriptcat.org/docs/script_installation/",
"https://docs.scriptcat.org/en/docs/script_installation/",
"https://www.tampermonkey.net/script_installation.php", "https://www.tampermonkey.net/script_installation.php",
], ],
types: ["main_frame"], types: ["main_frame"],
} }
); );
// 获取i18n
let localePath = "";
if (i18n.language !== "zh-CN") {
localePath = `/en`;
}
// 重定向到脚本安装页 // 重定向到脚本安装页
chrome.declarativeNetRequest.updateDynamicRules( chrome.declarativeNetRequest.updateDynamicRules(
{ {
@ -114,7 +124,7 @@ export class ScriptService {
action: { action: {
type: chrome.declarativeNetRequest.RuleActionType.REDIRECT, type: chrome.declarativeNetRequest.RuleActionType.REDIRECT,
redirect: { redirect: {
regexSubstitution: "https://docs.scriptcat.org/docs/script_installation#url=\\0", regexSubstitution: `https://docs.scriptcat.org${localePath}/docs/script_installation/#url=\\0`,
}, },
}, },
condition: { condition: {
@ -479,6 +489,15 @@ export class ScriptService {
return this.checkUpdate(uuid, "user"); return this.checkUpdate(uuid, "user");
} }
isInstalled({ name, namespace }: { name: string; namespace: string }) {
return this.scriptDAO.findByNameAndNamespace(name, namespace).then((script) => {
if (script) {
return { installed: true, version: script.metadata.version && script.metadata.version[0] };
}
return { installed: false };
});
}
init() { init() {
this.listenerScriptInstall(); this.listenerScriptInstall();
@ -494,6 +513,7 @@ export class ScriptService {
this.group.on("resetMatch", this.resetMatch.bind(this)); this.group.on("resetMatch", this.resetMatch.bind(this));
this.group.on("resetExclude", this.resetExclude.bind(this)); this.group.on("resetExclude", this.resetExclude.bind(this));
this.group.on("requestCheckUpdate", this.requestCheckUpdate.bind(this)); this.group.on("requestCheckUpdate", this.requestCheckUpdate.bind(this));
this.group.on("isInstalled", this.isInstalled.bind(this));
// 定时检查更新, 每10分钟检查一次 // 定时检查更新, 每10分钟检查一次
chrome.alarms.create("checkScriptUpdate", { chrome.alarms.create("checkScriptUpdate", {

View File

@ -1,7 +1,7 @@
{ {
"manifest_version": 3, "manifest_version": 3,
"name": "__MSG_scriptcat__", "name": "__MSG_scriptcat__",
"version": "0.17.0.1003", "version": "0.17.0.1005",
"author": "CodFrm", "author": "CodFrm",
"description": "__MSG_scriptcat_description__", "description": "__MSG_scriptcat_description__",
"options_ui": { "options_ui": {

View File

@ -39,11 +39,9 @@ const CodeEditor: React.ForwardRefRenderFunction<{ editor: editor.IStandaloneCod
}, []); }, []);
useEffect(() => { useEffect(() => {
console.log("1231", code);
if (diffCode === undefined || code === undefined || !div.current) { if (diffCode === undefined || code === undefined || !div.current) {
return () => {}; return () => {};
} }
console.log("1232");
let edit: editor.IStandaloneDiffEditor | editor.IStandaloneCodeEditor; let edit: editor.IStandaloneDiffEditor | editor.IStandaloneCodeEditor;
const inlineDiv = document.getElementById(id) as HTMLDivElement; const inlineDiv = document.getElementById(id) as HTMLDivElement;
// @ts-ignore // @ts-ignore

View File

@ -1,4 +1,4 @@
import { Script, ScriptAndCode, ScriptCodeDAO, ScriptDAO } from "@App/app/repo/scripts"; import { Script, SCRIPT_TYPE_NORMAL, ScriptAndCode, ScriptCodeDAO, ScriptDAO } from "@App/app/repo/scripts";
import CodeEditor from "@App/pages/components/CodeEditor"; import CodeEditor from "@App/pages/components/CodeEditor";
import React, { useCallback, useEffect, useRef, useState } from "react"; import React, { useCallback, useEffect, useRef, useState } from "react";
import { useNavigate, useParams, useSearchParams } from "react-router-dom"; import { useNavigate, useParams, useSearchParams } from "react-router-dom";
@ -16,7 +16,7 @@ import { prepareScriptByCode } from "@App/pkg/utils/script";
import ScriptStorage from "@App/pages/components/ScriptStorage"; import ScriptStorage from "@App/pages/components/ScriptStorage";
import ScriptResource from "@App/pages/components/ScriptResource"; import ScriptResource from "@App/pages/components/ScriptResource";
import ScriptSetting from "@App/pages/components/ScriptSetting"; import ScriptSetting from "@App/pages/components/ScriptSetting";
import { scriptClient } from "@App/pages/store/features/script"; import { runtimeClient, scriptClient } from "@App/pages/store/features/script";
import { i18nName } from "@App/locales/locales"; import { i18nName } from "@App/locales/locales";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@ -188,57 +188,58 @@ function ScriptEditor() {
const save = (script: Script, e: editor.IStandaloneCodeEditor): Promise<Script> => { const save = (script: Script, e: editor.IStandaloneCodeEditor): Promise<Script> => {
// 解析code生成新的script并更新 // 解析code生成新的script并更新
return new Promise(() => { return prepareScriptByCode(e.getValue(), script.origin || "", script.uuid)
prepareScriptByCode(e.getValue(), script.origin || "", script.uuid) .then((prepareScript) => {
.then((prepareScript) => { const newScript = prepareScript.script;
const newScript = prepareScript.script; if (!newScript.name) {
if (!newScript.name) { Message.warning(t("script_name_cannot_be_set_to_empty"));
Message.warning(t("script_name_cannot_be_set_to_empty")); return Promise.reject(new Error("script name cannot be empty"));
return; }
} return scriptClient
scriptClient.install(newScript, e.getValue()).then( .install(newScript, e.getValue())
(update) => { .then((update): Script => {
if (!update) { if (!update) {
Message.success("新建成功,请注意后台脚本不会默认开启"); Message.success("新建成功,请注意后台脚本不会默认开启");
// 保存的时候如何左侧没有脚本即新建 // 保存的时候如何左侧没有脚本即新建
setScriptList((prev) => { setScriptList((prev) => {
setSelectSciptButtonAndTab(newScript.uuid); setSelectSciptButtonAndTab(newScript.uuid);
return [newScript, ...prev]; return [newScript, ...prev];
}); });
} else { } else {
setScriptList((prev) => { setScriptList((prev) => {
// eslint-disable-next-line no-shadow, array-callback-return prev.map((script: Script) => {
prev.map((script: Script) => { if (script.uuid === newScript.uuid) {
if (script.uuid === newScript.uuid) { script.name = newScript.name;
script.name = newScript.name;
}
});
return [...prev];
});
Message.success("保存成功");
}
setEditors((prev) => {
for (let i = 0; i < prev.length; i += 1) {
if (prev[i].script.uuid === newScript.uuid) {
prev[i].code = e.getValue();
prev[i].isChanged = false;
prev[i].script.name = newScript.name;
break;
} }
} });
return [...prev]; return [...prev];
}); });
}, Message.success("保存成功");
(err: any) => {
Message.error(`保存失败: ${err}`);
} }
); setEditors((prev) => {
}) for (let i = 0; i < prev.length; i += 1) {
.catch((err) => { if (prev[i].script.uuid === newScript.uuid) {
Message.error(`错误的脚本代码: ${err}`); prev[i].code = e.getValue();
}); prev[i].isChanged = false;
}); prev[i].script.name = newScript.name;
break;
}
}
return [...prev];
});
return newScript;
})
.catch((err: any) => {
Message.error(`保存失败: ${err}`);
return Promise.reject(err);
});
})
.catch((err) => {
Message.error(`错误的脚本代码: ${err}`);
return Promise.reject(err);
});
}; };
const saveAs = (script: Script, e: editor.IStandaloneCodeEditor) => { const saveAs = (script: Script, e: editor.IStandaloneCodeEditor) => {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
chrome.downloads.download( chrome.downloads.download(
@ -289,30 +290,35 @@ function ScriptEditor() {
title: t("run"), title: t("run"),
items: [ items: [
{ {
id: "debug", id: "run",
title: t("debug"), title: t("run"),
hotKey: KeyMod.CtrlCmd | KeyCode.F5, hotKey: KeyMod.CtrlCmd | KeyCode.F5,
hotKeyString: "Ctrl+F5", hotKeyString: "Ctrl+F5",
tooltip: "只有后台脚本/定时脚本才能调试, 且调试模式下不对进行权限校验(例如@connect)", tooltip: "只有后台脚本/定时脚本才能运行",
action: async (script, e) => { action: async (script, e) => {
// 保存更新代码之后再调试 // 保存更新代码之后再调试
const newScript = await save(script, e); const newScript = await save(script, e);
// 判断脚本类型
if (newScript.type === SCRIPT_TYPE_NORMAL) {
Message.error("只有后台脚本/定时脚本才能运行");
return;
}
Message.loading({ Message.loading({
id: "debug_script", id: "debug_script",
content: "正在准备脚本资源...", content: "正在准备脚本资源...",
duration: 3000, duration: 3000,
}); });
runtimeCtrl runtimeClient
.debugScript(newScript) .runScript(newScript.uuid)
.then(() => { .then(() => {
Message.success({ Message.success({
id: "debug_script", id: "debug_script",
content: "构建成功, 可以打开开发者工具在控制台中查看输出", content: "构建成功, 可以在扩展页打开开发者工具在控制台中查看输出",
duration: 3000, duration: 3000,
}); });
}) })
.catch((err) => { .catch((err) => {
LoggerCore.logger(Logger.E(err)).debug("debug script error"); LoggerCore.logger(Logger.E(err)).debug("run script error");
Message.error({ Message.error({
id: "debug_script", id: "debug_script",
content: `构建失败: ${err}`, content: `构建失败: ${err}`,

View File

@ -17,6 +17,8 @@ import { useTranslation } from "react-i18next";
import ScriptMenuList from "../components/ScriptMenuList"; import ScriptMenuList from "../components/ScriptMenuList";
import { popupClient } from "../store/features/script"; import { popupClient } from "../store/features/script";
import { ScriptMenu } from "@App/app/service/service_worker/popup"; import { ScriptMenu } from "@App/app/service/service_worker/popup";
import { systemConfig } from "../store/global";
import { SystemConfig } from "@App/pkg/config/config";
const CollapseItem = Collapse.Item; const CollapseItem = Collapse.Item;
@ -30,9 +32,11 @@ function App() {
const [scriptList, setScriptList] = useState<ScriptMenu[]>([]); const [scriptList, setScriptList] = useState<ScriptMenu[]>([]);
const [backScriptList, setBackScriptList] = useState<ScriptMenu[]>([]); const [backScriptList, setBackScriptList] = useState<ScriptMenu[]>([]);
const [showAlert, setShowAlert] = useState(false); const [showAlert, setShowAlert] = useState(false);
const [notice, setNotice] = useState(""); const [checkUpdate, setCheckUpdate] = useState<Parameters<typeof systemConfig.setCheckUpdate>[0]>({
const [isRead, setIsRead] = useState(true); version: ExtVersion,
const [version, setVersion] = useState(ExtVersion); notice: "",
isRead: false,
});
const [currentUrl, setCurrentUrl] = useState(""); const [currentUrl, setCurrentUrl] = useState("");
const [isEnableScript, setIsEnableScript] = useState(localStorage.enable_script !== "false"); const [isEnableScript, setIsEnableScript] = useState(localStorage.enable_script !== "false");
const { t } = useTranslation(); const { t } = useTranslation();
@ -45,22 +49,15 @@ function App() {
} }
useEffect(() => { useEffect(() => {
// systemManage.getNotice().then((res) => { systemConfig.getCheckUpdate().then((res) => {
// if (res) { setCheckUpdate(res);
// setNotice(res.notice); });
// setIsRead(res.isRead);
// }
// });
// systemManage.getVersion().then((res) => {
// res && setVersion(res);
// });
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (!tabs.length) { if (!tabs.length) {
return; return;
} }
setCurrentUrl(tabs[0].url || ""); setCurrentUrl(tabs[0].url || "");
popupClient.getPopupData({ url: tabs[0].url!, tabId: tabs[0].id! }).then((resp) => { popupClient.getPopupData({ url: tabs[0].url!, tabId: tabs[0].id! }).then((resp) => {
console.log(resp);
// 按照开启状态和更新时间排序 // 按照开启状态和更新时间排序
const list = resp.scriptList; const list = resp.scriptList;
list.sort((a, b) => { list.sort((a, b) => {
@ -109,15 +106,17 @@ function App() {
window.open("/src/options.html", "_blank"); window.open("/src/options.html", "_blank");
}} }}
/> />
<Badge count={isRead ? 0 : 1} dot offset={[-8, 6]}> <Badge count={checkUpdate.isRead ? 0 : 1} dot offset={[-8, 6]}>
<Button <Button
type="text" type="text"
icon={<IconNotification />} icon={<IconNotification />}
iconOnly iconOnly
onClick={() => { onClick={() => {
setShowAlert(!showAlert); setShowAlert(!showAlert);
setIsRead(true); console.log(checkUpdate);
systemManage.setRead(true); checkUpdate.isRead = true;
setCheckUpdate(checkUpdate);
systemConfig.setCheckUpdate(checkUpdate);
}} }}
/> />
</Badge> </Badge>
@ -179,9 +178,9 @@ function App() {
bodyStyle={{ padding: 0 }} bodyStyle={{ padding: 0 }}
> >
<Alert <Alert
style={{ marginBottom: 20, display: showAlert ? "flex" : "none" }} style={{ display: showAlert ? "flex" : "none" }}
type="info" type="info"
content={<div dangerouslySetInnerHTML={{ __html: notice }} />} content={<div dangerouslySetInnerHTML={{ __html: checkUpdate.notice || "" }} />}
/> />
<Collapse bordered={false} defaultActiveKey={["script", "background"]} style={{ maxWidth: 640 }}> <Collapse bordered={false} defaultActiveKey={["script", "background"]} style={{ maxWidth: 640 }}>
<CollapseItem <CollapseItem
@ -204,7 +203,7 @@ function App() {
</Collapse> </Collapse>
<div className="flex flex-row arco-card-header !h-6"> <div className="flex flex-row arco-card-header !h-6">
<span className="text-[12px] font-500">{`v${ExtVersion}`}</span> <span className="text-[12px] font-500">{`v${ExtVersion}`}</span>
{semver.lt(ExtVersion, version) && ( {semver.lt(ExtVersion, checkUpdate.version) && (
<span <span
onClick={() => { onClick={() => {
window.open(`https://github.com/scriptscat/scriptcat/releases/tag/v${version}`); window.open(`https://github.com/scriptscat/scriptcat/releases/tag/v${version}`);

View File

@ -5,6 +5,7 @@ import { FileSystemType } from "@Packages/filesystem/factory";
import { MessageQueue } from "@Packages/message/message_queue"; import { MessageQueue } from "@Packages/message/message_queue";
import i18n from "@App/locales/locales"; import i18n from "@App/locales/locales";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { ExtVersion } from "@App/app/const";
export const SystamConfigChange = "systemConfigChange"; export const SystamConfigChange = "systemConfigChange";
@ -65,9 +66,7 @@ export class SystemConfig {
public set(key: string, val: any) { public set(key: string, val: any) {
this.cache.set(key, val); this.cache.set(key, val);
this.storage.set(key, val).then(() => { this.storage.set(key, val);
console.log(chrome.runtime.lastError, val);
});
// 发送消息通知更新 // 发送消息通知更新
this.mq.publish(SystamConfigChange, { this.mq.publish(SystamConfigChange, {
key, key,
@ -247,4 +246,20 @@ export class SystemConfig {
i18n.changeLanguage(value); i18n.changeLanguage(value);
dayjs.locale(value.toLocaleLowerCase()); dayjs.locale(value.toLocaleLowerCase());
} }
setCheckUpdate(data: { notice: string; version: string; isRead: boolean }) {
this.set("check_update", {
notice: data.notice,
version: data.version,
isRead: data.isRead,
});
}
getCheckUpdate(): Promise<Parameters<typeof this.setCheckUpdate>[0]> {
return this.get("check_update", {
notice: "",
isRead: false,
version: ExtVersion,
});
}
} }

View File

@ -264,3 +264,15 @@ export function errorMsg(e: any): string {
} }
return ""; return "";
} }
export function isUserScriptsAvailable() {
return false;
try {
// Property access which throws if developer mode is not enabled.
chrome.userScripts;
return true;
} catch {
// Not available.
return false;
}
}