Skip to content

Commit 41f51ba

Browse files
NicolasSchindlerchrjorgensen
authored andcommitted
Add IFS shortcut removal confirmation and directory existence check
Signed-off-by: Nicolas Schindler <schindler.nicolas@gmx.de>
1 parent fa30e33 commit 41f51ba

8 files changed

Lines changed: 118 additions & 72 deletions

File tree

l10n/bundle.l10n.da.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@
101101
"Deleting {0} element(s)...": "Sletning af {0} element(er)...",
102102
"Deletion canceled.": "Sletning afbrudt.",
103103
"directory": "mappe",
104+
"Directory does not exist.": "Directory does not exist.",
104105
"Directory of the file on the remote system": "Katalog over filen på fjernsystemet",
106+
"Do you also want to remove the IFS shortcut to the folder {0}?": "Do you also want to remove the IFS shortcut to the folder {0}?",
107+
"Do you also want to remove the {0} IFS shortcuts to the folders?": "Do you also want to remove the {0} IFS shortcuts to the folders?",
105108
"Do you want to copy or move the selection to {0}?": "Vil du kopiere eller flytte det valgte til {0}?",
106109
"Download certificate": "Hent certifikat",
107110
"Download complete": "Hentning gennemført.",

l10n/bundle.l10n.de.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@
101101
"Deleting {0} element(s)...": "{0} Element(e) werden gelöscht...",
102102
"Deletion canceled.": "Löschung abgebrochen.",
103103
"directory": "Verzeichnis",
104+
"Directory does not exist.": "Verzeichnis existiert nicht.",
104105
"Directory of the file on the remote system": "Verzeichnis der Datei auf dem Remote-System",
106+
"Do you also want to remove the IFS shortcut to the folder {0}?": "Möchten Sie auch die IFS-Verknüpfung zum Ordner {0} entfernen?",
107+
"Do you also want to remove the {0} IFS shortcuts to the folders?": "Möchten Sie auch die {0} IFS-Verknüpfungen zu den Ordnern entfernen?",
105108
"Do you want to copy or move the selection to {0}?": "Möchten Sie die Auswahl nach {0} kopieren oder verschieben?",
106109
"Download certificate": "Zertifikat herunterladen",
107110
"Download complete": "Herunterladen abgeschlossen",

l10n/bundle.l10n.fr.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@
101101
"Deleting {0} element(s)...": "Suppression de {0} élément(s)...",
102102
"Deletion canceled.": "Suppression annulée.",
103103
"directory": "Répertoire",
104+
"Directory does not exist.": "Directory does not exist.",
104105
"Directory of the file on the remote system": "Répertoire du fichier sur le système distant",
106+
"Do you also want to remove the IFS shortcut to the folder {0}?": "Do you also want to remove the IFS shortcut to the folders {0}?",
107+
"Do you also want to remove the {0} IFS shortcuts to the folders?": "Do you also want to remove the {0} IFS shortcuts to the folders?",
105108
"Do you want to copy or move the selection to {0}?": "Voulez-vous déplacer ou copier la sélection vers {0}?",
106109
"Do you want to reconnect to {0} and open {1}?": "Voulez-vous vous reconnecter et ouvrir {0}?",
107110
"Download certificate": "Télécharger le certificat",

l10n/bundle.l10n.it.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,10 @@
104104
"Deleting {0} element(s)...": "Cancellazione {0} elementi in corso...",
105105
"Deletion canceled.": "Cancellazione annullata.",
106106
"directory": "directory",
107+
"Directory does not exist.": "Directory does not exist.",
107108
"Directory of the file on the remote system": "Directory del file sul sistema remoto",
109+
"Do you also want to remove the IFS shortcut to the folder {0}?": "Do you also want to remove the IFS shortcut to the folders {0}?",
110+
"Do you also want to remove the {0} IFS shortcuts to the folders?": "Do you also want to remove the {0} IFS shortcuts to the folders?",
108111
"Do you want to copy or move the selection to {0}?": "Vuoi copiare o spostare gli elementi selezioni in {0}?",
109112
"Do you want to reconnect to {0} and open {1}?": "Vuoi riconnetterti a {0} e aprire {1}?",
110113
"Download certificate": "Scarica certificato",

