Skip to content

Commit a4e4216

Browse files
committed
Toast notifications, and async perfomance improvments where applicable
1 parent c686e77 commit a4e4216

5 files changed

Lines changed: 316 additions & 213 deletions

File tree

src/archiveFsCommands.ts

Lines changed: 86 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -591,32 +591,41 @@ export function registerArchiveFileCommands(context: vscode.ExtensionContext): v
591591
return;
592592
}
593593
try {
594-
const backups = await createBackups(items);
595-
await parallelMap(items, async (entry) => {
596-
const exists = await vscode.workspace.fs.stat(entry.resourceUri).then(
597-
() => true,
598-
() => false,
599-
);
600-
if (!exists) {
601-
return;
602-
}
603-
const stat = await vscode.workspace.fs.stat(entry.resourceUri);
604-
const isDirectory = stat.type === vscode.FileType.Directory && !isArchiveFile(entry.resourceUri.fsPath);
605-
await vscode.workspace.fs.delete(entry.resourceUri, {
606-
recursive: isDirectory,
607-
useTrash: false,
608-
});
609-
});
610-
historyManager.push({
611-
description: `Delete ${label}`,
612-
undo: async () => {
613-
await restoreBackups(backups);
614-
},
615-
redo: async () => {
616-
await deleteBackups(backups);
594+
await vscode.window.withProgress(
595+
{
596+
location: vscode.ProgressLocation.Notification,
597+
title: `Deleting ${label}...`,
598+
cancellable: false,
617599
},
618-
});
619-
refreshArchives();
600+
async () => {
601+
const backups = await createBackups(items);
602+
await parallelMap(items, async (entry) => {
603+
const exists = await vscode.workspace.fs.stat(entry.resourceUri).then(
604+
() => true,
605+
() => false,
606+
);
607+
if (!exists) {
608+
return;
609+
}
610+
const stat = await vscode.workspace.fs.stat(entry.resourceUri);
611+
const isDirectory = stat.type === vscode.FileType.Directory && !isArchiveFile(entry.resourceUri.fsPath);
612+
await vscode.workspace.fs.delete(entry.resourceUri, {
613+
recursive: isDirectory,
614+
useTrash: false,
615+
});
616+
});
617+
historyManager.push({
618+
description: `Delete ${label}`,
619+
undo: async () => {
620+
await restoreBackups(backups);
621+
},
622+
redo: async () => {
623+
await deleteBackups(backups);
624+
},
625+
});
626+
refreshArchives();
627+
}
628+
);
620629
} catch (error) {
621630
const message = error instanceof Error ? error.message : String(error);
622631
void vscode.window.showErrorMessage(`Delete failed: ${message}`);
@@ -765,6 +774,8 @@ export function registerArchiveFileCommands(context: vscode.ExtensionContext): v
765774
validItems.map((entry) => ({ uri: entry.resourceUri.toString(), move: false })),
766775
);
767776
await vscode.commands.executeCommand('setContext', 'totk-editor.archiveClipboardNotEmpty', true);
777+
const label = validItems.length === 1 ? path.basename(validItems[0]!.resourceUri.fsPath) : `${validItems.length} items`;
778+
void vscode.window.showInformationMessage(`Copied ${label} to clipboard`);
768779
}),
769780
);
770781

@@ -785,6 +796,8 @@ export function registerArchiveFileCommands(context: vscode.ExtensionContext): v
785796
mutableItems.map((entry) => ({ uri: entry.resourceUri.toString(), move: true })),
786797
);
787798
await vscode.commands.executeCommand('setContext', 'totk-editor.archiveClipboardNotEmpty', true);
799+
const label = mutableItems.length === 1 ? path.basename(mutableItems[0]!.resourceUri.fsPath) : `${mutableItems.length} items`;
800+
void vscode.window.showInformationMessage(`Cut ${label} to clipboard`);
788801
}),
789802
);
790803

