Progress Modal on download buttons

This commit is contained in:
Ryan
2025-04-08 20:30:17 -04:00
committed by GitHub
parent 703c93db25
commit f65b151bc3
8 changed files with 152 additions and 18 deletions

View File

@@ -1,5 +1,6 @@
// domUtils.js
import { t } from './i18n.js';
import { openDownloadModal } from './fileActions.js';
// Basic DOM Helpers
export function toggleVisibility(elementId, shouldShow) {
@@ -165,11 +166,11 @@ export function buildFileTableRow(file, folderPath) {
<td class="hide-small hide-medium nowrap">${safeUploader}</td>
<td>
<div class="button-wrap" style="display: flex; justify-content: left; gap: 5px;">
<a class="btn btn-sm btn-success download-btn"
href="download.php?folder=${encodeURIComponent(file.folder || 'root')}&file=${encodeURIComponent(file.name)}"
title="Download">
<i class="material-icons">file_download</i>
</a>
<button type="button" class="btn btn-sm btn-success download-btn"
onclick="openDownloadModal('${file.name}', '${file.folder || 'root'}')"
title="Download">
<i class="material-icons">file_download</i>
</button>
${file.editable ? `
<button class="btn btn-sm edit-btn"
onclick='editFile(${JSON.stringify(file.name)}, ${JSON.stringify(file.folder || "root")})'

View File

@@ -28,7 +28,7 @@ document.addEventListener("DOMContentLoaded", function () {
window.filesToDelete = [];
});
}
const confirmDelete = document.getElementById("confirmDeleteFiles");
if (confirmDelete) {
confirmDelete.addEventListener("click", function () {
@@ -76,6 +76,81 @@ export function handleDownloadZipSelected(e) {
}, 100);
};
export function openDownloadModal(fileName, folder) {
// Store file details globally for the download confirmation function.
window.singleFileToDownload = fileName;
window.currentFolder = folder || "root";
// Optionally pre-fill the file name input in the modal.
const input = document.getElementById("downloadFileNameInput");
if (input) {
input.value = fileName; // Use file name as-is (or modify if desired)
}
// Show the single file download modal (a new modal element).
document.getElementById("downloadFileModal").style.display = "block";
// Optionally focus the input after a short delay.
setTimeout(() => {
if (input) input.focus();
}, 100);
}
export function confirmSingleDownload() {
// Get the file name from the modal. Users can change it if desired.
let fileName = document.getElementById("downloadFileNameInput").value.trim();
if (!fileName) {
showToast("Please enter a name for the file.");
return;
}
// Hide the download modal.
document.getElementById("downloadFileModal").style.display = "none";
// Show the progress modal (same as in your ZIP download flow).
document.getElementById("downloadProgressModal").style.display = "block";
// Build the URL for download.php using GET parameters.
const folder = window.currentFolder || "root";
const downloadURL = "download.php?folder=" + encodeURIComponent(folder) +
"&file=" + encodeURIComponent(window.singleFileToDownload);
fetch(downloadURL, {
method: "GET",
credentials: "include"
})
.then(response => {
if (!response.ok) {
return response.text().then(text => {
throw new Error("Failed to download file: " + text);
});
}
return response.blob();
})
.then(blob => {
if (!blob || blob.size === 0) {
throw new Error("Received empty file.");
}
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.style.display = "none";
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
a.remove();
// Hide the progress modal.
document.getElementById("downloadProgressModal").style.display = "none";
showToast("Download started.");
})
.catch(error => {
// Hide progress modal and show error.
document.getElementById("downloadProgressModal").style.display = "none";
console.error("Error downloading file:", error);
showToast("Error downloading file: " + error.message);
});
}
export function handleExtractZipSelected(e) {
if (e) {
e.preventDefault();
@@ -137,7 +212,8 @@ document.addEventListener("DOMContentLoaded", function () {
document.getElementById("downloadZipModal").style.display = "none";
});
}
// This part remains in your confirmDownloadZip event handler:
const confirmDownloadZip = document.getElementById("confirmDownloadZip");
if (confirmDownloadZip) {
confirmDownloadZip.addEventListener("click", function () {
@@ -149,7 +225,11 @@ document.addEventListener("DOMContentLoaded", function () {
if (!zipName.toLowerCase().endsWith(".zip")) {
zipName += ".zip";
}
// Hide the ZIP name input modal
document.getElementById("downloadZipModal").style.display = "none";
// Show the progress modal here only on confirm
console.log("Download confirmed. Showing progress modal.");
document.getElementById("downloadProgressModal").style.display = "block";
const folder = window.currentFolder || "root";
fetch("downloadZip.php", {
method: "POST",
@@ -181,9 +261,13 @@ document.addEventListener("DOMContentLoaded", function () {
a.click();
window.URL.revokeObjectURL(url);
a.remove();
// Hide the progress modal after download starts
document.getElementById("downloadProgressModal").style.display = "none";
showToast("Download started.");
})
.catch(error => {
// Hide the progress modal on error
document.getElementById("downloadProgressModal").style.display = "none";
console.error("Error downloading zip:", error);
showToast("Error downloading selected files as zip: " + error.message);
});
@@ -220,12 +304,12 @@ export async function loadCopyMoveFolderListForModal(dropdownId) {
folder.toLowerCase() !== "trash" &&
(folder === username || folder.indexOf(username + "/") === 0)
);
const rootOption = document.createElement("option");
rootOption.value = username;
rootOption.textContent = formatFolderName(username);
folderSelect.appendChild(rootOption);
folders.forEach(folder => {
if (folder !== username) {
const option = document.createElement("option");
@@ -239,7 +323,7 @@ export async function loadCopyMoveFolderListForModal(dropdownId) {
}
return;
}
try {
const response = await fetch("getFolderList.php");
let folders = await response.json();
@@ -247,12 +331,12 @@ export async function loadCopyMoveFolderListForModal(dropdownId) {
folders = folders.map(item => item.folder);
}
folders = folders.filter(folder => folder !== "root" && folder.toLowerCase() !== "trash");
const rootOption = document.createElement("option");
rootOption.value = "root";
rootOption.textContent = "(Root)";
folderSelect.appendChild(rootOption);
if (Array.isArray(folders) && folders.length > 0) {
folders.forEach(folder => {
const option = document.createElement("option");

View File

@@ -14,6 +14,7 @@ import {
} from './domUtils.js';
import { t } from './i18n.js';
import { bindFileListContextMenu } from './fileMenu.js';
import { openDownloadModal } from './fileActions.js';
export let fileData = [];
export let sortOrder = { column: "uploaded", ascending: true };
@@ -284,11 +285,11 @@ export function renderGalleryView(folder) {
<span class="gallery-file-name" style="display: block;">${escapeHTML(file.name)}</span>
${tagBadgesHTML}
<div class="button-wrap" style="display: flex; justify-content: center; gap: 5px;">
<a class="btn btn-sm btn-success download-btn"
href="download.php?folder=${encodeURIComponent(file.folder || 'root')}&file=${encodeURIComponent(file.name)}"
title="Download">
<i class="material-icons">file_download</i>
</a>
<button type="button" class="btn btn-sm btn-success download-btn"
onclick="openDownloadModal('${file.name}', '${file.folder || 'root'}')"
title="Download">
<i class="material-icons">file_download</i>
</button>
${file.editable ? `
<button class="btn btn-sm edit-btn" onclick='editFile(${JSON.stringify(file.name)}, ${JSON.stringify(file.folder || "root")})' title="Edit">
<i class="material-icons">edit</i>

View File

@@ -135,6 +135,8 @@ const translations = {
"upload": "Upload",
"copy": "Copy",
"extract": "Extract",
"user": "User:",
"password": "Password:",
// Dark Mode Toggle
"dark_mode_toggle": "Dark Mode",

View File

@@ -8,7 +8,7 @@ import { initDragAndDrop, loadSidebarOrder, loadHeaderOrder } from './dragAndDro
import { initTagSearch, openTagModal, filterFilesByTag } from './fileTags.js';
import { displayFilePreview } from './filePreview.js';
import { loadFileList } from './fileListView.js';
import { initFileActions, renameFile } from './fileActions.js';
import { initFileActions, renameFile, openDownloadModal, confirmSingleDownload } from './fileActions.js';
import { editFile, saveFile } from './fileEditor.js';
import { t, applyTranslations, setLocale } from './i18n.js';
@@ -64,6 +64,8 @@ window.toggleAllCheckboxes = toggleAllCheckboxes;
window.editFile = editFile;
window.saveFile = saveFile;
window.renameFile = renameFile;
window.confirmSingleDownload = confirmSingleDownload;
window.openDownloadModal = openDownloadModal;
// Global variable for the current folder.
window.currentFolder = "root";