diff --git a/js/app.js b/js/app.js index 75735c8..5d2b37c 100644 --- a/js/app.js +++ b/js/app.js @@ -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 = + '