Merge pull request #76 from jpirnay/feat-filedrop
feat: Add file drop support in Web-Interface
This commit is contained in:
@@ -167,6 +167,36 @@
|
|||||||
background-color: #c0392b;
|
background-color: #c0392b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Drag & drop overlay */
|
||||||
|
.drop-overlay {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: rgba(52, 152, 219, 0.15);
|
||||||
|
border: 4px dashed #3498db;
|
||||||
|
z-index: 300;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drop-overlay.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drop-overlay-message {
|
||||||
|
background: var(--card-bg);
|
||||||
|
color: #3498db;
|
||||||
|
padding: 24px 40px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: bold;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
/* Upload modal */
|
/* Upload modal */
|
||||||
.modal-overlay {
|
.modal-overlay {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -1760,6 +1790,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Drag & drop overlay -->
|
||||||
|
<div class="drop-overlay" id="dropOverlay">
|
||||||
|
<div class="drop-overlay-message">📥 Drop files to upload to <span id="dropOverlayPath"></span></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Failed Uploads Banner -->
|
<!-- Failed Uploads Banner -->
|
||||||
<div class="failed-uploads-banner" id="failedUploadsBanner">
|
<div class="failed-uploads-banner" id="failedUploadsBanner">
|
||||||
<div class="failed-uploads-header">
|
<div class="failed-uploads-header">
|
||||||
@@ -3078,8 +3113,70 @@
|
|||||||
this.value = qualitySlider.value;
|
this.value = qualitySlider.value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupPageDragAndDrop();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function setupPageDragAndDrop() {
|
||||||
|
const overlay = document.getElementById('dropOverlay');
|
||||||
|
const pathSpan = document.getElementById('dropOverlayPath');
|
||||||
|
let dragDepth = 0;
|
||||||
|
|
||||||
|
const hasFiles = (e) => {
|
||||||
|
if (!e.dataTransfer) return false;
|
||||||
|
const types = e.dataTransfer.types;
|
||||||
|
if (!types) return false;
|
||||||
|
for (let i = 0; i < types.length; i++) {
|
||||||
|
if (types[i] === 'Files') return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const canAcceptDrop = () => {
|
||||||
|
if (isUploadInProgress) return false;
|
||||||
|
if (document.getElementById('uploadModal').classList.contains('open')) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('dragenter', (e) => {
|
||||||
|
if (!hasFiles(e) || !canAcceptDrop()) return;
|
||||||
|
e.preventDefault();
|
||||||
|
dragDepth++;
|
||||||
|
pathSpan.textContent = currentPath === '/' ? '/ 🏠' : currentPath;
|
||||||
|
overlay.classList.add('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('dragover', (e) => {
|
||||||
|
if (!hasFiles(e) || !canAcceptDrop()) return;
|
||||||
|
e.preventDefault();
|
||||||
|
e.dataTransfer.dropEffect = 'copy';
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('dragleave', (e) => {
|
||||||
|
if (!hasFiles(e)) return;
|
||||||
|
dragDepth = Math.max(0, dragDepth - 1);
|
||||||
|
if (dragDepth === 0) overlay.classList.remove('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('drop', (e) => {
|
||||||
|
if (!hasFiles(e)) return;
|
||||||
|
e.preventDefault();
|
||||||
|
dragDepth = 0;
|
||||||
|
overlay.classList.remove('active');
|
||||||
|
if (!canAcceptDrop()) return;
|
||||||
|
const files = e.dataTransfer.files;
|
||||||
|
if (!files || files.length === 0) return;
|
||||||
|
|
||||||
|
const dt = new DataTransfer();
|
||||||
|
for (let i = 0; i < files.length; i++) dt.items.add(files[i]);
|
||||||
|
|
||||||
|
openUploadModal();
|
||||||
|
const fileInput = document.getElementById('fileInput');
|
||||||
|
fileInput.files = dt.files;
|
||||||
|
validateFile();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function openFolderModal() {
|
function openFolderModal() {
|
||||||
document.getElementById('folderPathDisplay').textContent = currentPath === '/' ? '/ 🏠' : currentPath;
|
document.getElementById('folderPathDisplay').textContent = currentPath === '/' ? '/ 🏠' : currentPath;
|
||||||
document.getElementById('folderModal').classList.add('open');
|
document.getElementById('folderModal').classList.add('open');
|
||||||
|
|||||||
Reference in New Issue
Block a user