Skip to content

Commit 00cef05

Browse files
committed
code update
1 parent 05ce96e commit 00cef05

11 files changed

Lines changed: 106 additions & 1 deletion

File tree

packages/filesystem/googledrive/googledrive.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,16 @@ describe("GoogleDriveFileSystem", () => {
165165
});
166166
});
167167

168+
it("findFileInDirectory should reject duplicate file names", async () => {
169+
const fs = new GoogleDriveFileSystem("/", "token");
170+
vi.spyOn(fs, "findFilesInDirectory").mockResolvedValue([{ id: "file-1" }, { id: "file-2" }]);
171+
172+
await expect(fs.findFileInDirectory("file.txt", "parent-id")).rejects.toMatchObject({
173+
provider: "googledrive",
174+
conflict: true,
175+
});
176+
});
177+
168178
it("writer should create createOnly files with a generated Google Drive id", async () => {
169179
const fs = new GoogleDriveFileSystem("/", "token");
170180
const writer = await fs.create("file.txt", { createOnly: true });

packages/filesystem/googledrive/googledrive.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,15 @@ export default class GoogleDriveFileSystem implements FileSystem {
362362
// 辅助方法:在指定目录中查找文件
363363
async findFileInDirectory(fileName: string, parentId: string): Promise<string | null> {
364364
const files = await this.findFilesInDirectory(fileName, parentId);
365+
if (files.length > 1) {
366+
throw new FileSystemError({
367+
provider: "googledrive",
368+
message: `Duplicate Google Drive files found: ${fileName}`,
369+
status: 409,
370+
code: "nameAlreadyExists",
371+
conflict: true,
372+
});
373+
}
365374
return files[0]?.id || null;
366375
}
367376

src/app/service/service_worker/synchronize.test.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,46 @@ console.log("ok");`
866866
});
867867
});
868868

869+
it("retries digest list before falling back to pushed md5", async () => {
870+
const fs = createFs({
871+
list: vi
872+
.fn()
873+
.mockResolvedValueOnce([])
874+
.mockResolvedValueOnce([
875+
{
876+
name: "push-uuid.user.js",
877+
path: "push-uuid.user.js",
878+
size: 1,
879+
digest: "etag-user-js",
880+
createtime: 1,
881+
updatetime: 1,
882+
},
883+
]),
884+
});
885+
const service = new SynchronizeService(
886+
{} as any,
887+
{} as any,
888+
{} as any,
889+
{} as any,
890+
{} as any,
891+
{} as any,
892+
{} as any,
893+
{
894+
scriptCodeDAO: {},
895+
all: vi.fn().mockResolvedValue([]),
896+
} as any
897+
);
898+
899+
await service.updateFileDigest(fs, {
900+
"push-uuid.user.js": "local-md5",
901+
});
902+
903+
expect(fs.list).toHaveBeenCalledTimes(2);
904+
await expect((service as any).storage.get("file_digest")).resolves.toEqual({
905+
"push-uuid.user.js": "etag-user-js",
906+
});
907+
});
908+
869909
it("skips status and digest update when a push hits remote conflict", async () => {
870910
const conflict = new FileSystemError({
871911
provider: "webdav",
@@ -903,11 +943,18 @@ console.log("ok");`
903943
);
904944
vi.spyOn(service, "pushScript").mockRejectedValue(conflict);
905945
const updateDigestSpy = vi.spyOn(service, "updateFileDigest");
946+
const notificationSpy = vi.spyOn(chrome.notifications, "create").mockReturnValue("notification-id" as any);
906947

907948
await service.syncOnce(syncConfig, fs);
908949

909950
expect(updateDigestSpy).not.toHaveBeenCalled();
910951
expect(fs.create).not.toHaveBeenCalledWith("scriptcat-sync.json", expect.anything());
952+
expect(notificationSpy).toHaveBeenCalledWith(
953+
expect.objectContaining({
954+
title: "Script Sync Failed",
955+
message: expect.stringContaining("remote conflict"),
956+
})
957+
);
911958
});
912959

