Enable drag-and-drop to folder strip & fix restore toast messaging

This commit is contained in:
Ryan
2025-05-21 00:54:20 -04:00
committed by GitHub
parent f162a7d0d7
commit 4a736b0224
3 changed files with 59 additions and 36 deletions

View File

@@ -1,16 +1,29 @@
# Changelog # Changelog
## Changes 5/20/2025 1.3.6 ## Changes 5/21/2025
- **Drag & Drop to Folder Strip**
- Enabled dragging files from the file list directly onto the folder-strip items.
- Hooked up `folderDragOverHandler`, `folderDragLeaveHandler`, and `folderDropHandler` to `.folder-strip-container .folder-item`.
- On drop, files are moved via `/api/file/moveFiles.php` and the file list is refreshed.
- **Restore files from trash Toast Message**
- Changed the restore handlers so that the toast always reports the actual file(s) restored (e.g. “Restored file: foo.txt”) instead of “No trash record found.”
- Removed reliance on backend message payload and now generate the confirmation text client-side based on selected items.
---
## Changes 5/20/2025 v1.3.6
- **domUtils.js** - **domUtils.js**
- `updateFileActionButtons` - `updateFileActionButtons`
- Hide selection buttons (`Delete Files`, `Copy Files`, `Move Files` & `Download ZIP`) until file is selected. - Hide selection buttons (`Delete Files`, `Copy Files`, `Move Files` & `Download ZIP`) until file is selected.
- Hides `Extract ZIP` until selecting zip files - Hide `Extract ZIP` until selecting zip files
- Hide `Create File` button when file list items are selected. - Hide `Create File` button when file list items are selected.
--- ---
## Changes 5/19/2025 1.3.5 ## Changes 5/19/2025 v1.3.5
### Added Folder strip & Create File ### Added Folder strip & Create File

View File

@@ -17,6 +17,11 @@ import { bindFileListContextMenu } from './fileMenu.js';
import { openDownloadModal } from './fileActions.js'; import { openDownloadModal } from './fileActions.js';
import { openTagModal, openMultiTagModal } from './fileTags.js'; import { openTagModal, openMultiTagModal } from './fileTags.js';
import { getParentFolder, updateBreadcrumbTitle, setupBreadcrumbDelegation } from './folderManager.js'; import { getParentFolder, updateBreadcrumbTitle, setupBreadcrumbDelegation } from './folderManager.js';
import {
folderDragOverHandler,
folderDragLeaveHandler,
folderDropHandler
} from './fileDragDrop.js';
export let fileData = []; export let fileData = [];
export let sortOrder = { column: "uploaded", ascending: true }; export let sortOrder = { column: "uploaded", ascending: true };
@@ -357,26 +362,31 @@ export async function loadFileList(folderParam) {
} }
if (window.showFoldersInList && subfolders.length) { if (window.showFoldersInList && subfolders.length) {
strip.innerHTML = subfolders.map(sf => ` strip.innerHTML = subfolders.map(sf => `
<div class="folder-item" data-folder="${sf.full}"> <div class="folder-item" data-folder="${sf.full}" draggable="true">
<i class="material-icons">folder</i> <i class="material-icons">folder</i>
<div class="folder-name">${escapeHTML(sf.name)}</div> <div class="folder-name">${escapeHTML(sf.name)}</div>
</div> </div>
`).join(""); `).join("");
strip.style.display = "flex"; strip.style.display = "flex";
strip.querySelectorAll(".folder-item").forEach(el => { strip.querySelectorAll(".folder-item").forEach(el => {
// clicktonavigate
el.addEventListener("click", () => { el.addEventListener("click", () => {
const dest = el.dataset.folder; const dest = el.dataset.folder;
window.currentFolder = dest; window.currentFolder = dest;
localStorage.setItem("lastOpenedFolder", dest); localStorage.setItem("lastOpenedFolder", dest);
// sync breadcrumb & tree
updateBreadcrumbTitle(dest); updateBreadcrumbTitle(dest);
document.querySelectorAll(".folder-option.selected") document.querySelectorAll(".folder-option.selected")
.forEach(o => o.classList.remove("selected")); .forEach(o => o.classList.remove("selected"));
document.querySelector(`.folder-option[data-folder="${dest}"]`) document.querySelector(`.folder-option[data-folder="${dest}"]`)
?.classList.add("selected"); ?.classList.add("selected");
// reload
loadFileList(dest); loadFileList(dest);
}); });
// drag & drop handlers
el.addEventListener("dragover", folderDragOverHandler);
el.addEventListener("dragleave", folderDragLeaveHandler);
el.addEventListener("drop", folderDropHandler);
}); });
} else { } else {
strip.style.display = "none"; strip.style.display = "none";

View File

@@ -79,15 +79,16 @@ export function setupTrashRestoreDelete() {
body: JSON.stringify({ files }) body: JSON.stringify({ files })
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(() => {
if (data.success) { // Always report what we actually restored
showToast(data.success); if (files.length === 1) {
showToast(`Restored file: ${files[0]}`);
} else {
showToast(`Restored files: ${files.join(", ")}`);
}
toggleVisibility("restoreFilesModal", false); toggleVisibility("restoreFilesModal", false);
loadFileList(window.currentFolder); loadFileList(window.currentFolder);
loadFolderTree(window.currentFolder); loadFolderTree(window.currentFolder);
} else {
showToast(data.error);
}
}) })
.catch(err => { .catch(err => {
console.error("Error restoring files:", err); console.error("Error restoring files:", err);
@@ -119,16 +120,15 @@ export function setupTrashRestoreDelete() {
body: JSON.stringify({ files }) body: JSON.stringify({ files })
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(() => {
if (data.success) { if (files.length === 1) {
showToast(data.success); showToast(`Restored file: ${files[0]}`);
} else {
showToast(`Restored files: ${files.join(", ")}`);
}
toggleVisibility("restoreFilesModal", false); toggleVisibility("restoreFilesModal", false);
loadFileList(window.currentFolder); loadFileList(window.currentFolder);
loadFolderTree(window.currentFolder); loadFolderTree(window.currentFolder);
} else {
showToast(data.error);
}
}) })
.catch(err => { .catch(err => {
console.error("Error restoring files:", err); console.error("Error restoring files:", err);