mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-11-01 16:15:24 +00:00
feat(file-manager): allow disabling move-to-trash confirmation (#1511)
This commit is contained in:
1 parent
fef33142b3
commit
e69029fbf7
5 files changed
+56
-11
No files matched your search
@@ -27,6 +27,10 @@
|
||||
"transferConcurrency": {
|
||||
"label": "Simultaneous File Transfers",
|
||||
"description": "How many files the side by side local/remote manager uploads or downloads at the same time. Lower this if your server limits SFTP channels."
|
||||
},
|
||||
"confirmBeforeTrash": {
|
||||
"label": "Confirm before moving files to trash",
|
||||
"description": "Ask before moving remote files to trash. Permanent deletion still requires confirmation."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -80,6 +80,13 @@
|
||||
"min": 1,
|
||||
"max": 8,
|
||||
"default": 4
|
||||
},
|
||||
{
|
||||
"key": "confirmBeforeTrash",
|
||||
"type": "boolean",
|
||||
"labelKey": "settings.user.confirmBeforeTrash.label",
|
||||
"descriptionKey": "settings.user.confirmBeforeTrash.description",
|
||||
"default": true
|
||||
}
|
||||
],
|
||||
"host": {
|
||||
|
||||
@@ -48,6 +48,7 @@ import { ConnectionLogPanel } from "@termix/plugin-sdk/ui";
|
||||
import {
|
||||
usePluginUiPreferences,
|
||||
invokeAction,
|
||||
useSettings,
|
||||
useConnectionRetry,
|
||||
logActivity,
|
||||
} from "@termix/plugin-sdk/frontend";
|
||||
@@ -146,6 +147,8 @@ function FileManagerContent({
|
||||
[t],
|
||||
);
|
||||
const { confirmWithToast } = useConfirmation();
|
||||
const confirmBeforeTrash =
|
||||
useSettings("user").values.confirmBeforeTrash !== false;
|
||||
const { addLog, clearLogs } = useConnectionLog();
|
||||
|
||||
const [currentHost] = useState<SSHHost | null>(initialHost || null);
|
||||
@@ -1484,9 +1487,7 @@ function FileManagerContent({
|
||||
|
||||
const fullMessage = `${confirmMessage}\n\n${t("fileManager.moveToTrashWarning")}`;
|
||||
|
||||
confirmWithToast(
|
||||
fullMessage,
|
||||
async () => {
|
||||
const moveToTrash = async () => {
|
||||
const operationPath = currentPath;
|
||||
const operationSession = sshSessionId;
|
||||
const deletedPaths = new Set(files.map((file) => file.path));
|
||||
@@ -1595,9 +1596,12 @@ function FileManagerContent({
|
||||
}
|
||||
console.error("Delete failed:", error);
|
||||
}
|
||||
},
|
||||
"destructive",
|
||||
);
|
||||
};
|
||||
if (confirmBeforeTrash) {
|
||||
confirmWithToast(fullMessage, moveToTrash, "destructive");
|
||||
} else {
|
||||
await moveToTrash();
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSudoPasswordSubmit(password: string) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useSettings } from "@termix/plugin-sdk/frontend";
|
||||
import { fileManagerHostSetting } from "./host-settings";
|
||||
import {
|
||||
useCallback,
|
||||
@@ -548,6 +549,8 @@ function RemotePane({
|
||||
}
|
||||
|
||||
export function SftpTransferTab() {
|
||||
const confirmBeforeTrash =
|
||||
useSettings("user").values.confirmBeforeTrash !== false;
|
||||
const { t } = useTranslation();
|
||||
const formatTransferMetrics = useMemo(
|
||||
() => createFormatTransferMetrics(t),
|
||||
@@ -894,10 +897,10 @@ export function SftpTransferTab() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteConfirmed = async () => {
|
||||
if (!deleteTarget) return;
|
||||
const entries = getContextEntries(deleteTarget);
|
||||
const paneId = deleteTarget.paneId;
|
||||
const handleDeleteConfirmed = async (target = deleteTarget) => {
|
||||
if (!target) return;
|
||||
const entries = getContextEntries(target);
|
||||
const paneId = target.paneId;
|
||||
setDeleteTarget(null);
|
||||
if (entries.length === 0) return;
|
||||
|
||||
@@ -1071,7 +1074,8 @@ export function SftpTransferTab() {
|
||||
<ContextMenuButton
|
||||
disabled={!canMutateContextPane || contextEntries.length === 0}
|
||||
onClick={() => {
|
||||
setDeleteTarget(contextMenu);
|
||||
if (confirmBeforeTrash) setDeleteTarget(contextMenu);
|
||||
else void handleDeleteConfirmed(contextMenu);
|
||||
setContextMenu(null);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { SftpTransferTab } from "../../src/frontend/SftpTransferTab";
|
||||
|
||||
const api = vi.hoisted(() => ({
|
||||
confirmBeforeTrash: undefined as boolean | undefined,
|
||||
addTransferRecent: vi.fn(),
|
||||
browseSSHDirectory: vi.fn(),
|
||||
changeSSHPermissions: vi.fn(),
|
||||
@@ -51,12 +52,20 @@ vi.mock("react-i18next", () => ({
|
||||
initReactI18next: { type: "3rdParty", init: () => {} },
|
||||
}));
|
||||
|
||||
vi.mock("@termix/plugin-sdk/frontend", async (importOriginal) => ({
|
||||
...(await importOriginal<typeof import("@termix/plugin-sdk/frontend")>()),
|
||||
useSettings: () => ({
|
||||
values: { confirmBeforeTrash: api.confirmBeforeTrash },
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock("sonner", () => ({
|
||||
toast: { success: vi.fn(), error: vi.fn() },
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
api.confirmBeforeTrash = undefined;
|
||||
api.getSSHHosts.mockResolvedValue([
|
||||
{
|
||||
id: 1,
|
||||
@@ -206,12 +215,29 @@ describe("SftpTransferTab", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("moves files to trash directly when confirmation is disabled", async () => {
|
||||
api.confirmBeforeTrash = false;
|
||||
render(<SftpTransferTab />);
|
||||
await selectHosts();
|
||||
fireEvent.contextMenu(screen.getByText("remote-1.txt"));
|
||||
await userEvent.click(screen.getByText("sftpTransfer.delete"));
|
||||
await waitFor(() =>
|
||||
expect(api.deleteSSHItem).toHaveBeenCalledWith(
|
||||
"1",
|
||||
"/srv/remote-1.txt",
|
||||
false,
|
||||
),
|
||||
);
|
||||
expect(screen.queryByText("sftpTransfer.deleteSelectedItems")).toBeNull();
|
||||
});
|
||||
|
||||
it("deletes a remote file after confirming", async () => {
|
||||
render(<SftpTransferTab />);
|
||||
await selectHosts();
|
||||
|
||||
fireEvent.contextMenu(screen.getByText("remote-1.txt"));
|
||||
await userEvent.click(screen.getByText("sftpTransfer.delete"));
|
||||
expect(api.deleteSSHItem).not.toHaveBeenCalled();
|
||||
const confirmButtons = await screen.findAllByText("sftpTransfer.delete");
|
||||
await userEvent.click(confirmButtons[confirmButtons.length - 1]);
|
||||
|
||||
|
||||
Reference in new issue
Block a user