脚本订阅功能
This commit is contained in:
parent
44066d9543
commit
d7adffcd9f
@ -9,7 +9,7 @@ export abstract class Repo<T> {
|
|||||||
return this.prefix + key;
|
return this.prefix + key;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async _save(key: string, val: T):Promise<T> {
|
protected async _save(key: string, val: T): Promise<T> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const data = {
|
const data = {
|
||||||
[this.joinKey(key)]: val,
|
[this.joinKey(key)]: val,
|
||||||
|
@ -12,7 +12,6 @@ export interface SubscribeScript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Subscribe {
|
export interface Subscribe {
|
||||||
id: number;
|
|
||||||
url: string;
|
url: string;
|
||||||
name: string;
|
name: string;
|
||||||
code: string;
|
code: string;
|
||||||
@ -31,6 +30,10 @@ export class SubscribeDAO extends Repo<Subscribe> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public findByUrl(url: string) {
|
public findByUrl(url: string) {
|
||||||
return this.findOne((key, value) => value.url === url);
|
return this.get(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public save(val: Subscribe) {
|
||||||
|
return super._save(val.url, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { MessageQueue } from "@Packages/message/message_queue";
|
import { MessageQueue } from "@Packages/message/message_queue";
|
||||||
import { Script, SCRIPT_RUN_STATUS } from "../repo/scripts";
|
import { Script, SCRIPT_RUN_STATUS } from "../repo/scripts";
|
||||||
import { InstallSource } from "./service_worker";
|
import { InstallSource } from "./service_worker";
|
||||||
|
import { Subscribe } from "../repo/subscribe";
|
||||||
|
|
||||||
export function subscribeScriptInstall(
|
export function subscribeScriptInstall(
|
||||||
messageQueue: MessageQueue,
|
messageQueue: MessageQueue,
|
||||||
@ -13,6 +14,17 @@ export function subscribeScriptDelete(messageQueue: MessageQueue, callback: (mes
|
|||||||
return messageQueue.subscribe("deleteScript", callback);
|
return messageQueue.subscribe("deleteScript", callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function subscribeSubscribeInstall(
|
||||||
|
messageQueue: MessageQueue,
|
||||||
|
callback: (message: { subscribe: Subscribe; update: boolean }) => void
|
||||||
|
) {
|
||||||
|
return messageQueue.subscribe("installSubscribe", callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function publishSubscribeInstall(messageQueue: MessageQueue, message: { subscribe: Subscribe }) {
|
||||||
|
return messageQueue.publish("installSubscribe", message);
|
||||||
|
}
|
||||||
|
|
||||||
export type ScriptEnableCallbackValue = { uuid: string; enable: boolean };
|
export type ScriptEnableCallbackValue = { uuid: string; enable: boolean };
|
||||||
|
|
||||||
export function subscribeScriptEnable(
|
export function subscribeScriptEnable(
|
||||||
|
@ -9,6 +9,7 @@ import { FileSystemType } from "@Packages/filesystem/factory";
|
|||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import Cache from "@App/app/cache";
|
import Cache from "@App/app/cache";
|
||||||
import CacheKey from "@App/app/cache_key";
|
import CacheKey from "@App/app/cache_key";
|
||||||
|
import { Subscribe } from "@App/app/repo/subscribe";
|
||||||
|
|
||||||
export class ServiceWorkerClient extends Client {
|
export class ServiceWorkerClient extends Client {
|
||||||
constructor(msg: MessageSend) {
|
constructor(msg: MessageSend) {
|
||||||
@ -185,3 +186,25 @@ export class SynchronizeClient extends Client {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class SubscribeClient extends Client {
|
||||||
|
constructor(msg: MessageSend) {
|
||||||
|
super(msg, "serviceWorker/subscribe");
|
||||||
|
}
|
||||||
|
|
||||||
|
install(subscribe: Subscribe) {
|
||||||
|
return this.do("install", { subscribe });
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(url: string) {
|
||||||
|
return this.do("delete", { url });
|
||||||
|
}
|
||||||
|
|
||||||
|
checkUpdate(url: string) {
|
||||||
|
return this.do("checkUpdate", { url });
|
||||||
|
}
|
||||||
|
|
||||||
|
enable(url: string, enable: boolean) {
|
||||||
|
return this.do("enable", { url, enable });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import { ServiceWorkerMessageSend } from "@Packages/message/window_message";
|
|||||||
import { PopupService } from "./popup";
|
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";
|
||||||
|
|
||||||
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
|
export type InstallSource = "user" | "system" | "sync" | "subscribe" | "vscode";
|
||||||
|
|
||||||
@ -49,6 +50,8 @@ export default class ServiceWorkerManager {
|
|||||||
systemConfig
|
systemConfig
|
||||||
);
|
);
|
||||||
synchronize.init();
|
synchronize.init();
|
||||||
|
const subscribe = new SubscribeService(systemConfig, this.api.group("subscribe"), this.mq, script);
|
||||||
|
subscribe.init();
|
||||||
|
|
||||||
// 定时器处理
|
// 定时器处理
|
||||||
chrome.alarms.onAlarm.addListener((alarm) => {
|
chrome.alarms.onAlarm.addListener((alarm) => {
|
||||||
@ -63,6 +66,10 @@ export default class ServiceWorkerManager {
|
|||||||
synchronize.syncOnce(fs);
|
synchronize.syncOnce(fs);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
case "checkSubscribeUpdate":
|
||||||
|
subscribe.checkSubscribeUpdate();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ 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).catch((e) => {
|
this.openInstallPageByUrl(targetUrl, "user").catch((e) => {
|
||||||
logger.error("install script error", Logger.E(e));
|
logger.error("install script error", Logger.E(e));
|
||||||
// 如果打开失败, 则重定向到安装页
|
// 如果打开失败, 则重定向到安装页
|
||||||
chrome.scripting.executeScript({
|
chrome.scripting.executeScript({
|
||||||
@ -135,9 +135,9 @@ export class ScriptService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public openInstallPageByUrl(url: string) {
|
public openInstallPageByUrl(url: string, source: InstallSource) {
|
||||||
const uuid = uuidv4();
|
const uuid = uuidv4();
|
||||||
return fetchScriptInfo(url, "user", false, uuidv4()).then((info) => {
|
return fetchScriptInfo(url, source, false, uuidv4()).then((info) => {
|
||||||
Cache.getInstance().set(CacheKey.scriptInstallInfo(uuid), info);
|
Cache.getInstance().set(CacheKey.scriptInstallInfo(uuid), info);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// 清理缓存
|
// 清理缓存
|
||||||
@ -147,6 +147,19 @@ export class ScriptService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 直接通过url静默安装脚本
|
||||||
|
async installByUrl(url: string, source: InstallSource, subscribeUrl?: string) {
|
||||||
|
const info = await fetchScriptInfo(url, source, false, uuidv4());
|
||||||
|
const prepareScript = await prepareScriptByCode(info.code, url, info.uuid);
|
||||||
|
prepareScript.script.subscribeUrl = subscribeUrl;
|
||||||
|
this.installScript({
|
||||||
|
script: prepareScript.script,
|
||||||
|
code: info.code,
|
||||||
|
upsertBy: source,
|
||||||
|
});
|
||||||
|
return Promise.resolve(prepareScript.script);
|
||||||
|
}
|
||||||
|
|
||||||
// 获取安装信息
|
// 获取安装信息
|
||||||
getInstallInfo(uuid: string) {
|
getInstallInfo(uuid: string) {
|
||||||
return Cache.getInstance().get(CacheKey.scriptInstallInfo(uuid));
|
return Cache.getInstance().get(CacheKey.scriptInstallInfo(uuid));
|
||||||
@ -330,7 +343,7 @@ export class ScriptService {
|
|||||||
}
|
}
|
||||||
const newVersion = metadata.version && metadata.version[0];
|
const newVersion = metadata.version && metadata.version[0];
|
||||||
if (!newVersion) {
|
if (!newVersion) {
|
||||||
logger.error("parse version failed", { version: "" });
|
logger.error("parse version failed", { version: metadata.version });
|
||||||
return Promise.resolve(false);
|
return Promise.resolve(false);
|
||||||
}
|
}
|
||||||
let oldVersion = script.metadata.version && script.metadata.version[0];
|
let oldVersion = script.metadata.version && script.metadata.version[0];
|
||||||
@ -393,16 +406,16 @@ export class ScriptService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkScriptUpdate() {
|
async checkScriptUpdate() {
|
||||||
|
const checkCycle = await this.systemConfig.getCheckScriptUpdateCycle();
|
||||||
|
if (!checkCycle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.scriptDAO.all().then(async (scripts) => {
|
this.scriptDAO.all().then(async (scripts) => {
|
||||||
const checkCycle = await this.systemConfig.getCheckScriptUpdateCycle();
|
const checkDisableScript = await this.systemConfig.getUpdateDisableScript();
|
||||||
if (!checkCycle) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const check = await this.systemConfig.getUpdateDisableScript();
|
|
||||||
scripts.forEach(async (script) => {
|
scripts.forEach(async (script) => {
|
||||||
// 是否检查禁用脚本
|
// 是否检查禁用脚本
|
||||||
if (!check && script.status === SCRIPT_STATUS_DISABLE) {
|
if (!checkDisableScript && script.status === SCRIPT_STATUS_DISABLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 检查是否符合
|
// 检查是否符合
|
||||||
|
280
src/app/service/service_worker/subscribe.ts
Normal file
280
src/app/service/service_worker/subscribe.ts
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
import LoggerCore from "@App/app/logger/core";
|
||||||
|
import Logger from "@App/app/logger/logger";
|
||||||
|
import { ScriptDAO } from "@App/app/repo/scripts";
|
||||||
|
import {
|
||||||
|
Subscribe,
|
||||||
|
SUBSCRIBE_STATUS_DISABLE,
|
||||||
|
SUBSCRIBE_STATUS_ENABLE,
|
||||||
|
SubscribeDAO,
|
||||||
|
SubscribeScript,
|
||||||
|
} from "@App/app/repo/subscribe";
|
||||||
|
import { SystemConfig } from "@App/pkg/config/config";
|
||||||
|
import { MessageQueue } from "@Packages/message/message_queue";
|
||||||
|
import { Group } from "@Packages/message/server";
|
||||||
|
import { InstallSource } from ".";
|
||||||
|
import { publishSubscribeInstall, subscribeSubscribeInstall } from "../queue";
|
||||||
|
import { ScriptService } from "./script";
|
||||||
|
import { checkSilenceUpdate, InfoNotification, ltever } from "@App/pkg/utils/utils";
|
||||||
|
import { fetchScriptInfo, prepareSubscribeByCode, ScriptInfo } from "@App/pkg/utils/script";
|
||||||
|
import Cache from "@App/app/cache";
|
||||||
|
import CacheKey from "@App/app/cache_key";
|
||||||
|
|
||||||
|
export class SubscribeService {
|
||||||
|
logger: Logger;
|
||||||
|
subscribeDAO = new SubscribeDAO();
|
||||||
|
scriptDAO = new ScriptDAO();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private systemConfig: SystemConfig,
|
||||||
|
private group: Group,
|
||||||
|
private mq: MessageQueue,
|
||||||
|
private scriptService: ScriptService
|
||||||
|
) {
|
||||||
|
this.logger = LoggerCore.logger().with({ service: "subscribe" });
|
||||||
|
}
|
||||||
|
|
||||||
|
async install(param: { subscribe: Subscribe }) {
|
||||||
|
const logger = this.logger.with({
|
||||||
|
subscribeUrl: param.subscribe.url,
|
||||||
|
name: param.subscribe.name,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await this.subscribeDAO.save(param.subscribe);
|
||||||
|
logger.info("upsert subscribe success");
|
||||||
|
publishSubscribeInstall(this.mq, {
|
||||||
|
subscribe: param.subscribe,
|
||||||
|
});
|
||||||
|
return Promise.resolve(param.subscribe.url);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("upsert subscribe error", Logger.E(e));
|
||||||
|
return Promise.reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(param: { url: string }) {
|
||||||
|
const logger = this.logger.with({
|
||||||
|
subscribeUrl: param.url,
|
||||||
|
});
|
||||||
|
const subscribe = await this.subscribeDAO.get(param.url);
|
||||||
|
if (!subscribe) {
|
||||||
|
logger.warn("subscribe not found");
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 删除相关脚本
|
||||||
|
const scripts = await this.scriptDAO.find((_, value) => {
|
||||||
|
return value.subscribeUrl === param.url;
|
||||||
|
});
|
||||||
|
scripts.forEach((script) => {
|
||||||
|
this.scriptService.deleteScript(script.uuid);
|
||||||
|
});
|
||||||
|
// 删除订阅
|
||||||
|
await this.subscribeDAO.delete(param.url);
|
||||||
|
logger.info("delete subscribe success");
|
||||||
|
return Promise.resolve(true);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("uninstall subscribe error", Logger.E(e));
|
||||||
|
return Promise.reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新订阅的脚本
|
||||||
|
async upsertScript(subscribe: Subscribe) {
|
||||||
|
const logger = this.logger.with({
|
||||||
|
url: subscribe.url,
|
||||||
|
name: subscribe.name,
|
||||||
|
});
|
||||||
|
// 对比脚本是否有变化
|
||||||
|
const addScript: string[] = [];
|
||||||
|
const removeScript: SubscribeScript[] = [];
|
||||||
|
const scriptUrl = subscribe.metadata.scripturl || [];
|
||||||
|
const scripts = Object.keys(subscribe.scripts);
|
||||||
|
scriptUrl.forEach((url) => {
|
||||||
|
// 不存在于已安装的脚本中, 则添加
|
||||||
|
if (!scripts.includes(url)) {
|
||||||
|
addScript.push(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
scripts.forEach((url) => {
|
||||||
|
// 不存在于订阅的脚本中, 则删除
|
||||||
|
if (!scriptUrl.includes(url)) {
|
||||||
|
removeScript.push(subscribe.scripts[url]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const notification: string[][] = [[], []];
|
||||||
|
const result: Promise<any>[] = [];
|
||||||
|
// 添加脚本
|
||||||
|
addScript.forEach((url) => {
|
||||||
|
result.push(
|
||||||
|
(async () => {
|
||||||
|
const script = await this.scriptService.installByUrl(url, "subscribe", subscribe.url);
|
||||||
|
subscribe.scripts[url] = {
|
||||||
|
url,
|
||||||
|
uuid: script.uuid,
|
||||||
|
};
|
||||||
|
notification[0].push(script.name);
|
||||||
|
return Promise.resolve(true);
|
||||||
|
})().catch((e) => {
|
||||||
|
logger.error("install script failed", Logger.E(e));
|
||||||
|
return Promise.resolve(false);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
// 删除脚本
|
||||||
|
removeScript.forEach((item) => {
|
||||||
|
// 通过uuid查询脚本id
|
||||||
|
result.push(
|
||||||
|
(async () => {
|
||||||
|
const script = await this.scriptDAO.findByUUID(item.uuid);
|
||||||
|
if (script) {
|
||||||
|
notification[1].push(script.name);
|
||||||
|
// 删除脚本
|
||||||
|
this.scriptService.deleteScript(script.uuid);
|
||||||
|
}
|
||||||
|
return Promise.resolve(true);
|
||||||
|
})().catch((e) => {
|
||||||
|
logger.error("delete script failed", Logger.E(e));
|
||||||
|
return Promise.resolve(false);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.allSettled(result);
|
||||||
|
|
||||||
|
await this.subscribeDAO.update(subscribe.url, subscribe);
|
||||||
|
|
||||||
|
InfoNotification("订阅更新", `安装了:${notification[0].join(",")}\n删除了:${notification[1].join("\n")}`);
|
||||||
|
|
||||||
|
logger.info("subscribe update", {
|
||||||
|
install: notification[0],
|
||||||
|
update: notification[1],
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查更新
|
||||||
|
async checkUpdate(url: string, source: InstallSource) {
|
||||||
|
const subscribe = await this.subscribeDAO.get(url);
|
||||||
|
if (!subscribe) {
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
const logger = this.logger.with({
|
||||||
|
url: subscribe.url,
|
||||||
|
name: subscribe.name,
|
||||||
|
});
|
||||||
|
await this.subscribeDAO.update(url, { checktime: new Date().getTime() });
|
||||||
|
try {
|
||||||
|
const info = await fetchScriptInfo(subscribe.url, source, false, subscribe.url);
|
||||||
|
const { metadata } = info;
|
||||||
|
if (!metadata) {
|
||||||
|
logger.error("parse metadata failed");
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
const newVersion = metadata.version && metadata.version[0];
|
||||||
|
if (!newVersion) {
|
||||||
|
logger.error("parse version failed", { version: metadata.version });
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
let oldVersion = subscribe.metadata.version && subscribe.metadata.version[0];
|
||||||
|
if (!oldVersion) {
|
||||||
|
oldVersion = "0.0.0";
|
||||||
|
}
|
||||||
|
// 对比版本大小
|
||||||
|
if (ltever(newVersion, oldVersion, logger)) {
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
// 进行更新
|
||||||
|
this.openUpdatePage(info);
|
||||||
|
return Promise.resolve(true);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("check update failed", Logger.E(e));
|
||||||
|
return Promise.resolve(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async openUpdatePage(info: ScriptInfo) {
|
||||||
|
const logger = this.logger.with({
|
||||||
|
url: info.url,
|
||||||
|
});
|
||||||
|
// 是否静默更新
|
||||||
|
const silenceUpdate = await this.systemConfig.getSilenceUpdateScript();
|
||||||
|
if (silenceUpdate) {
|
||||||
|
try {
|
||||||
|
const newSubscribe = await prepareSubscribeByCode(info.code, info.url);
|
||||||
|
if (checkSilenceUpdate(newSubscribe.oldSubscribe!.metadata, newSubscribe.subscribe.metadata)) {
|
||||||
|
logger.info("silence update subscribe");
|
||||||
|
this.install({
|
||||||
|
subscribe: newSubscribe.subscribe,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("prepare script failed", Logger.E(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cache.getInstance().set(CacheKey.scriptInstallInfo(info.uuid), info);
|
||||||
|
chrome.tabs.create({
|
||||||
|
url: `/src/install.html?uuid=${info.uuid}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkSubscribeUpdate() {
|
||||||
|
const checkCycle = await this.systemConfig.getCheckScriptUpdateCycle();
|
||||||
|
if (!checkCycle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.logger.debug("start check update");
|
||||||
|
const checkDisable = await this.systemConfig.getUpdateDisableScript();
|
||||||
|
const list = await this.subscribeDAO.find((_, value) => {
|
||||||
|
return value.checktime + checkCycle * 1000 < Date.now();
|
||||||
|
});
|
||||||
|
|
||||||
|
list.forEach((subscribe) => {
|
||||||
|
if (!checkDisable && subscribe.status === SUBSCRIBE_STATUS_ENABLE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.checkUpdate(subscribe.url, "system");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
requestCheckUpdate(url: string) {
|
||||||
|
return this.checkUpdate(url, "user");
|
||||||
|
}
|
||||||
|
|
||||||
|
enable(param: { url: string; enable: boolean }) {
|
||||||
|
const logger = this.logger.with({
|
||||||
|
url: param.url,
|
||||||
|
});
|
||||||
|
return this.subscribeDAO
|
||||||
|
.update(param.url, {
|
||||||
|
status: param.enable ? SUBSCRIBE_STATUS_ENABLE : SUBSCRIBE_STATUS_DISABLE,
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
logger.info("enable subscribe success");
|
||||||
|
return Promise.resolve(true);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
logger.error("enable subscribe error", Logger.E(e));
|
||||||
|
return Promise.reject(e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.group.on("install", this.install.bind(this));
|
||||||
|
this.group.on("delete", this.delete.bind(this));
|
||||||
|
this.group.on("checkUpdate", this.requestCheckUpdate.bind(this));
|
||||||
|
this.group.on("enable", this.enable.bind(this));
|
||||||
|
|
||||||
|
subscribeSubscribeInstall(this.mq, (message) => {
|
||||||
|
this.upsertScript(message.subscribe);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 定时检查更新, 每10分钟检查一次
|
||||||
|
chrome.alarms.create("checkSubscribeUpdate", {
|
||||||
|
delayInMinutes: 10,
|
||||||
|
periodInMinutes: 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@ import { i18nDescription, i18nName } from "@App/locales/locales";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { prepareScriptByCode, prepareSubscribeByCode, ScriptInfo } from "@App/pkg/utils/script";
|
import { prepareScriptByCode, prepareSubscribeByCode, ScriptInfo } from "@App/pkg/utils/script";
|
||||||
import { nextTime } from "@App/pkg/utils/utils";
|
import { nextTime } from "@App/pkg/utils/utils";
|
||||||
import { scriptClient } from "../store/features/script";
|
import { scriptClient, subscribeClient } from "../store/features/script";
|
||||||
|
|
||||||
type Permission = { label: string; color?: string; value: string[] }[];
|
type Permission = { label: string; color?: string; value: string[] }[];
|
||||||
|
|
||||||
@ -253,18 +253,18 @@ function App() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (scriptInfo?.userSubscribe) {
|
if (scriptInfo?.userSubscribe) {
|
||||||
// subscribeCtrl
|
subscribeClient
|
||||||
// .upsert(upsertScript as Subscribe)
|
.install(upsertScript as Subscribe)
|
||||||
// .then(() => {
|
.then(() => {
|
||||||
// Message.success(t("subscribe_success")!);
|
Message.success(t("subscribe_success")!);
|
||||||
// setBtnText(t("subscribe_success")!);
|
setBtnText(t("subscribe_success")!);
|
||||||
// setTimeout(() => {
|
setTimeout(() => {
|
||||||
// closeWindow();
|
closeWindow();
|
||||||
// }, 200);
|
}, 500);
|
||||||
// })
|
})
|
||||||
// .catch((e) => {
|
.catch((e) => {
|
||||||
// Message.error(`${t("subscribe_failed")}: ${e}`);
|
Message.error(`${t("subscribe_failed")}: ${e}`);
|
||||||
// });
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scriptClient
|
scriptClient
|
||||||
|
@ -1,47 +1,27 @@
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import Text from "@arco-design/web-react/es/Typography/text";
|
import Text from "@arco-design/web-react/es/Typography/text";
|
||||||
import {
|
import { Button, Card, Input, Message, Popconfirm, Switch, Table, Tag, Tooltip } from "@arco-design/web-react";
|
||||||
Button,
|
import { Subscribe, SUBSCRIBE_STATUS_DISABLE, SUBSCRIBE_STATUS_ENABLE, SubscribeDAO } from "@App/app/repo/subscribe";
|
||||||
Card,
|
|
||||||
Input,
|
|
||||||
Message,
|
|
||||||
Popconfirm,
|
|
||||||
Switch,
|
|
||||||
Table,
|
|
||||||
Tag,
|
|
||||||
Tooltip,
|
|
||||||
} from "@arco-design/web-react";
|
|
||||||
import {
|
|
||||||
Subscribe,
|
|
||||||
SUBSCRIBE_STATUS_DISABLE,
|
|
||||||
SUBSCRIBE_STATUS_ENABLE,
|
|
||||||
SubscribeDAO,
|
|
||||||
} from "@App/app/repo/subscribe";
|
|
||||||
import { ColumnProps } from "@arco-design/web-react/es/Table";
|
import { ColumnProps } from "@arco-design/web-react/es/Table";
|
||||||
import { IconSearch, IconUserAdd } from "@arco-design/web-react/icon";
|
import { IconSearch, IconUserAdd } from "@arco-design/web-react/icon";
|
||||||
import { RefInputType } from "@arco-design/web-react/es/Input/interface";
|
import { RefInputType } from "@arco-design/web-react/es/Input/interface";
|
||||||
import { semTime } from "@App/pkg/utils/utils";
|
import { semTime } from "@App/pkg/utils/utils";
|
||||||
import { RiDeleteBin5Fill } from "react-icons/ri";
|
import { RiDeleteBin5Fill } from "react-icons/ri";
|
||||||
import { useTranslation } from "react-i18next"; // 添加了 react-i18next 的引用
|
import { useTranslation } from "react-i18next"; // 添加了 react-i18next 的引用
|
||||||
|
import { subscribeClient } from "@App/pages/store/features/script";
|
||||||
|
|
||||||
type ListType = Subscribe & { loading?: boolean };
|
type ListType = Subscribe & { loading?: boolean };
|
||||||
|
|
||||||
function SubscribeList() {
|
function SubscribeList() {
|
||||||
const dao = new SubscribeDAO();
|
const dao = new SubscribeDAO();
|
||||||
const subscribeCtrl = IoC.instance(
|
|
||||||
SubscribeController
|
|
||||||
) as SubscribeController;
|
|
||||||
const [list, setList] = useState<ListType[]>([]);
|
const [list, setList] = useState<ListType[]>([]);
|
||||||
const inputRef = useRef<RefInputType>(null);
|
const inputRef = useRef<RefInputType>(null);
|
||||||
const { t } = useTranslation(); // 使用 useTranslation hook
|
const { t } = useTranslation(); // 使用 useTranslation hook
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dao.table
|
dao.all().then((subscribes) => {
|
||||||
.orderBy("id")
|
setList(subscribes);
|
||||||
.toArray()
|
});
|
||||||
.then((subscribes) => {
|
|
||||||
setList(subscribes);
|
|
||||||
});
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const columns: ColumnProps[] = [
|
const columns: ColumnProps[] = [
|
||||||
@ -50,7 +30,13 @@ function SubscribeList() {
|
|||||||
dataIndex: "id",
|
dataIndex: "id",
|
||||||
width: 70,
|
width: 70,
|
||||||
key: "#",
|
key: "#",
|
||||||
sorter: (a, b) => a.id - b.id,
|
sorter: (a: Subscribe, b) => a.createtime - b.createtime,
|
||||||
|
render(col) {
|
||||||
|
if (col < 0) {
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
return col + 1;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("enable"),
|
title: t("enable"),
|
||||||
@ -79,22 +65,18 @@ function SubscribeList() {
|
|||||||
onChange={(checked) => {
|
onChange={(checked) => {
|
||||||
list[index].loading = true;
|
list[index].loading = true;
|
||||||
setList([...list]);
|
setList([...list]);
|
||||||
let p: Promise<any>;
|
subscribeClient
|
||||||
if (checked) {
|
.enable(item.url, checked)
|
||||||
p = subscribeCtrl.enable(item.id).then(() => {
|
.then(() => {
|
||||||
list[index].status = SUBSCRIBE_STATUS_ENABLE;
|
list[index].status = checked ? SUBSCRIBE_STATUS_ENABLE : SUBSCRIBE_STATUS_DISABLE;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
Message.error(err);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
list[index].loading = false;
|
||||||
|
setList([...list]);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
p = subscribeCtrl.disable(item.id).then(() => {
|
|
||||||
list[index].status = SUBSCRIBE_STATUS_DISABLE;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
p.catch((err) => {
|
|
||||||
Message.error(err);
|
|
||||||
}).finally(() => {
|
|
||||||
list[index].loading = false;
|
|
||||||
setList([...list]);
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -169,14 +151,7 @@ function SubscribeList() {
|
|||||||
return <div />;
|
return <div />;
|
||||||
}
|
}
|
||||||
return (item.metadata.connect as string[]).map((val) => {
|
return (item.metadata.connect as string[]).map((val) => {
|
||||||
return (
|
return <img src={`https://${val}/favicon.ico`} alt={val} height={16} width={16} />;
|
||||||
<img
|
|
||||||
src={`https://${val}/favicon.ico`}
|
|
||||||
alt={val}
|
|
||||||
height={16}
|
|
||||||
width={16}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -227,8 +202,8 @@ function SubscribeList() {
|
|||||||
id: "checkupdate",
|
id: "checkupdate",
|
||||||
content: t("checking_for_updates"),
|
content: t("checking_for_updates"),
|
||||||
});
|
});
|
||||||
subscribeCtrl
|
subscribeClient
|
||||||
.checkUpdate(subscribe.id)
|
.checkUpdate(subscribe.url)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res) {
|
if (res) {
|
||||||
Message.warning({
|
Message.warning({
|
||||||
@ -267,10 +242,15 @@ function SubscribeList() {
|
|||||||
title={t("confirm_delete_subscription")}
|
title={t("confirm_delete_subscription")}
|
||||||
icon={<RiDeleteBin5Fill />}
|
icon={<RiDeleteBin5Fill />}
|
||||||
onOk={() => {
|
onOk={() => {
|
||||||
setList(list.filter((val) => val.id !== item.id));
|
subscribeClient
|
||||||
subscribeCtrl.delete(item.id).catch((e) => {
|
.delete(item.url)
|
||||||
Message.error(`${t("delete_failed")}: ${e}`);
|
.then(() => {
|
||||||
});
|
setList(list.filter((val) => val.url !== item.url));
|
||||||
|
Message.success(t("delete_success"));
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
Message.error(`${t("delete_failed")}: ${e}`);
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
|
@ -13,11 +13,13 @@ import {
|
|||||||
PopupClient,
|
PopupClient,
|
||||||
RuntimeClient,
|
RuntimeClient,
|
||||||
ScriptClient,
|
ScriptClient,
|
||||||
|
SubscribeClient,
|
||||||
ValueClient,
|
ValueClient,
|
||||||
} from "@App/app/service/service_worker/client";
|
} from "@App/app/service/service_worker/client";
|
||||||
import { message } from "../global";
|
import { message } from "../global";
|
||||||
|
|
||||||
export const scriptClient = new ScriptClient(message);
|
export const scriptClient = new ScriptClient(message);
|
||||||
|
export const subscribeClient = new SubscribeClient(message);
|
||||||
export const runtimeClient = new RuntimeClient(message);
|
export const runtimeClient = new RuntimeClient(message);
|
||||||
export const popupClient = new PopupClient(message);
|
export const popupClient = new PopupClient(message);
|
||||||
export const permissionClient = new PermissionClient(message);
|
export const permissionClient = new PermissionClient(message);
|
||||||
|
@ -65,7 +65,9 @@ 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);
|
this.storage.set(key, val).then(() => {
|
||||||
|
console.log(chrome.runtime.lastError, val);
|
||||||
|
});
|
||||||
// 发送消息通知更新
|
// 发送消息通知更新
|
||||||
this.mq.publish(SystamConfigChange, {
|
this.mq.publish(SystamConfigChange, {
|
||||||
key,
|
key,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user