Skip to content

Commit 021e6db

Browse files
committed
🐛 修复同步删除问题 #143
1 parent 43ee0de commit 021e6db

File tree

6 files changed

+73
-13
lines changed

6 files changed

+73
-13
lines changed

src/app/service/synchronize/manager.ts

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
import ChromeStorage from "@App/pkg/config/chrome_storage";
1616
import { CloudSyncConfig, SystemConfig } from "@App/pkg/config/config";
1717
import { prepareScriptByCode } from "@App/pkg/utils/script";
18-
import { InfoNotification } from "@App/pkg/utils/utils";
18+
import { errorMsg, InfoNotification } from "@App/pkg/utils/utils";
1919
import FileSystemFactory from "@Pkg/filesystem/factory";
2020
import FileSystem, { File } from "@Pkg/filesystem/filesystem";
2121
import Manager from "../manager";
@@ -36,6 +36,7 @@ export type SyncMeta = {
3636
origin?: string; // 脚本来源
3737
downloadUrl?: string;
3838
checkUpdateUrl?: string;
39+
isDeleted?: boolean;
3940
};
4041

4142
// 同步控件
@@ -76,7 +77,7 @@ export default class SynchronizeManager extends Manager {
7677
this.valueManager = valueManager;
7778
this.resourceManager = resourceManager;
7879
this.scriptManager = scriptManager;
79-
this.storage = new ChromeStorage("sync", chrome.storage.local);
80+
this.storage = new ChromeStorage("sync", false);
8081
this.logger = LoggerCore.getLogger({ component: "SynchronizeManager" });
8182
}
8283