@@ -834,46 +847,57 @@ export function registerArchiveFileCommands(context: vscode.ExtensionContext): v
834847
} as ArchiveTreeItem;
835848
});
836849
const isMove = clipboard[0]!.move;
850+
const label = sources.length === 1 ? sources[0]!.entryName : `${sources.length} items`;
851+
const progressTitle = isMove ? `Moving ${label}...` : `Copying ${label}...`;
837852
try {
838-
if (isMove) {
839-
const targets = await copyEntries(sources, folderUri, true);
840-
const moves = sources.map((source, index) => ({
841-
src: source.resourceUri,
842-
dest: targets[index]!,
843-
}));
844-
historyManager.push({
845-
description: `Move ${sources.length === 1 ? sources[0]!.entryName : `${sources.length} items`}`,
846-
undo: async () => {
847-
await parallelMap(moves, async (move) => {
848-
await moveEntry(move.dest, move.src);
853+
await vscode.window.withProgress(
854+
{
855+
location: vscode.ProgressLocation.Notification,
856+
title: progressTitle,
857+
cancellable: false,
858+
},
859+
async () => {
860+
if (isMove) {
861+
const targets = await copyEntries(sources, folderUri!, true);
862+
const moves = sources.map((source, index) => ({
863+
src: source.resourceUri,
864+
dest: targets[index]!,
865+
}));
866+
historyManager.push({
867+
description: `Move ${sources.length === 1 ? sources[0]!.entryName : `${sources.length} items`}`,
868+
undo: async () => {
869+
await parallelMap(moves, async (move) => {
870+
await moveEntry(move.dest, move.src);
871+
});
872+
},
873+
redo: async () => {
874+
await parallelMap(moves, async (move) => {
875+
await moveEntry(move.src, move.dest);
876+
});
877+
},
849878
});
850-
},
851-
redo: async () => {
852-
await parallelMap(moves, async (move) => {
853-
await moveEntry(move.src, move.dest);
879+
await context.workspaceState.update(CLIPBOARD_KEY, []);
880+
await vscode.commands.executeCommand('setContext', 'totk-editor.archiveClipboardNotEmpty', false);
881+
} else {
882+
const targets = await copyEntries(sources, folderUri!, false);
883+
const treeTargets = targets.map((target) => ({
884+
uri: target,
885+
resourceUri: target,
886+
entryName: path.basename(target.fsPath),
887+
} as ArchiveTreeItem));
888+
const backups = await createBackups(treeTargets);
889+
historyManager.push({
890+
description: `Copy ${sources.length === 1 ? sources[0]!.entryName : `${sources.length} items`}`,
891+
undo: async () => {
892+
await deleteBackups(backups);
893+
},
894+
redo: async () => {
895+
await restoreBackups(backups);
896+
},
854897
});
855-
},
856-
});
857-
await context.workspaceState.update(CLIPBOARD_KEY, []);
858-
await vscode.commands.executeCommand('setContext', 'totk-editor.archiveClipboardNotEmpty', false);
859-
} else {
860-
const targets = await copyEntries(sources, folderUri, false);
861-
const treeTargets = targets.map((target) => ({
862-
uri: target,
863-
resourceUri: target,
864-
entryName: path.basename(target.fsPath),
865-
} as ArchiveTreeItem));
866-
const backups = await createBackups(treeTargets);
867-
historyManager.push({
868-
description: `Copy ${sources.length === 1 ? sources[0]!.entryName : `${sources.length} items`}`,
869-
undo: async () => {
870-
await deleteBackups(backups);
871-
},
872-
redo: async () => {
873-
await restoreBackups(backups);
874-
},
875-
});
876-
}
898+
}
899+
}
900+
);
877901
refreshArchives();
878902
} catch (error) {
879903
const message = error instanceof Error ? error.message : String(error);

src/canonicalSavePropagation.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,21 +295,21 @@ export async function propagateCanonicalSave(
295295

296296
let propagated = 0;
297297
let copiedArchives = 0;
298-
for (const match of mergedMatches.values()) {
298+
const tasks = Array.from(mergedMatches.values()).map(async (match) => {
299299
const dumpArchivePath = path.join(options.romfsPath, ...splitRel(match.archiveRelPath));
300300
const projectArchivePath = path.join(projectRomfsRoot, ...splitRel(match.archiveRelPath));
301301
if (
302302
pathContainsBlacklistedArchiveType(match.canonicalPath, options.archiveTypeBlacklist) ||
303303
pathContainsBlacklistedArchiveType(match.archiveRelPath, options.archiveTypeBlacklist)
304304
) {
305-
continue;
305+
return { propagated: false, copied: false };
306306
}
307307
if (pathMatchesBlacklistedFileSuffix(match.canonicalPath, mergedFileExtensionBlacklist)) {
308-
continue;
308+
return { propagated: false, copied: false };
309309
}
310310

311311
if (pathsEqual(projectArchivePath, primaryArchive)) {
312-
continue;
312+
return { propagated: false, copied: false };
313313
}
314314

315315
const prepareResult = await ensureArchiveInProject(
@@ -318,10 +318,7 @@ export async function propagateCanonicalSave(
318318
options.output,
319319
);
320320
if (!prepareResult.ready) {
321-
continue;
322-
}
323-
if (prepareResult.copied) {
324-
copiedArchives++;
321+
return { propagated: false, copied: false };
325322
}
326323

327324
try {
@@ -342,12 +339,23 @@ export async function propagateCanonicalSave(
342339
options.bridgeEnv,
343340
);
344341
}
345-
propagated++;
342+
return { propagated: true, copied: prepareResult.copied };
346343
} catch (error) {
347344
const message = error instanceof Error ? error.message : String(error);
348345
options.output.appendLine(
349346
`[canonical-save] Failed to propagate to ${projectArchivePath}: ${message}`,
350347
);
348+
return { propagated: false, copied: prepareResult.copied };
349+
}
350+
});
351+
352+
const results = await Promise.all(tasks);
353+
for (const res of results) {
354+
if (res.propagated) {
355+
propagated++;
356+
}
357+
if (res.copied) {
358+
copiedArchives++;
351359
}
352360
}
353361

0 commit comments

Comments
 (0)