Merge pull request #263 from EdouardVanbelle/fix/select-all
This commit is contained in:
@@ -206,23 +206,11 @@ async function loadFiles(options = { insertHistory: true}) {
|
|||||||
|
|
||||||
const listing = await response.json();
|
const listing = await response.json();
|
||||||
|
|
||||||
if (window.multiSelect) window.multiSelect.clear();
|
|
||||||
window.ui._items.clear();
|
window.ui._items.clear();
|
||||||
|
window.ui.resetFilesList();
|
||||||
const _t = (window.i18n && window.i18n.t) ? window.i18n.t : k => k.split('.').pop();
|
if (window.multiSelect) {
|
||||||
window.ui.showError(`
|
window.multiSelect.clear();
|
||||||
<div class="list-header">
|
window.multiSelect.init(); // this will wire buttons & select-all-checkbox
|
||||||
<div class="list-header-checkbox"><input type="checkbox" id="select-all-checkbox" title="Select all"></div>
|
|
||||||
<div data-i18n="files.name">${_t('files.name')}</div>
|
|
||||||
<div data-i18n="files.type">${_t('files.type')}</div>
|
|
||||||
<div data-i18n="files.size">${_t('files.size')}</div>
|
|
||||||
<div data-i18n="files.modified">${_t('files.modified')}</div>
|
|
||||||
</div>`
|
|
||||||
);
|
|
||||||
|
|
||||||
const selectAllCb = document.getElementById('select-all-checkbox');
|
|
||||||
if (selectAllCb && window.multiSelect) {
|
|
||||||
selectAllCb.addEventListener('change', () => window.multiSelect.toggleAll());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const folderList = Array.isArray(listing.folders) ? listing.folders : [];
|
const folderList = Array.isArray(listing.folders) ? listing.folders : [];
|
||||||
@@ -231,7 +219,6 @@ async function loadFiles(options = { insertHistory: true}) {
|
|||||||
if (folderList.length === 0 && fileList.length === 0) {
|
if (folderList.length === 0 && fileList.length === 0) {
|
||||||
window.ui.showEmptyList();
|
window.ui.showEmptyList();
|
||||||
} else {
|
} else {
|
||||||
window.ui.resetFilesList();
|
|
||||||
window.ui.renderFolders(folderList);
|
window.ui.renderFolders(folderList);
|
||||||
window.ui.renderFiles(fileList);
|
window.ui.renderFiles(fileList);
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -892,6 +892,12 @@ const ui = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shiftkey is used to complete selection
|
||||||
|
if (e.shiftKey && window.multiSelect) {
|
||||||
|
window.multiSelect.handleToggleItem(card, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (info.type === 'folder') {
|
if (info.type === 'folder') {
|
||||||
navigateFolder(card);
|
navigateFolder(card);
|
||||||
} else {
|
} else {
|
||||||
@@ -1225,6 +1231,7 @@ const ui = {
|
|||||||
const filesContainerError=document.getElementById("files-container-error");
|
const filesContainerError=document.getElementById("files-container-error");
|
||||||
|
|
||||||
if (!filesList) return;
|
if (!filesList) return;
|
||||||
|
|
||||||
filesList.innerHTML=`
|
filesList.innerHTML=`
|
||||||
<div class="list-header">
|
<div class="list-header">
|
||||||
<div class="list-header-checkbox"><input type="checkbox" id="select-all-checkbox" title="Select all"></div>
|
<div class="list-header-checkbox"><input type="checkbox" id="select-all-checkbox" title="Select all"></div>
|
||||||
@@ -1350,7 +1357,7 @@ const ui = {
|
|||||||
*/
|
*/
|
||||||
function toggleCardSelection(card, event) {
|
function toggleCardSelection(card, event) {
|
||||||
if (window.multiSelect) {
|
if (window.multiSelect) {
|
||||||
window.multiSelect.handleItemClick(card, event);
|
window.multiSelect.handleToggleItem(card, event);
|
||||||
} else {
|
} else {
|
||||||
card.classList.toggle('selected');
|
card.classList.toggle('selected');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
// TODO: rename into selection-bar ?
|
// TODO: rename into selection-bar ?
|
||||||
// TODO: merge with photo part
|
// TODO: merge with photo part
|
||||||
|
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
const multiSelect = {
|
const multiSelect = {
|
||||||
/** Currently selected items: Map<id, { id, name, type, parentId }> */
|
/** Currently selected items: Map<id, { id, name, type, parentId }> */
|
||||||
_selected: new Map(),
|
_selected: new Map(),
|
||||||
@@ -162,17 +164,12 @@ const multiSelect = {
|
|||||||
|
|
||||||
// ── Click handler (shared by grid + list) ───────────────
|
// ── Click handler (shared by grid + list) ───────────────
|
||||||
|
|
||||||
handleItemClick(el, event) {
|
handleToggleItem(el, event) {
|
||||||
const items = this._getAllVisibleItems();
|
const items = this._getAllVisibleItems();
|
||||||
const index = items.indexOf(el);
|
const index = items.indexOf(el);
|
||||||
const info = this._extractInfo(el);
|
const info = this._extractInfo(el);
|
||||||
if (!info) return;
|
if (!info) return;
|
||||||
|
|
||||||
const selectorOther = info.type === 'folder'
|
|
||||||
? `[data-folder-id="${info.id}"]`
|
|
||||||
: `[data-file-id="${info.id}"]`;
|
|
||||||
const otherEl = [...document.querySelectorAll(selectorOther)].find(e => e !== el);
|
|
||||||
|
|
||||||
if (event && event.shiftKey && this._lastClickedIndex >= 0 && index >= 0) {
|
if (event && event.shiftKey && this._lastClickedIndex >= 0 && index >= 0) {
|
||||||
const start = Math.min(this._lastClickedIndex, index);
|
const start = Math.min(this._lastClickedIndex, index);
|
||||||
const end = Math.max(this._lastClickedIndex, index);
|
const end = Math.max(this._lastClickedIndex, index);
|
||||||
@@ -183,16 +180,24 @@ const multiSelect = {
|
|||||||
const sel = iInfo.type === 'folder'
|
const sel = iInfo.type === 'folder'
|
||||||
? `[data-folder-id="${iInfo.id}"]`
|
? `[data-folder-id="${iInfo.id}"]`
|
||||||
: `[data-file-id="${iInfo.id}"]`;
|
: `[data-file-id="${iInfo.id}"]`;
|
||||||
document.querySelectorAll(sel).forEach(e => e.classList.add('selected'));
|
document.querySelectorAll(sel).forEach((e) => {
|
||||||
|
e.classList.add('selected');
|
||||||
|
let checkbox = e.querySelector('input[type="checkbox"]');
|
||||||
|
if (checkbox)
|
||||||
|
checkbox.checked = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const nowSelected = this.toggle(info.id, info.name, info.type, info.parentId);
|
const nowSelected = this.toggle(info.id, info.name, info.type, info.parentId);
|
||||||
el.classList.toggle('selected', nowSelected);
|
el.classList.toggle('selected', nowSelected);
|
||||||
if (otherEl) otherEl.classList.toggle('selected', nowSelected);
|
let checkbox = el.querySelector('input[type="checkbox"]');
|
||||||
|
if (checkbox)
|
||||||
|
checkbox.checked = nowSelected;
|
||||||
}
|
}
|
||||||
this._lastClickedIndex = index;
|
this._lastClickedIndex = index;
|
||||||
this._syncUI();
|
this._syncUI();
|
||||||
|
this._syncSelectAllCheckbox();
|
||||||
},
|
},
|
||||||
|
|
||||||
// ── Selection bar (replaces list-header when items selected) ────
|
// ── Selection bar (replaces list-header when items selected) ────
|
||||||
@@ -481,15 +486,19 @@ const multiSelect = {
|
|||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if (e.target.closest('input, textarea, [contenteditable], .rename-dialog, .share-dialog, .confirm-dialog')) return;
|
if (e.target.closest('input, textarea, [contenteditable], .rename-dialog, .share-dialog, .confirm-dialog')) return;
|
||||||
|
|
||||||
|
const selectAllCheckbox = document.getElementById('select-all-checkbox');
|
||||||
// ctrl+a cmd+a
|
// ctrl+a cmd+a
|
||||||
if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
|
if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
|
||||||
const filesList = document.getElementById('files-list');
|
if (selectAllCheckbox)
|
||||||
if (filesList && filesList.closest('.files-container')) {
|
selectAllCheckbox.checked = true;
|
||||||
e.preventDefault();
|
this.selectAll();
|
||||||
this.selectAll();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
if (e.key === 'Escape' && this.hasSelection) {
|
||||||
|
this.clear();
|
||||||
|
if (selectAllCheckbox)
|
||||||
|
selectAllCheckbox.checked = false;
|
||||||
}
|
}
|
||||||
if (e.key === 'Escape' && this.hasSelection) this.clear();
|
|
||||||
if (e.key === 'Delete' && this.hasSelection) this.batchDelete();
|
if (e.key === 'Delete' && this.hasSelection) this.batchDelete();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -503,10 +512,12 @@ const multiSelect = {
|
|||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// FIXME: competition with _
|
||||||
_injectListHeaderCheckbox() {
|
_injectListHeaderCheckbox() {
|
||||||
const cb = document.getElementById('select-all-checkbox');
|
const self = this;
|
||||||
if (!cb) return;
|
const selectAllCheckbox = document.getElementById('select-all-checkbox');
|
||||||
cb.addEventListener('change', () => this.toggleAll());
|
if (!selectAllCheckbox) return;
|
||||||
|
selectAllCheckbox.addEventListener('change', () => self.toggleAll());
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -106,18 +106,6 @@ const search = {
|
|||||||
window.ui.resetFilesList(); // ensure also list visible & error hidden
|
window.ui.resetFilesList(); // ensure also list visible & error hidden
|
||||||
const filesList = document.getElementById('files-list');
|
const filesList = document.getElementById('files-list');
|
||||||
|
|
||||||
// reset list
|
|
||||||
filesList.innerHTML = `
|
|
||||||
<div class="list-header">
|
|
||||||
<div class="list-header-checkbox"><input type="checkbox" id="select-all-checkbox" title="Select all"></div>
|
|
||||||
<div data-i18n="files.name">Name</div>
|
|
||||||
<div data-i18n="files.type">Type</div>
|
|
||||||
<div data-i18n="files.size">Size</div>
|
|
||||||
<div data-i18n="files.modified">Modified</div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Search results header with query time and sort controls
|
// Search results header with query time and sort controls
|
||||||
const totalCount = results.total_count || (results.files.length + results.folders.length);
|
const totalCount = results.total_count || (results.files.length + results.folders.length);
|
||||||
const queryTimeText = results.query_time_ms !== undefined
|
const queryTimeText = results.query_time_ms !== undefined
|
||||||
|
|||||||
@@ -168,18 +168,6 @@ const favorites = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.ui.resetFilesList(); // ensure also list visible & error hidden
|
window.ui.resetFilesList(); // ensure also list visible & error hidden
|
||||||
const filesList = document.getElementById('files-list');
|
|
||||||
|
|
||||||
filesList.innerHTML = `
|
|
||||||
<div class="list-header">
|
|
||||||
<div class="list-header-checkbox"><input type="checkbox" id="select-all-checkbox" title="Select all"></div>
|
|
||||||
<div data-i18n="files.name">Name</div>
|
|
||||||
<div data-i18n="files.type">Type</div>
|
|
||||||
<div data-i18n="files.size">Size</div>
|
|
||||||
<div data-i18n="files.modified">Modified</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
window.ui.updateBreadcrumb('');
|
window.ui.updateBreadcrumb('');
|
||||||
|
|
||||||
if (this._cache.size === 0) {
|
if (this._cache.size === 0) {
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ const recent = {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
if (window.multiSelect) {
|
||||||
|
window.multiSelect.clear();
|
||||||
|
window.multiSelect.init(); // this will wire buttons & select-all-checkbox
|
||||||
|
}
|
||||||
window.ui.updateBreadcrumb('');
|
window.ui.updateBreadcrumb('');
|
||||||
|
|
||||||
if (recentItems.length === 0) {
|
if (recentItems.length === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user