Fix non-file dragover bug #597 (#598)

This commit is contained in:
Jaifroid 2024-05-06 14:59:21 +01:00 committed by GitHub
parent cb763bbcab
commit ef0c3d306f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 79 additions and 21 deletions

View File

@ -110,6 +110,10 @@ div:not(.panel-success, .alert-message) {
padding-left: 1px !important; padding-left: 1px !important;
} }
.dragging-over * {
pointer-events: none;
}
#articleList { #articleList {
margin-bottom: 12px !important; margin-bottom: 12px !important;
overflow-wrap: break-word; overflow-wrap: break-word;

View File

@ -1247,7 +1247,7 @@
<span class="checkmark"></span> <span class="checkmark"></span>
<b>Use legacy method for reading Zimit-based archives</b> (may be faster on some systems) <b>Use legacy method for reading Zimit-based archives</b> (may be faster on some systems)
</label> </label>
<label class="checkbox" title="In some browsers on some platforms, drag-and-drop may malfunction and make it difficult to select text, and other operations. Disable it here if it is causing issues." > <label class="checkbox" title="In some browsers on some platforms, drag-and-drop may malfunction. Disable it here if it is causing issues." >
<input type="checkbox" name="disableDragAndDrop" id="disableDragAndDropCheck"> <input type="checkbox" name="disableDragAndDrop" id="disableDragAndDropCheck">
<span class="checkmark"></span> <span class="checkmark"></span>
<b>Disable drag-and-drop</b> (in case it is causing anomalies) <b>Disable drag-and-drop</b> (in case it is causing anomalies)

View File

@ -3696,19 +3696,6 @@ function processDirectoryOfFiles (fileHandles, archive) {
} }
} }
if (!params.disableDragAndDrop) {
// Define globalDropZone (universal drop area) and configDropZone (highlighting area on Config page)
var globalDropZone = document.getElementById('search-article');
var configDropZone = document.getElementById('configuration');
// Set the main drop zone
globalDropZone.addEventListener('dragover', handleGlobalDragover);
globalDropZone.addEventListener('drop', handleFileDrop);
configDropZone.addEventListener('dragleave', function (e) {
configDropZone.style.border = '';
});
}
/** /**
* Displays the zone to select files from the archive * Displays the zone to select files from the archive
*/ */
@ -3717,29 +3704,94 @@ function displayFileSelect () {
document.getElementById('rescanStorage').style.display = 'none'; document.getElementById('rescanStorage').style.display = 'none';
} }
/** Drag and Drop handling for ZIM files (see kiwix-js#1245 by @D3V-D) **/
// Set a global drop zone, so that whole page is enabled for drag and drop
const globalDropZone = document.getElementById('search-article');
// Keep track of entrance event so we only fire the correct leave event
let enteredElement;
// Add drag-and-drop event listeners
if (!params.disableDragAndDrop) {
globalDropZone.addEventListener('dragover', handleGlobalDragover);
globalDropZone.addEventListener('dragleave', handleGlobalDragleave);
globalDropZone.addEventListener('drop', handleFileDrop);
globalDropZone.addEventListener('dragenter', handleGlobalDragenter);
}
function handleGlobalDragenter (e) {
e.preventDefault();
// Disable pointer-events on children so they don't interfere with dragleave events
globalDropZone.classList.add('dragging-over');
enteredElement = e.target;
}
function handleGlobalDragover (e) { function handleGlobalDragover (e) {
e.preventDefault(); e.preventDefault();
e.dataTransfer.dropEffect = 'link'; if (hasType(e.dataTransfer.types, 'Files') && !hasInvalidType(e.dataTransfer.types)) {
if (configDropZone.style.display === 'none') document.getElementById('btnConfigure').click(); e.dataTransfer.dropEffect = 'link';
configDropZone.style.border = '3px dotted red'; globalDropZone.classList.add('dragging-over');
globalDropZone.style.border = '3px dashed red';
if (document.getElementById('configuration').style.display === 'none') {
btnConfigure.click();
}
}
}
function handleGlobalDragleave (e) {
e.preventDefault();
globalDropZone.style.border = '';
if (enteredElement === e.target) {
globalDropZone.classList.remove('dragging-over');
// Only return to page if a ZIM is actually loaded
if (appstate.selectedArchive !== null && appstate.selectedArchive.isReady()) {
setTab();
}
}
} }
function handleIframeDragover (e) { function handleIframeDragover (e) {
e.preventDefault(); e.preventDefault();
e.dataTransfer.dropEffect = 'link'; if (hasType(e.dataTransfer.types, 'Files') && !hasInvalidType(e.dataTransfer.types)) {
document.getElementById('btnConfigure').click(); globalDropZone.classList.add('dragging-over');
e.dataTransfer.dropEffect = 'link';
document.getElementById('btnConfigure').click();
}
} }
function handleIframeDrop (e) { function handleIframeDrop (e) {
e.stopPropagation();
e.preventDefault(); e.preventDefault();
e.stopPropagation();
}
// Add type check for chromium browsers, since they count images on the same page as files
function hasInvalidType (typesList) {
for (var i = 0; i < typesList.length; i++) {
// Use indexOf() instead of startsWith() for IE11 support. Also, IE11 uses Text instead of text (and so does Opera).
// This is not comprehensive, but should cover most cases.
if (typesList[i].indexOf('image') === 0 || typesList[i].indexOf('text') === 0 || typesList[i].indexOf('Text') === 0 || typesList[i].indexOf('video') === 0) {
return true;
}
}
return false;
}
// IE11 doesn't support .includes(), so custom function to check for presence of types
function hasType (typesList, type) {
for (var i = 0; i < typesList.length; i++) {
if (typesList[i] === type) {
return true;
}
}
return false;
} }
function handleFileDrop (packet) { function handleFileDrop (packet) {
appstate.filesDropped = true; appstate.filesDropped = true;
packet.stopPropagation(); packet.stopPropagation();
packet.preventDefault(); packet.preventDefault();
configDropZone.style.border = ''; globalDropZone.style.border = '';
globalDropZone.classList.remove('dragging-over');
var items = packet.dataTransfer.items; var items = packet.dataTransfer.items;
// Turn off OPFS if it is on // Turn off OPFS if it is on
if (params.useOPFS) { if (params.useOPFS) {
@ -3779,6 +3831,8 @@ function handleFileDrop (packet) {
params.storedFile = null; params.storedFile = null;
params.rescan = false; params.rescan = false;
setLocalArchiveFromFileList(files); setLocalArchiveFromFileList(files);
// Delete any previous file system handle (as otherwise, it will get inadvertienly reloaded)
cache.idxDB('delete', 'pickedFSHandle', function () {});
} }
} }