913960
it("skips status and digest update when any push task fails", async () => {
@@ -942,11 +989,18 @@ console.log("ok");`
942989
);
943990
vi.spyOn(service, "pushScript").mockRejectedValue(error);
944991
const updateDigestSpy = vi.spyOn(service, "updateFileDigest");
992+
const notificationSpy = vi.spyOn(chrome.notifications, "create").mockReturnValue("notification-id" as any);
945993

946994
await service.syncOnce(syncConfig, fs);
947995

948996
expect(updateDigestSpy).not.toHaveBeenCalled();
949997
expect(fs.create).not.toHaveBeenCalledWith("scriptcat-sync.json", expect.anything());
998+
expect(notificationSpy).toHaveBeenCalledWith(
999+
expect.objectContaining({
1000+
title: "Script Sync Failed",
1001+
message: expect.stringContaining("cloud sync changes failed"),
1002+
})
1003+
);
9501004
});
9511005

9521006
it("scriptInstall enters cloud_sync queue and updates digest after push", async () => {

src/app/service/service_worker/synchronize.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,11 @@ export class SynchronizeService {
505505
conflict: hasConflict,
506506
failed: rejected.length,
507507
});
508+
const title = i18n.t("notification.script_sync_failed");
509+
const message = hasConflict
510+
? i18n.t("notification.script_sync_conflict_desc")
511+
: i18n.t("notification.script_sync_failed_desc");
512+
InfoNotification(title, message);
508513
return;
509514
}
510515
// 同步状态
@@ -577,7 +582,13 @@ export class SynchronizeService {
577582
}
578583

579584
async updateFileDigest(fs: FileSystem, knownFileDigestMap: FileDigestMap = {}) {
580-
const newList = await fs.list();
585+
let newList = await fs.list();
586+
if (Object.keys(knownFileDigestMap).some((name) => !newList.some((file) => file.name === name))) {
587+
const retryList = await fs.list();
588+
if (Array.isArray(retryList)) {
589+
newList = retryList;
590+
}
591+
}
581592
const newFileDigestMap: FileDigestMap = {};
582593
for (const file of newList) {
583594
newFileDigestMap[file.name] = file.digest;

src/locales/de-DE/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@
569569
"notification": {
570570
"script_sync_delete": "Skript-Löschsynchronisation",
571571
"script_sync_delete_desc": "Skript {{scriptName}} wurde gelöscht",
572+
"script_sync_failed": "Skriptsynchronisierung fehlgeschlagen",
573+
"script_sync_failed_desc": "Einige Cloud-Synchronisierungsänderungen sind fehlgeschlagen. Der lokale Synchronisierungsstatus wurde nicht aktualisiert; bitte prüfen Sie die Protokolle und synchronisieren Sie erneut.",
574+
"script_sync_conflict_desc": "Die Cloud-Synchronisierung hat einen Remote-Konflikt erkannt. Der lokale Synchronisierungsstatus wurde nicht aktualisiert; bitte prüfen Sie Änderungen auf anderen Geräten und synchronisieren Sie erneut.",
572575
"subscribe_update": "Abonnement {{subscribeName}} wurde aktualisiert",
573576
"subscribe_update_desc": "Neue Skripte: {{newScripts}}\nGelöschte Skripte: {{deletedScripts}}"
574577
},

src/locales/en-US/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@
569569
"notification": {
570570
"script_sync_delete": "Script Sync Delete",
571571
"script_sync_delete_desc": "Script {{scriptName}} has been deleted",
572+
"script_sync_failed": "Script Sync Failed",
573+
"script_sync_failed_desc": "Some cloud sync changes failed. Local sync state was not updated; please check the logs and try syncing again.",
574+
"script_sync_conflict_desc": "Cloud sync detected a remote conflict. Local sync state was not updated; please review changes on other devices and sync again.",
572575
"subscribe_update": "Subscribe {{subscribeName}} has been updated",
573576
"subscribe_update_desc": "New scripts: {{newScripts}}\nDeleted scripts: {{deletedScripts}}"
574577
},

src/locales/ja-JP/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@
569569
"notification": {
570570
"script_sync_delete": "スクリプト同期削除",
571571
"script_sync_delete_desc": "スクリプト {{scriptName}} が削除されました",
572+
"script_sync_failed": "スクリプト同期に失敗しました",
573+
"script_sync_failed_desc": "一部のクラウド同期の変更に失敗しました。ローカルの同期状態は更新されていません。ログを確認してから再同期してください。",
574+
"script_sync_conflict_desc": "クラウド同期でリモートの競合が検出されました。ローカルの同期状態は更新されていません。他のデバイスでの変更を確認してから再同期してください。",
572575
"subscribe_update": "サブスクリプション {{subscribeName}} が更新されました",
573576
"subscribe_update_desc": "新しいスクリプト: {{newScripts}}\n削除されたスクリプト: {{deletedScripts}}"
574577
},

src/locales/ru-RU/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@
569569
"notification": {
570570
"script_sync_delete": "Синхронизация удаления скрипта",
571571
"script_sync_delete_desc": "Скрипт {{scriptName}} был удален",
572+
"script_sync_failed": "Не удалось синхронизировать скрипт",
573+
"script_sync_failed_desc": "Не удалось применить часть изменений облачной синхронизации. Локальное состояние синхронизации не обновлено; проверьте журналы и повторите синхронизацию.",
574+
"script_sync_conflict_desc": "Облачная синхронизация обнаружила конфликт на удаленной стороне. Локальное состояние синхронизации не обновлено; проверьте изменения на других устройствах и повторите синхронизацию.",
572575
"subscribe_update": "Подписка {{subscribeName}} была обновлена",
573576
"subscribe_update_desc": "Новые скрипты: {{newScripts}}\nУдаленные скрипты: {{deletedScripts}}"
574577
},

src/locales/vi-VN/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@
569569
"notification": {
570570
"script_sync_delete": "Đồng bộ xóa script",
571571
"script_sync_delete_desc": "Script {{scriptName}} đã bị xóa",
572+
"script_sync_failed": "Đồng bộ script thất bại",
573+
"script_sync_failed_desc": "Một số thay đổi đồng bộ đám mây thất bại. Trạng thái đồng bộ cục bộ chưa được cập nhật; vui lòng kiểm tra nhật ký rồi đồng bộ lại.",
574+
"script_sync_conflict_desc": "Đồng bộ đám mây phát hiện xung đột từ xa. Trạng thái đồng bộ cục bộ chưa được cập nhật; vui lòng kiểm tra thay đổi trên các thiết bị khác rồi đồng bộ lại.",
572575
"subscribe_update": "Đăng ký {{subscribeName}} đã được cập nhật",
573576
"subscribe_update_desc": "Script mới: {{newScripts}}\nScript đã xóa: {{deletedScripts}}"
574577
},

src/locales/zh-CN/translation.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@
569569
"notification": {
570570
"script_sync_delete": "脚本删除同步",
571571
"script_sync_delete_desc": "脚本 {{scriptName}} 已被删除",
572+
"script_sync_failed": "脚本同步失败",
573+
"script_sync_failed_desc": "部分云同步变更失败,本地同步状态未更新,请检查日志后重新同步。",
574+
"script_sync_conflict_desc": "云同步检测到远端冲突,本地同步状态未更新,请检查其他设备上的变更后重新同步。",
572575
"subscribe_update": "订阅 {{subscribeName}} 已更新",
573576
"subscribe_update_desc": "新增脚本:{{newScripts}}\n删除脚本:{{deletedScripts}}"
574577
},

0 commit comments

Comments
 (0)