Skip to content

Commit 223da30

Browse files
committed
♻️ 优化引导与脚本站外部调用等功能
1 parent 37a5731 commit 223da30

15 files changed

Lines changed: 401 additions & 252 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "scriptcat",
3-
"version": "0.17.0-alpha.3",
3+
"version": "0.17.0-alpha.4",
44
"description": "脚本猫,一个可以执行用户脚本的浏览器扩展,万物皆可脚本化,让你的浏览器可以做更多的事情!",
55
"author": "CodFrm",
66
"license": "GPLv3",

src/app/migrate.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ function renameField() {
113113
if (subscribe.length) {
114114
await Promise.all(
115115
subscribe.map((s: Subscribe) => {
116-
console.log("1234", s);
117116
const { url, name, code, author, scripts, metadata, status, createtime, updatetime, checktime } = s;
118117
return subscribeDAO.save({
119118
url,

src/app/service/content/content.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default class ContentRuntime {
2323
// 转发给inject
2424
return sendMessage(this.msg, "inject/runtime/valueUpdate", data);
2525
});
26+
forwardMessage("serviceWorker", "script/isInstalled", this.server, this.extSend);
2627
forwardMessage(
2728
"serviceWorker",
2829
"runtime/gmApi",

src/app/service/content/inject.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import ExecScript, { ValueUpdateData } from "./exec_script";
44
import { addStyle, ScriptFunc } from "./utils";
55
import { getStorageName } from "@App/pkg/utils/utils";
66
import { EmitEventRequest } from "../service_worker/runtime";
7+
import { ExternalWhitelist } from "@App/app/const";
8+
import { sendMessage } from "@Packages/message/client";
79

810
export class InjectRuntime {
911
execList: ExecScript[] = [];
@@ -44,6 +46,40 @@ export class InjectRuntime {
4446
val.valueUpdate(data);
4547
});
4648
});
49+
// 注入允许外部调用
50+
this.externalMessage();
51+
}
52+
53+
externalMessage() {
54+
// 对外接口白名单
55+
let msg = this.msg;
56+
for (let i = 0; i < ExternalWhitelist.length; i += 1) {
57+
if (window.location.host.endsWith(ExternalWhitelist[i])) {
58+
// 注入
59+
(<{ external: any }>(<unknown>window)).external = window.external || {};
60+
(<
61+
{
62+
external: {
63+
Scriptcat: {
64+
isInstalled: (name: string, namespace: string, callback: any) => void;
65+
};
66+
};
67+
}
68+
>(<unknown>window)).external.Scriptcat = {
69+
async isInstalled(name: string, namespace: string, callback: any) {
70+
const resp = await sendMessage(msg, "content/script/isInstalled", {
71+
name,
72+
namespace,
73+
});
74+
callback(resp);
75+
},
76+
};
77+
(<{ external: { Tampermonkey: any } }>(<unknown>window)).external.Tampermonkey = (<
78+
{ external: { Scriptcat: any } }
79+
>(<unknown>window)).external.Scriptcat;
80+
break;
81+
}
82+
}
4783
}
4884

4985
execScript(script: ScriptRunResouce, scriptFunc: ScriptFunc) {

src/app/service/service_worker/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { PopupService } from "./popup";
99
import { SystemConfig } from "@App/pkg/config/config";
1010
import { SynchronizeService } from "./synchronize";
1111
import { SubscribeService } from "./subscribe";
12+
import { ExtServer, ExtVersion } from "@App/app/const";
13+
import { systemConfig } from "@App/pages/store/global";
1214

1315
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
1416

@@ -78,8 +80,17 @@ export default class ServiceWorkerManager {
7880
case "checkSubscribeUpdate":
7981
subscribe.checkSubscribeUpdate();
8082
break;
83+
case "checkUpdate":
84+
// 检查扩展更新
85+
this.checkUpdate();
86+
break;
8187
}
8288
});
89+
// 8小时检查一次扩展更新
90+
chrome.alarms.create("checkUpdate", {
91+
delayInMinutes: 0,
92+
periodInMinutes: 8 * 60,
93+
});
8394

8495
// 监听配置变化
8596
this.mq.subscribe("systemConfigChange", (msg) => {
@@ -96,4 +107,18 @@ export default class ServiceWorkerManager {
96107
synchronize.cloudSyncConfigChange(config);
97108
});
98109
}
110+
111+
checkUpdate() {
112+
fetch(`${ExtServer}api/v1/system/version?version=${ExtVersion}`)
113+
.then((resp) => resp.json())
114+
.then((resp: { data: { notice: string; version: string } }) => {
115+
systemConfig.getCheckUpdate().then((items) => {
116+
if (items.notice !== resp.data.notice) {
117+
systemConfig.setCheckUpdate(Object.assign(resp.data, { isRead: false }));
118+
} else {
119+
systemConfig.setCheckUpdate(Object.assign(resp.data, { isRead: items.isRead }));
120+
}
121+
});
122+
});
123+
}
99124
}

src/app/service/service_worker/runtime.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { subscribeScriptDelete, subscribeScriptEnable, subscribeScriptInstall }
1515
import { ScriptService } from "./script";
1616
import { runScript, stopScript } from "../offscreen/client";
1717
import { getRunAt } from "./utils";
18-
import { randomString } from "@App/pkg/utils/utils";
18+
import { InfoNotification, isUserScriptsAvailable, randomString } from "@App/pkg/utils/utils";
1919
import Cache from "@App/app/cache";
2020
import { dealPatternMatches, UrlMatch } from "@App/pkg/utils/match";
2121
import { ExtensionContentMessageSend } from "@Packages/message/extension_message";
@@ -27,6 +27,8 @@ import LoggerCore from "@App/app/logger/core";
2727
import PermissionVerify from "./permission_verify";
2828
import { SystemConfig } from "@App/pkg/config/config";
2929
import { ResourceService } from "./resource";
30+
import { LocalStorageDAO } from "@App/app/repo/localStorage";
31+
import i18n from "@App/locales/locales";
3032

3133
// 为了优化性能,存储到缓存时删除了code、value与resource
3234
export interface ScriptMatchInfo extends ScriptRunResouce {
@@ -49,6 +51,8 @@ export class RuntimeService {
4951
scriptCustomizeMatch: UrlMatch<string> = new UrlMatch<string>();
5052
scriptMatchCache: Map<string, ScriptMatchInfo> | null | undefined;
5153

54+
isEnableDeveloperMode = false;
55+
5256
constructor(
5357
private systemConfig: SystemConfig,
5458
private group: Group,
@@ -70,6 +74,34 @@ export class RuntimeService {
7074
this.group.on("runScript", this.runScript.bind(this));
7175
this.group.on("pageLoad", this.pageLoad.bind(this));
7276

77+
// 检查是否开启了开发者模式
78+
this.isEnableDeveloperMode = isUserScriptsAvailable();
79+
if (!this.isEnableDeveloperMode) {
80+
// 未开启加上警告引导
81+
// 判断是否首次
82+
const localStorage = new LocalStorageDAO();
83+
localStorage.get("firstShowDeveloperMode").then((res) => {
84+
if (!res) {
85+
localStorage.save({
86+
key: "firstShowDeveloperMode",
87+
value: true,
88+
});
89+
// 打开页面
90+
chrome.tabs.create({
91+
url: `https://docs.scriptcat.org/docs/use/open-dev/`,
92+
});
93+
}
94+
});
95+
chrome.action.setBadgeBackgroundColor({
96+
color: "#ff8c00",
97+
});
98+
chrome.action.setBadgeTextColor({
99+
color: "#ffffff",
100+
});
101+
chrome.action.setBadgeText({
102+
text: "!",
103+
});
104+
}
73105
// 读取inject.js注入页面
74106
this.registerInjectScript();
75107
// 监听脚本开启
@@ -434,7 +466,7 @@ export class RuntimeService {
434466
this.addScriptMatch(scriptMatchInfo);
435467

436468
// 如果脚本开启, 则注册脚本
437-
if (script.status === SCRIPT_STATUS_ENABLE) {
469+
if (this.isEnableDeveloperMode && script.status === SCRIPT_STATUS_ENABLE) {
438470
if (!scriptRes.metadata["noframes"]) {
439471
registerScript.allFrames = true;
440472
}
@@ -462,7 +494,7 @@ export class RuntimeService {
462494
}
463495

464496
async unregistryPageScript(uuid: string) {
465-
if (!(await Cache.getInstance().get("registryScript:" + uuid))) {
497+
if (!this.isEnableDeveloperMode || !(await Cache.getInstance().get("registryScript:" + uuid))) {
466498
return;
467499
}
468500
chrome.userScripts.unregister(

src/app/service/service_worker/script.ts

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ResourceService } from "./resource";
2121
import { ValueService } from "./value";
2222
import { compileScriptCode } from "../content/utils";
2323
import { SystemConfig } from "@App/pkg/config/config";
24+
import i18n, { localePath } from "@App/locales/locales";
2425

2526
export class ScriptService {
2627
logger: Logger;
@@ -59,50 +60,55 @@ export class ScriptService {
5960
// 读取脚本url内容, 进行安装
6061
const logger = this.logger.with({ url: targetUrl });
6162
logger.debug("install script");
62-
this.openInstallPageByUrl(targetUrl, "user").catch((e) => {
63-
logger.error("install script error", Logger.E(e));
64-
// 如果打开失败, 则重定向到安装页
65-
chrome.scripting.executeScript({
66-
target: { tabId: req.tabId },
67-
func: function () {
68-
history.back();
69-
},
70-
});
71-
// 并不再重定向当前url
72-
chrome.declarativeNetRequest.updateDynamicRules(
73-
{
74-
removeRuleIds: [2],
75-
addRules: [
76-
{
77-
id: 2,
78-
priority: 1,
79-
action: {
80-
type: chrome.declarativeNetRequest.RuleActionType.ALLOW,
63+
this.openInstallPageByUrl(targetUrl, "user")
64+
.catch((e) => {
65+
logger.error("install script error", Logger.E(e));
66+
// 不再重定向当前url
67+
chrome.declarativeNetRequest.updateDynamicRules(
68+
{
69+
removeRuleIds: [2],
70+
addRules: [
71+
{
72+
id: 2,
73+
priority: 1,
74+
action: {
75+
type: chrome.declarativeNetRequest.RuleActionType.ALLOW,
76+
},
77+
condition: {
78+
regexFilter: targetUrl,
79+
resourceTypes: [chrome.declarativeNetRequest.ResourceType.MAIN_FRAME],
80+
requestMethods: [chrome.declarativeNetRequest.RequestMethod.GET],
81+
},
8182
},
82-
condition: {
83-
regexFilter: targetUrl,
84-
resourceTypes: [chrome.declarativeNetRequest.ResourceType.MAIN_FRAME],
85-
requestMethods: [chrome.declarativeNetRequest.RequestMethod.GET],
86-
},
87-
},
88-
],
89-
},
90-
() => {
91-
if (chrome.runtime.lastError) {
92-
console.error(chrome.runtime.lastError);
83+
],
84+
},
85+
() => {
86+
if (chrome.runtime.lastError) {
87+
console.error(chrome.runtime.lastError);
88+
}
9389
}
94-
}
95-
);
96-
});
90+
);
91+
})
92+
.finally(() => {
93+
// 回退到到安装页
94+
chrome.scripting.executeScript({
95+
target: { tabId: req.tabId },
96+
func: function () {
97+
history.back();
98+
},
99+
});
100+
});
97101
},
98102
{
99103
urls: [
100-
"https://docs.scriptcat.org/docs/script_installation",
104+
"https://docs.scriptcat.org/docs/script_installation/",
105+
"https://docs.scriptcat.org/en/docs/script_installation/",
101106
"https://www.tampermonkey.net/script_installation.php",
102107
],
103108
types: ["main_frame"],
104109
}
105110
);
111+
// 获取i18n
106112
// 重定向到脚本安装页
107113
chrome.declarativeNetRequest.updateDynamicRules(
108114
{
@@ -114,7 +120,7 @@ export class ScriptService {
114120
action: {
115121
type: chrome.declarativeNetRequest.RuleActionType.REDIRECT,
116122
redirect: {
117-
regexSubstitution: "https://docs.scriptcat.org/docs/script_installation#url=\\0",
123+
regexSubstitution: `https://docs.scriptcat.org${localePath}/docs/script_installation/#url=\\0`,
118124
},
119125
},
120126
condition: {
@@ -479,6 +485,15 @@ export class ScriptService {
479485
return this.checkUpdate(uuid, "user");
480486
}
481487

488+
isInstalled({ name, namespace }: { name: string; namespace: string }) {
489+
return this.scriptDAO.findByNameAndNamespace(name, namespace).then((script) => {
490+
if (script) {
491+
return { installed: true, version: script.metadata.version && script.metadata.version[0] };
492+
}
493+
return { installed: false };
494+
});
495+
}
496+
482497
init() {
483498
this.listenerScriptInstall();
484499

@@ -494,6 +509,7 @@ export class ScriptService {
494509
this.group.on("resetMatch", this.resetMatch.bind(this));
495510
this.group.on("resetExclude", this.resetExclude.bind(this));
496511
this.group.on("requestCheckUpdate", this.requestCheckUpdate.bind(this));
512+
this.group.on("isInstalled", this.isInstalled.bind(this));
497513

498514
// 定时检查更新, 每10分钟检查一次
499515
chrome.alarms.create("checkScriptUpdate", {

src/locales/locales.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,15 @@ i18n.use(initReactI18next).init({
2727
},
2828
});
2929

30+
export let localePath = "";
31+
3032
chrome.i18n.getAcceptLanguages((lngs) => {
31-
systemConfig.getLanguage().then((lng) => {
33+
systemConfig.getLanguage(lngs).then((lng) => {
3234
i18n.changeLanguage(lng);
3335
dayjs.locale(lng.toLocaleLowerCase());
36+
if (lng !== "zh-CN") {
37+
localePath = "en";
38+
}
3439
});
3540
});
3641

src/locales/zh-CN/translation.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,5 +368,6 @@
368368
"eslint_config_format_error": "eslint配置格式错误",
369369
"export_success": "导出成功",
370370
"get_backup_dir_url_failed": "获取备份目录地址失败",
371-
"get_backup_files_failed": "获取备份文件失败"
371+
"get_backup_files_failed": "获取备份文件失败",
372+
"develop_mode_guide": "检测到当前未开启开发者模式,您的脚本无法正常使用,<a href=\"https://docs.scriptcat.org/docs/use/open-dev/\" target=\"black\" style=\"color: var(--color-text-1)\">👉点我了解如何开启</a>"
372373
}

src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"manifest_version": 3,
33
"name": "__MSG_scriptcat__",
4-
"version": "0.17.0.1004",
4+
"version": "0.17.0.1005",
55
"author": "CodFrm",
66
"description": "__MSG_scriptcat_description__",
77
"options_ui": {

0 commit comments

Comments
 (0)