l10n/bundle.l10n.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@
101101
"Deleting {0} element(s)...": "Deleting {0} element(s)...",
102102
"Deletion canceled.": "Deletion canceled.",
103103
"directory": "directory",
104+
"Directory does not exist.": "Directory does not exist.",
104105
"Directory of the file on the remote system": "Directory of the file on the remote system",
106+
"Do you also want to remove the IFS shortcut to the folder {0}?": "Do you also want to remove the IFS shortcut to the folders {0}?",
107+
"Do you also want to remove the {0} IFS shortcuts to the folders?": "Do you also want to remove the {0} IFS shortcuts to the folders?",
105108
"Do you want to copy or move the selection to {0}?": "Do you want to copy or move the selection to {0}?",
106109
"Do you want to reconnect to {0} and open {1}?": "Do you want to reconnect to {0} and open {1}?",
107110
"Download certificate": "Download certificate",

l10n/bundle.l10n.no.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@
101101
"Deleting {0} element(s)...": "Sletting av {0} element(er)...",
102102
"Deletion canceled.": "Sletting avbrutt.",
103103
"directory": "mappe",
104+
"Directory does not exist.": "Directory does not exist.",
104105
"Directory of the file on the remote system": "Katalog over filen på fjernsystemet",
106+
"Do you also want to remove the IFS shortcut to the folder {0}?": "Do you also want to remove the IFS shortcut to the folders {0}?",
107+
"Do you also want to remove the {0} IFS shortcuts to the folders?": "Do you also want to remove the {0} IFS shortcuts to the folders?",
105108
"Do you want to copy or move the selection to {0}?": "Vil du kopiere eller flytte det valgte til {0}?",
106109
"Download certificate": "Hent sertifikat",
107110
"Download complete": "Hentning gjennomført.",

l10n/bundle.l10n.pl.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@
101101
"Deleting {0} element(s)...": "Usuwanie elementów: {0}...",
102102
"Deletion canceled.": "Usuwanie anulowane.",
103103
"directory": "katalog",
104+
"Directory does not exist.": "Directory does not exist.",
104105
"Directory of the file on the remote system": "Katalog pliku w systemie zdalnym",
106+
"Do you also want to remove the IFS shortcut to the folder {0}?": "Do you also want to remove the IFS shortcut to the folders {0}?",
107+
"Do you also want to remove the {0} IFS shortcuts to the folders?": "Do you also want to remove the {0} IFS shortcuts to the folders?",
105108
"Do you want to copy or move the selection to {0}?": "Czy chcesz skopiować, czy przenieść zaznaczenie do {0}?",
106109
"Download certificate": "Pobierz certyfikat",
107110
"Download complete": "Pobieranie zakończone",

src/ui/views/ifsBrowser.ts

Lines changed: 97 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os from "os";
22
import path, { dirname, extname } from "path";
3-
import vscode, { FileType, l10n, Uri, window } from "vscode";
3+
import vscode, { CancellationToken, Event, FileDecoration, FileDecorationProvider, FileType, l10n, ProviderResult, ThemeColor, Uri, window } from "vscode";
44

55
import { existsSync, mkdirSync, rmdirSync } from "fs";
66
import IBMi from "../../api/IBMi";
@@ -187,6 +187,7 @@ class IFSShortcutItem extends IFSDirectoryItem {
187187
this.contextValue = `shortcut${protectedDir ? `_protected` : ``}`;
188188
this.iconPath = new vscode.ThemeIcon(protectedDir ? "lock-small" : "folder-library");
189189
this.tooltip = ``;
190+
this.resourceUri = Uri.parse(`shortcut:${shortcut}`);
190191
}
191192
}
192193

