Fix batch toast spam and add Ctrl+A select all
Batch delete/restore now shows single toast with count instead of one per entry. delEntry() and restoreEntry() accept noToast param. Added Ctrl+A to select all visible entries. Updated keyboard shortcuts help.
This commit is contained in:
@@ -294,8 +294,8 @@ function toggleTrash() {
|
||||
loadEntries();
|
||||
playSound('click');
|
||||
}
|
||||
async function restoreEntry(id) {
|
||||
try { const r = await fetch(API + '/entries/' + id + '/restore', { method: 'POST', headers: { 'Authorization': 'Bearer ' + token, 'X-CSRF-Token': csrfToken } }); if (r.ok) { toast('✅ Restored!'); await loadEntries(); playSound('success'); } } catch (e) { toast('⚠️ Error', 'error'); }
|
||||
async function restoreEntry(id, noToast) {
|
||||
try { const r = await fetch(API + '/entries/' + id + '/restore', { method: 'POST', headers: { 'Authorization': 'Bearer ' + token, 'X-CSRF-Token': csrfToken } }); if (r.ok) { if (!noToast) { toast('✅ Restored!'); await loadEntries(); playSound('success'); } } } catch (e) { if (!noToast) toast('⚠️ Error', 'error'); }
|
||||
}
|
||||
async function toggleFavorite(id) {
|
||||
try { await fetch(API + '/entries/' + id + '/favorite', { method: 'POST', headers: { 'Authorization': 'Bearer ' + token, 'X-CSRF-Token': csrfToken } }); const e = entries.find(x => x.id == id); if (e) e.favorite = e.favorite ? 0 : 1; renderFolders(); render(); playSound('click'); } catch (e) {}
|
||||
@@ -1066,8 +1066,12 @@ function hideBatchBar() {
|
||||
|
||||
async function batchDelete() {
|
||||
if (!confirm(`Move ${selectedIds.size} entries to trash?`)) return;
|
||||
for (const id of selectedIds) await delEntry(id);
|
||||
const count = selectedIds.size;
|
||||
for (const id of selectedIds) await delEntry(id, true);
|
||||
toast('📦 Moved ' + count + ' entries to trash');
|
||||
playSound('delete');
|
||||
clearSelection();
|
||||
await loadEntries();
|
||||
}
|
||||
|
||||
async function batchPermanentDelete() {
|
||||
@@ -1077,8 +1081,12 @@ async function batchPermanentDelete() {
|
||||
}
|
||||
|
||||
async function batchRestore() {
|
||||
for (const id of selectedIds) await restoreEntry(id);
|
||||
const count = selectedIds.size;
|
||||
for (const id of selectedIds) await restoreEntry(id, true);
|
||||
toast('✅ Restored ' + count + ' entries');
|
||||
playSound('success');
|
||||
clearSelection();
|
||||
await loadEntries();
|
||||
}
|
||||
|
||||
async function batchMove() {
|
||||
@@ -1127,11 +1135,11 @@ async function addEntry() {
|
||||
} catch (e) { toast('⚠️ Error', 'error'); }
|
||||
finally { btn.disabled = false; }
|
||||
}
|
||||
async function delEntry(id) {
|
||||
async function delEntry(id, noToast) {
|
||||
try {
|
||||
const r = await fetch(API + '/entries/' + id, { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + token, 'X-CSRF-Token': csrfToken } });
|
||||
if (r.ok) { selectedIds.delete(id); order = order.filter(x => x != id); localStorage.setItem('entryOrder', JSON.stringify(order)); toast('📦 Moved to trash'); await loadEntries(); playSound('delete'); }
|
||||
} catch (e) { toast('Error', 'error'); }
|
||||
if (r.ok) { selectedIds.delete(id); order = order.filter(x => x != id); localStorage.setItem('entryOrder', JSON.stringify(order)); if (!noToast) { toast('📦 Moved to trash'); await loadEntries(); playSound('delete'); } }
|
||||
} catch (e) { if (!noToast) toast('Error', 'error'); }
|
||||
}
|
||||
|
||||
// ==================== UTILS ====================
|
||||
@@ -1185,7 +1193,7 @@ function highlightText(text, query) {
|
||||
function showShortcutsHelp() {
|
||||
const overlay = document.createElement('div');
|
||||
overlay.className = 'custom-modal-overlay show';
|
||||
overlay.innerHTML = `<div class="custom-modal" style="min-width:380px"><h3>⌨️ Keyboard Shortcuts</h3><div style="display:grid;grid-template-columns:auto 1fr;gap:0.5rem 1.2rem;font-size:0.85rem;margin-bottom:1rem"><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+N</span><span>New entry</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+F</span><span>Search</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+T</span><span>Toggle trash</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+L</span><span>Lock vault</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+S</span><span>Save entry</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Esc</span><span>Close modal / deselect</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">◀ ▶</span><span>Detail view nav</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">?</span><span>Show this help</span></div><p style="color:var(--text2);font-size:0.8rem;margin-bottom:0.8rem">💡 Click any entry to select, Shift+click for range, Ctrl+click to toggle</p><div class="modal-actions"><button class="btn btn-sm" onclick="this.closest('.custom-modal-overlay').remove()">Got it</button></div></div>`;
|
||||
overlay.innerHTML = `<div class="custom-modal" style="min-width:380px"><h3>⌨️ Keyboard Shortcuts</h3><div style="display:grid;grid-template-columns:auto 1fr;gap:0.5rem 1.2rem;font-size:0.85rem;margin-bottom:1rem"><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+N</span><span>New entry</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+A</span><span>Select all</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+F</span><span>Search</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+T</span><span>Toggle trash</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+L</span><span>Lock vault</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Ctrl+S</span><span>Save entry</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">Esc</span><span>Close modal / deselect</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">◀ ▶</span><span>Detail view nav</span><span style="background:var(--input);padding:0.15rem 0.6rem;border-radius:0.4rem;font-family:monospace;text-align:center">?</span><span>Show this help</span></div><p style="color:var(--text2);font-size:0.8rem;margin-bottom:0.8rem">💡 Click any entry to select, Shift+click for range, Ctrl+click to toggle</p><div class="modal-actions"><button class="btn btn-sm" onclick="this.closest('.custom-modal-overlay').remove()">Got it</button></div></div>`;
|
||||
document.body.appendChild(overlay);
|
||||
overlay.addEventListener('click', e => { if (e.target === overlay) overlay.remove(); });
|
||||
}
|
||||
@@ -1352,7 +1360,7 @@ document.addEventListener('keydown', function(e) {
|
||||
|
||||
// Prevent browser defaults for ALL our shortcuts BEFORE dispatching
|
||||
const code = e.code;
|
||||
if (code === 'KeyN' || code === 'KeyF' || code === 'KeyT' || code === 'KeyL' || code === 'KeyS') {
|
||||
if (code === 'KeyN' || code === 'KeyF' || code === 'KeyT' || code === 'KeyL' || code === 'KeyS' || code === 'KeyA') {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
@@ -1368,5 +1376,12 @@ document.addEventListener('keydown', function(e) {
|
||||
} else if (code === 'KeyS') {
|
||||
if (document.getElementById('addModal').classList.contains('show')) addEntry();
|
||||
else if (document.getElementById('editModal').classList.contains('show')) saveEdit();
|
||||
} else if (code === 'KeyA') {
|
||||
if (!isInput && !document.getElementById('authSection').classList.contains('hidden')) {
|
||||
getFilteredEntries(view === 'grouped' || view === 'detail').forEach(e => selectedIds.add(e.id));
|
||||
updateBatchBar();
|
||||
render();
|
||||
playSound('click');
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user