From d423ec2646d444523fd44c92864988445cf072d2 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 16 Oct 2026 20:59:09 +0200 Subject: notes: delete asks before it destroys The confirm was on the second click, after the first had already removed the file and the entry, so the 'Confirm?' label promised a check that had already happened and one stray click lost the note. The first click now only arms the button; the second removes and pushes the removal. --- desktop/modules/notes/NotesPage.qml | 36 ++++++++++++++++++++++-------------- desktop/modules/notes/README.md | 5 +++-- 2 files changed, 25 insertions(+), 16 deletions(-) (limited to 'desktop/modules/notes') diff --git a/desktop/modules/notes/NotesPage.qml b/desktop/modules/notes/NotesPage.qml index 88382fc..585fcfb 100644 --- a/desktop/modules/notes/NotesPage.qml +++ b/desktop/modules/notes/NotesPage.qml @@ -37,10 +37,13 @@ Item { property string bodyError: "" // A write or git command is in flight; the buttons stand down meanwhile. property bool busy: false - // "create" | "edit" | "delete" once that write has landed and the commit - // and push are still owed. It outlives any timer, so a click after a pause - // pushes the note that was already written instead of writing it again. + // "create" | "edit" once that write has landed and the commit and push are + // still owed. It outlives any timer, so a click after a pause pushes the + // note that was already written instead of writing it again. property string awaiting: "" + // Delete is confirmed before anything is destroyed: the first click only + // arms the button, the second removes and pushes. + property bool confirmDelete: false // The shared Switch writes `checked` itself, which drops the binding // above; StatusRow.qml documents the same and resyncs the same way. @@ -50,6 +53,7 @@ Item { page.bodyError = ""; page.preview = note !== null; page.awaiting = ""; + page.confirmDelete = false; titleField.text = note ? note.title : ""; // Clear before the assignment below: that assignment is what retargets // the body FileView, and its load may land synchronously, so clearing @@ -62,6 +66,7 @@ Item { function toList() { page.awaiting = ""; + page.confirmDelete = false; page.busy = false; page.editing = null; page.bodyError = ""; @@ -98,22 +103,24 @@ Item { function remove() { if (page.busy || page.editing === null) return; const id = page.editing.id; - if (page.awaiting === "delete") { - page.busy = true; - page.owner.commitPush("delete", id, (ok, msg) => { - page.busy = false; - if (!ok) { page.owner.lastError = msg; return; } - page.toList(); - }); - return; - } + // Nothing is destroyed until the second click: a note lost to one + // stray click is only recoverable out of git history by hand. + if (!page.confirmDelete) { page.confirmDelete = true; return; } + page.confirmDelete = false; page.owner.lastError = ""; page.busy = true; page.owner.remove(id, (ok, msg) => { page.busy = false; if (!ok) { page.owner.lastError = msg; return; } if (!page.owner.gitEnabled) { page.toList(); return; } - page.awaiting = "delete"; + // The removal is confirmed, so the push follows it rather than + // asking for a third click. + page.busy = true; + page.owner.commitPush("delete", id, (ok2, msg2) => { + page.busy = false; + if (!ok2) page.owner.lastError = msg2; + page.toList(); + }); }); } @@ -290,7 +297,8 @@ Item { visible: page.editing !== null danger: true enabled: !page.busy - text: page.awaiting === "delete" ? "Confirm?" : "Delete" + text: page.busy ? "Deleting…" + : page.confirmDelete ? "Confirm?" : "Delete" onClicked: page.remove() } diff --git a/desktop/modules/notes/README.md b/desktop/modules/notes/README.md index 8efd7bc..0f642b8 100644 --- a/desktop/modules/notes/README.md +++ b/desktop/modules/notes/README.md @@ -14,8 +14,9 @@ per note, named by its creation time in epoch seconds. lists, links, inline code and quotes render; tables and fenced-code highlighting do not. - **Save** is two clicks: the first writes the note, the second reads - **Commit & push?** and pushes it. **Delete** is two clicks the same way. - With git off there is no second half, so Save writes and returns in one. + **Commit & push?** and pushes it. **Delete** asks first, then removes the + note and pushes the removal. With git off there is no second half, so Save + writes and returns in one. - Leaving the editor with **Cancel**, the back arrow, Escape or a click outside drops unsaved text. The save is the explicit act. - **Update list** runs `git pull` and stamps `git.lastpull`. -- cgit v1.2.3