feat: download - fase 01

This commit is contained in:
kodi
2026-03-14 12:31:11 +01:00
parent af1d1eea23
commit 610a648fd1
11 changed files with 182 additions and 0 deletions
+50
View File
@@ -328,6 +328,7 @@ function contextMenuElements() {
target: document.getElementById("context-menu-target"),
openButton: document.getElementById("context-menu-open-btn"),
editButton: document.getElementById("context-menu-edit-btn"),
downloadButton: document.getElementById("context-menu-download-btn"),
renameButton: document.getElementById("context-menu-rename-btn"),
copyButton: document.getElementById("context-menu-copy-btn"),
moveButton: document.getElementById("context-menu-move-btn"),
@@ -383,12 +384,15 @@ function openContextMenu(pane, entry, event) {
const isMulti = items.length > 1;
const openableSingle = items.length === 1 && isOpenableSelection(items[0]);
const editableSingle = items.length === 1 && isEditableSelection(items[0]);
const downloadableSingle = items.length === 1 && items[0].kind === "file";
elements.scope.textContent = isMulti ? "Multi-selection" : "Single item";
elements.target.textContent = isMulti ? `${items.length} selected items` : entry.name;
elements.openButton.classList.toggle("hidden", isMulti);
elements.openButton.disabled = !openableSingle;
elements.editButton.classList.toggle("hidden", isMulti || items.length !== 1 || items[0].kind !== "file");
elements.editButton.disabled = !editableSingle;
elements.downloadButton.classList.toggle("hidden", !downloadableSingle);
elements.downloadButton.disabled = !downloadableSingle;
elements.renameButton.classList.toggle("hidden", isMulti);
elements.copyButton.classList.remove("hidden");
elements.copyButton.disabled = items.length === 0;
@@ -490,6 +494,40 @@ function startContextMenuEdit() {
openEditor();
}
async function startDownloadSelected() {
const selectedItems = activePaneState().selectedItems;
if (selectedItems.length !== 1 || selectedItems[0].kind !== "file") {
return;
}
const selected = selectedItems[0];
try {
const blob = await downloadFileRequest(selected.path);
const url = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = selected.name;
document.body.append(anchor);
anchor.click();
anchor.remove();
URL.revokeObjectURL(url);
setStatus(`Download started: ${selected.name}`);
} catch (err) {
setActionError("Download", err);
}
}
function startContextMenuDownload() {
if (contextMenuElements().downloadButton?.disabled) {
return;
}
if (!applyContextMenuSelection()) {
closeContextMenu();
return;
}
closeContextMenu();
startDownloadSelected();
}
function startContextMenuProperties() {
if (contextMenuElements().propertiesButton?.disabled) {
return;
@@ -744,6 +782,15 @@ function createApiError(response, data) {
return err;
}
async function downloadFileRequest(path) {
const response = await fetch(`/api/files/download?${new URLSearchParams({ path }).toString()}`);
if (!response.ok) {
const data = await response.json().catch(() => ({}));
throw createApiError(response, data);
}
return response.blob();
}
async function uploadFileRequest(targetPath, file, overwrite = false) {
const formData = new FormData();
formData.append("target_path", targetPath);
@@ -3836,6 +3883,9 @@ function setupEvents() {
if (contextMenu.editButton) {
contextMenu.editButton.onclick = startContextMenuEdit;
}
if (contextMenu.downloadButton) {
contextMenu.downloadButton.onclick = startContextMenuDownload;
}
if (contextMenu.copyButton) {
contextMenu.copyButton.onclick = startContextMenuCopy;
}