@@ -119,7 +120,7 @@ export default class SynchronizeManager extends Manager {
119120
logger.error("create filesystem error", Logger.E(e), {
120121
type: config.filesystem,
121122
});
122-
InfoNotification("同步系统连接失败", e);
123+
InfoNotification("同步系统连接失败", errorMsg(e));
123124
if (autoDisable) {
124125
this.systemConfig.cloudSync = {
125126
...this.systemConfig.cloudSync,
@@ -154,7 +155,7 @@ export default class SynchronizeManager extends Manager {
154155
try {
155156
await this.syncOnce(fs);
156157
} catch (e: any) {
157-
InfoNotification("同步失败,请检查同步配置", e);
158+
InfoNotification("同步失败,请检查同步配置", errorMsg(e));
158159
}
159160
}, 60 * 60 * 1000);
160161
freeFn.push(() => {
@@ -164,7 +165,7 @@ export default class SynchronizeManager extends Manager {
164165
try {
165166
await this.syncOnce(fs);
166167
} catch (e: any) {
167-
InfoNotification("同步失败,请检查同步配置", e);
168+
InfoNotification("同步失败,请检查同步配置", errorMsg(e));
168169
}
169170
return Promise.resolve(() => {
170171
logger.info("stop cloud sync");
@@ -176,7 +177,7 @@ export default class SynchronizeManager extends Manager {
176177
// 同步一次
177178
async syncOnce(fs: FileSystem): Promise<void> {
178179
this.logger.info("start sync once");
179-
// 首次同步
180+
// 获取文件列表
180181
const list = await fs.list();
181182
// 根据文件名生成一个map
182183
const uuidMap = new Map<
@@ -223,8 +224,35 @@ export default class SynchronizeManager extends Manager {
223224
const result: Promise<void>[] = [];
224225
uuidMap.forEach((file, uuid) => {
225226
const script = scriptMap.get(uuid);
226-
// 获取脚本数据
227227
if (script) {
228+
// 脚本存在但是文件不存在,则读取.meta.json内容判断是否需要删除脚本
229+
if (!file.script) {
230+
result.push(
231+
new Promise((resolve) => {
232+
const handler = async () => {
233+
// 读取meta文件
234+
const meta = await fs.open(file.meta!);
235+
const metaJson = (await meta.read("string")) as string;
236+
const metaObj = JSON.parse(metaJson) as SyncMeta;
237+
if (metaObj.isDeleted) {
238+
if (script) {
239+
this.scriptManager.event.deleteHandler(script.id);
240+
InfoNotification(
241+
"脚本删除同步",
242+
`脚本${script.name}已被删除`
243+
);
244+
}
245+
} else {
246+
// 否则认为是一个无效的.meta文件,进行删除
247+
await fs.delete(file.meta!.path);
248+
}
249+
resolve();
250+
};
251+
handler();
252+
})
253+
);
254+
return;
255+
}
228256
// 过滤掉无变动的文件
229257
if (fileDigestMap[file.script!.name] === file.script!.digest) {
230258
// 删除了之后,剩下的就是需要上传的脚本了
@@ -243,8 +271,10 @@ export default class SynchronizeManager extends Manager {
243271
scriptMap.delete(uuid);
244272
return;
245273
}
246-
// 如果脚本不存在,则安装脚本
247-
result.push(this.pullScript(fs, file as SyncFiles));
274+
// 如果脚本不存在,且文件存在,则安装脚本
275+
if (file.script) {
276+
result.push(this.pullScript(fs, file as SyncFiles));
277+
}
248278
});
249279
// 上传剩下的脚本
250280
scriptMap.forEach((script) => {
@@ -278,7 +308,17 @@ export default class SynchronizeManager extends Manager {
278308
});
279309
try {
280310
await fs.delete(filename);
281-
await fs.delete(`${script.uuid}.meta.json`);
311+
// 留下一个.meta.json删除标记
312+
const meta = await fs.create(`${script.uuid}.meta.json`);
313+
await meta.write(
314+
JSON.stringify(<SyncMeta>{
315+
uuid: script.uuid,
316+
origin: script.origin,
317+
downloadUrl: script.downloadUrl,
318+
checkUpdateUrl: script.checkUpdateUrl,
319+
isDeleted: true,
320+
})
321+
);
282322
logger.info("delete success");
283323
} catch (e) {
284324
logger.error("delete file error", Logger.E(e));

src/pkg/config/chrome_storage.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ export default class ChromeStorage {
33

44
private storage: chrome.storage.StorageArea;
55

6-
constructor(prefix: string, storage: chrome.storage.StorageArea) {
6+
constructor(prefix: string, sync: boolean) {
77
this.prefix = `${prefix}_`;
8-
this.storage = storage;
8+
this.storage = sync ? chrome.storage.sync : chrome.storage.local;
99
}
1010

1111
public buildKey(key: string): string {

src/pkg/config/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class SystemConfig {
2424

2525
public cache = new Map<string, any>();
2626

27-
public storage = new ChromeStorage("system", chrome.storage.sync);
27+
public storage = new ChromeStorage("system", true);
2828

2929
public message?: MessageCenter;
3030

src/pkg/utils/utils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,3 +293,16 @@ export function openInCurrentTab(url: string) {
293293
}
294294
);
295295
}
296+
297+
export function errorMsg(e: any): string {
298+
if (typeof e === "string") {
299+
return e;
300+
}
301+
if (e instanceof Error) {
302+
return e.message;
303+
}
304+
if (typeof e === "object") {
305+
return JSON.stringify(e);
306+
}
307+
return "";
308+
}

src/runtime/background/runtime.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ export default class Runtime extends Manager {
138138

139139
this.scriptDAO.table.toArray((items) => {
140140
items.forEach((item) => {
141+
// 容错处理
142+
if (!item) {
143+
this.logger.error("script is null");
144+
return;
145+
}
141146
// 加载所有的脚本
142147
if (item.status === SCRIPT_STATUS_ENABLE) {
143148
this.enable(item);

src/types/main.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ declare let sandbox: Window;
22

33
declare let ScriptFlag: string;
44

5+
declare let browser: chrome;
6+
57
declare let cloneInto: ((detail: any, view: any) => any) | undefined;
68

79
declare module "@App/types/scriptcat.d.ts";

0 commit comments

Comments
 (0)