Replace standard confirm() with custom centered confirm dialog
Add showCenterConfirm() function for dialogs without button anchor. Replaced all standard confirm() calls in batchDelete, batchPermanentDelete, permanentDelete, emptyTrash. Batch permanent delete shows single custom confirm with entry count, no nested dialogs. permanentDelete() accepts silent param to suppress UI for batch operations. Order cleanup added to permanentDelete.
This commit is contained in:
@@ -300,13 +300,17 @@ async function restoreEntry(id, noToast) {
|
||||
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) {}
|
||||
}
|
||||
async function permanentDelete(id) {
|
||||
if (!confirm('Permanently delete?')) return;
|
||||
try { const r = await fetch(API + '/entries/' + id + '?permanent=1', { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + token, 'X-CSRF-Token': csrfToken } }); if (r.ok) { toast('🗑️ Permanently deleted'); await loadEntries(); playSound('error'); } } catch (e) { toast('⚠️ Error', 'error'); }
|
||||
async function permanentDelete(id, silent) {
|
||||
const doDelete = async () => {
|
||||
try { const r = await fetch(API + '/entries/' + id + '?permanent=1', { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + token, 'X-CSRF-Token': csrfToken } }); if (r.ok) { order = order.filter(x => x != id); localStorage.setItem('entryOrder', JSON.stringify(order)); if (!silent) { toast('🗑️ Permanently deleted'); await loadEntries(); playSound('error'); } } } catch (e) { if (!silent) toast('⚠️ Error', 'error'); }
|
||||
};
|
||||
if (silent) { await doDelete(); return; }
|
||||
showCenterConfirm('Permanently delete?', doDelete);
|
||||
}
|
||||
async function emptyTrash() {
|
||||
if (!confirm('Delete ALL trashed entries?')) return;
|
||||
try { const r = await fetch(API + '/entries/trash/empty', { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + token, 'X-CSRF-Token': csrfToken } }); if (r.ok) { toast('🗑️ Trash emptied'); await loadEntries(); playSound('error'); } } catch (e) { toast('⚠️ Error', 'error'); }
|
||||
showCenterConfirm('Delete ALL trashed entries?', async () => {
|
||||
try { const r = await fetch(API + '/entries/trash/empty', { method: 'DELETE', headers: { 'Authorization': 'Bearer ' + token, 'X-CSRF-Token': csrfToken } }); if (r.ok) { toast('🗑️ Trash emptied'); await loadEntries(); playSound('error'); } } catch (e) { toast('⚠️ Error', 'error'); }
|
||||
});
|
||||
}
|
||||
function timeAgo(dateStr) {
|
||||
if (!dateStr) return '';
|
||||
@@ -937,6 +941,36 @@ function showConfirm(btn, message, callback) {
|
||||
}, 10);
|
||||
}
|
||||
function entryPw(id) { const e = entries.find(x => x.id == id); return e ? e.password : ''; }
|
||||
function showCenterConfirm(message, callback) {
|
||||
const existing = document.querySelector('.custom-confirm');
|
||||
if (existing) existing.remove();
|
||||
const confirm = document.createElement('div');
|
||||
confirm.className = 'custom-confirm show';
|
||||
confirm.style.cssText = 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10000;';
|
||||
confirm.innerHTML =
|
||||
'<div class="confirm-text">' + message + '</div>' +
|
||||
'<div class="confirm-btns">' +
|
||||
'<button class="confirm-yes">Yes</button>' +
|
||||
'<button class="confirm-no">No</button>' +
|
||||
'</div>';
|
||||
document.body.appendChild(confirm);
|
||||
const yesBtn = confirm.querySelector('.confirm-yes');
|
||||
const noBtn = confirm.querySelector('.confirm-no');
|
||||
const cleanup = () => { confirm.remove(); document.removeEventListener('keydown', keyHandler); };
|
||||
const keyHandler = (e) => {
|
||||
if (e.key === 'Enter' || e.key === 'y' || e.key === 'Y') { e.preventDefault(); cleanup(); callback(); playSound('delete'); }
|
||||
else if (e.key === 'Escape' || e.key === 'n' || e.key === 'N') { e.preventDefault(); cleanup(); }
|
||||
};
|
||||
yesBtn.onclick = () => { cleanup(); callback(); playSound('delete'); };
|
||||
noBtn.onclick = () => cleanup();
|
||||
confirm.tabIndex = 0; confirm.focus();
|
||||
document.addEventListener('keydown', keyHandler);
|
||||
setTimeout(() => {
|
||||
document.addEventListener('click', function closeConfirm(e) {
|
||||
if (!confirm.contains(e.target)) { cleanup(); document.removeEventListener('click', closeConfirm); }
|
||||
});
|
||||
}, 10);
|
||||
}
|
||||
function attachEvents() {
|
||||
document.querySelectorAll('.delete-btn').forEach(b => b.onclick = function(ev) { ev.stopPropagation(); if (showTrash) { permanentDelete(this.dataset.id); } else { showConfirm(this, 'Delete this entry?', id => delEntry(id)); } });
|
||||
document.querySelectorAll('.edit-btn').forEach(b => b.onclick = function(ev) { ev.stopPropagation(); openEdit(this.dataset.id); });
|
||||
@@ -1066,19 +1100,25 @@ function hideBatchBar() {
|
||||
}
|
||||
|
||||
async function batchDelete() {
|
||||
if (!confirm(`Move ${selectedIds.size} entries to trash?`)) return;
|
||||
const count = selectedIds.size;
|
||||
for (const id of selectedIds) await delEntry(id, true);
|
||||
toast('📦 Moved ' + count + ' entries to trash');
|
||||
playSound('delete');
|
||||
clearSelection();
|
||||
await loadEntries();
|
||||
showCenterConfirm('Move ' + count + ' entries to trash?', async () => {
|
||||
for (const id of selectedIds) await delEntry(id, true);
|
||||
toast('📦 Moved ' + count + ' entries to trash');
|
||||
playSound('delete');
|
||||
clearSelection();
|
||||
await loadEntries();
|
||||
});
|
||||
}
|
||||
|
||||
async function batchPermanentDelete() {
|
||||
if (!confirm(`Permanently delete ${selectedIds.size} entries?`)) return;
|
||||
for (const id of selectedIds) await permanentDelete(id);
|
||||
clearSelection();
|
||||
const count = selectedIds.size;
|
||||
showCenterConfirm('Permanently delete ' + count + ' entries?', async () => {
|
||||
for (const id of selectedIds) await permanentDelete(id, true);
|
||||
toast('🗑️ Permanently deleted ' + count + ' entries');
|
||||
playSound('error');
|
||||
clearSelection();
|
||||
await loadEntries();
|
||||
});
|
||||
}
|
||||
|
||||
async function batchRestore() {
|
||||
|
||||
Reference in New Issue
Block a user