@@ -312,12 +313,17 @@ export function initializeIFSBrowser(context: vscode.ExtensionContext) {
312313
canSelectMany: true,
313314
dragAndDropController: new IFSBrowserDragAndDrop()
314315
});
316+
const shortcutDecorationProvider = new ShortcutDecorationProvider();
315317

316318
const getSelectedItems = <T>(node?: T | T[]) => node ? Array.isArray(node) ? node : [node] : ifsTreeViewer.selection as T[];
317319

318320
context.subscriptions.push(
319321
ifsTreeViewer,
320-
vscode.commands.registerCommand(`code-for-ibmi.refreshIFSBrowser`, () => ifsBrowser.refresh()),
322+
window.registerFileDecorationProvider(shortcutDecorationProvider),
323+
vscode.commands.registerCommand(`code-for-ibmi.refreshIFSBrowser`, () => {
324+
ifsBrowser.refresh();
325+
shortcutDecorationProvider.refresh();
326+
}),
321327
vscode.commands.registerCommand(`code-for-ibmi.refreshIFSBrowserItem`, (item?: BrowserItem) => ifsBrowser.refresh(item)),
322328

323329
vscode.commands.registerCommand(`code-for-ibmi.revealInIFSBrowser`, async (item: BrowserItem, options?: FocusOptions) => {
@@ -443,6 +449,7 @@ export function initializeIFSBrowser(context: vscode.ExtensionContext) {
443449

444450
if (IBMi.connectionManager.get(`autoRefresh`)) {
445451
ifsBrowser.refresh(node);
452+
vscode.commands.executeCommand(`code-for-ibmi.refreshIFSBrowser`);
446453
}
447454

448455
} catch (e: any) {
@@ -542,92 +549,87 @@ export function initializeIFSBrowser(context: vscode.ExtensionContext) {
542549
}
543550
}),
544551

545-
vscode.commands.registerCommand(`code-for-ibmi.deleteIFS`, async (singleItem: IFSItem | IFSShortcutItem, items?: IFSItem[] | IFSShortcutItem[]) => {
552+
vscode.commands.registerCommand(`code-for-ibmi.deleteIFS`, async (singleItem: IFSItem, items?: IFSItem[]) => {
546553
const connection = instance.getConnection();
547554
if (connection) {
548-
if (singleItem instanceof IFSShortcutItem || items instanceof IFSShortcutItem) {
549-
const config = connection.getConfig();
550-
const shortcuts = config.ifsShortcuts;
551-
const toBeRemoved = (items || [singleItem]).map(n => n.path);
555+
const config = connection.getConfig();
556+
const shortcuts = config.ifsShortcuts;
557+
if (items || singleItem) {
558+
items = (items || [singleItem]).filter(reduceIFSPath);
559+
}
560+
else {
561+
items = getSelectedItems(singleItem).filter(reduceIFSPath);
562+
}
552563

553-
try {
554-
if (toBeRemoved.length) {
555-
config.ifsShortcuts = shortcuts.filter(path => !toBeRemoved.includes(path));
556-
await IBMi.connectionManager.update(config);
557-
if (IBMi.connectionManager.get(`autoRefresh`)) {
558-
ifsBrowser.refresh();
559-
}
560-
}
561-
} catch (e) {
562-
console.log(e);
563-
}
564-
} else {
565-
if (items || singleItem) {
566-
items = (items || [singleItem]).filter(reduceIFSPath);
567-
}
568-
else {
569-
items = getSelectedItems(singleItem).filter(reduceIFSPath);
570-
}
564+
if (items && items.length) {
565+
if (!items.find(n => isProtected(n.path))) {
566+
let deletionConfirmed = false;
567+
const message = items.length === 1 ? l10n.t(`Are you sure you want to delete {0}?`, items[0].path) : l10n.t("Are you sure you want to delete the {0} selected files?", items.length);
568+
const detail = items.length === 1 ? undefined : items.map(i => `- ${i.path}`).join("\n");
569+
if (await vscode.window.showWarningMessage(message, { modal: true, detail }, l10n.t(`Yes`))) {
570+
const toBeDeleted: string[] = [];
571+
for (const item of items) {
572+
if ((IBMi.connectionManager.get(`safeDeleteMode`)) && item.file.type === `directory`) { //Check if path is directory
573+
const dirName = path.basename(item.path) //Get the name of the directory to be deleted
571574

572-
if (items && items.length) {
573-
if (!items.find(n => isProtected(n.path))) {
574-
let deletionConfirmed = false;
575-
const message = items.length === 1 ? l10n.t(`Are you sure you want to delete {0}?`, items[0].path) : l10n.t("Are you sure you want to delete the {0} selected files?", items.length);
576-
const detail = items.length === 1 ? undefined : items.map(i => `- ${i.path}`).join("\n");
577-
if (await vscode.window.showWarningMessage(message, { modal: true, detail }, l10n.t(`Yes`))) {
578-
const toBeDeleted: string[] = [];
579-
for (const item of items) {
580-
if ((IBMi.connectionManager.get(`safeDeleteMode`)) && item.file.type === `directory`) { //Check if path is directory
581-
const dirName = path.basename(item.path) //Get the name of the directory to be deleted
582-
583-
const deletionPrompt = l10n.t(`Once you delete the directory, it cannot be restored.
575+
const deletionPrompt = l10n.t(`Once you delete the directory, it cannot be restored.
584576
Please type "{0}" to confirm deletion.`, dirName);
585-
const input = await vscode.window.showInputBox({
586-
placeHolder: dirName,
587-
prompt: deletionPrompt,
588-
validateInput: text => {
589-
return (text === dirName) ? null : deletionPrompt + l10n.t(` (Press "Escape" to cancel)`);
590-
}
591-
});
592-
deletionConfirmed = (input === dirName);
593-
}
594-
else {
595-
// If deleting a file rather than a directory, skip the name entry
596-
// Do not delete a file if one of its parent directory is going to be deleted
597-
deletionConfirmed = true;
598-
}
577+
const input = await vscode.window.showInputBox({
578+
placeHolder: dirName,
579+
prompt: deletionPrompt,
580+
validateInput: text => {
581+
return (text === dirName) ? null : deletionPrompt + l10n.t(` (Press "Escape" to cancel)`);
582+
}
583+
});
584+
deletionConfirmed = (input === dirName);
585+
}
586+
else {
587+
// If deleting a file rather than a directory, skip the name entry
588+
// Do not delete a file if one of its parent directory is going to be deleted
589+
deletionConfirmed = true;
590+
}
599591

600-
if (deletionConfirmed) {
601-
toBeDeleted.push(item.path);
602-
}
592+
if (deletionConfirmed) {
593+
toBeDeleted.push(item.path);
603594
}
595+
}
604596

605-
try {
606-
const removeResult = await vscode.window.withProgress({ title: l10n.t(`Deleting {0} element(s)...`, toBeDeleted.length), location: vscode.ProgressLocation.Notification }, async () => {
607-
return await connection.sendCommand({ command: `rm -rf ${toBeDeleted.map(path => Tools.escapePath(path)).join(" ")}` });
608-
});
597+
try {
598+
const removeResult = await vscode.window.withProgress({ title: l10n.t(`Deleting {0} element(s)...`, toBeDeleted.length), location: vscode.ProgressLocation.Notification }, async () => {
599+
return await connection.sendCommand({ command: `rm -rf ${toBeDeleted.map(path => Tools.escapePath(path)).join(" ")}` });
600+
});
609601

610-
if (removeResult.code !== 0) {
611-
throw removeResult.stderr;
612-
}
613-
if (IBMi.connectionManager.get(`autoRefresh`)) {
614-
items.map(item => item.parent)
615-
.filter(Tools.distinct)
616-
.forEach(async parent => parent?.refresh?.());
602+
if (removeResult.code !== 0) {
603+
throw removeResult.stderr;
604+
}
605+
606+
const deletedShortcuts = shortcuts.filter(path => toBeDeleted.includes(path));
607+
if (deletedShortcuts.length) {
608+
const message = deletedShortcuts.length === 1 ? l10n.t(`Do you also want to remove the IFS shortcut to the folder {0}?`, deletedShortcuts[0]) : l10n.t("Do you also want to remove the IFS shortcuts to the folders {0}?", deletedShortcuts.length);
609+
const detail = deletedShortcuts.length === 1 ? undefined : deletedShortcuts.map(i => `- ${i}`).join("\n");
610+
if (await vscode.window.showWarningMessage(message, { modal: true, detail }, l10n.t(`Yes`))) {
611+
config.ifsShortcuts = shortcuts.filter(path => !deletedShortcuts.includes(path));
617612
}
618-
} catch (e: any) {
619-
vscode.window.showErrorMessage(l10n.t(`Error deleting streamfile! {0}`, e));
620613
}
621-
}
622-
else {
623-
vscode.window.showInformationMessage(l10n.t(`Deletion canceled.`));
614+
615+
if (IBMi.connectionManager.get(`autoRefresh`)) {
616+
items.map(item => item.parent)
617+
.filter(Tools.distinct)
618+
.forEach(async parent => parent?.refresh?.());
619+
vscode.commands.executeCommand(`code-for-ibmi.refreshIFSBrowser`);
620+
}
621+
} catch (e: any) {
622+
vscode.window.showErrorMessage(l10n.t(`Error deleting streamfile! {0}`, e));
624623
}
625624
}
626625
else {
627-
vscode.window.showErrorMessage(l10n.t(`Unable to delete protected directories from the IFS Browser!
628-
{0}`, items.filter(n => isProtected(n.path)).map(n => n.path).join(`\n`)));
626+
vscode.window.showInformationMessage(l10n.t(`Deletion canceled.`));
629627
}
630628
}
629+
else {
630+
vscode.window.showErrorMessage(l10n.t(`Unable to delete protected directories from the IFS Browser!
631+
{0}`, items.filter(n => isProtected(n.path)).map(n => n.path).join(`\n`)));
632+
}
631633
}
632634
}
633635
}),
@@ -1095,3 +1097,26 @@ async function showOpenDialog() {
10951097
function reduceIFSPath(item: IFSItem, index: number, array: IFSItem[]) {
10961098
return !array.filter(i => i.file.type === "directory" && i !== item).some(folder => item.file.path.startsWith(`${folder.file.path}/`));
10971099
}
1100+
export class ShortcutDecorationProvider implements FileDecorationProvider {
1101+
private readonly _onDidChangeFileDecorations = new vscode.EventEmitter<vscode.Uri | vscode.Uri[] | undefined>();
1102+
readonly onDidChangeFileDecorations = this._onDidChangeFileDecorations.event;
1103+
1104+
provideFileDecoration(uri: Uri, token: CancellationToken): ProviderResult<FileDecoration> {
1105+
if (uri.scheme === 'shortcut') {
1106+
return instance.getConnection()?.getContent().isDirectory(uri.path).then(isFound => {
1107+
if (!isFound) {
1108+
return {
1109+
badge: '⚠',
1110+
color: new ThemeColor('errorForeground'),
1111+
tooltip: l10n.t(`Directory does not exist.`)
1112+
};
1113+
}
1114+
return undefined;
1115+
});
1116+
}
1117+
}
1118+
1119+
refresh(uri?: vscode.Uri | vscode.Uri[]) {
1120+
this._onDidChangeFileDecorations.fire(uri);
1121+
}
1122+
}

0 commit comments

Comments
 (0)