|
Reported from use: a note created with only a title then saved left a db.json
entry with no file beside it, and reopening it said the file was missing.
Cause: FileView.setText("") on a path that view has not loaded creates no
file at all and reports no error. The index write (always non-empty JSON)
was fine, so only the body was lost, which is why it looked like a missing
file rather than a failed save. Bodies are now written by a Process running
cat > <file> with the text on stdin: verified against empty and non-empty
payloads, consecutive writes on one Process, and a store with no db.json at
all. The exit code is the real outcome, so a refused write reports it.
Second report in the same flow: the editor stays editable after the first
click, so typing more and then pressing Commit & push dropped the edit, the
push carrying only what the first click wrote. The second click now writes
the current title and body before it commits and pushes.
|
|
A review of the branch found four ways the page could report success for
work that never happened, all reachable in ordinary use.
Writes: setText is asynchronous unless blockWrites, and its
saved()/saveFailed() do not fire for every write (a second setText to the
same path loses the signal, which stranded the callback), so a save was
reported before it landed and a failed db.json or body write was never
seen. Both views now block and carry the outcome, so writeDb and writeBody
know the result when they return; a failed create therefore leaves no index
entry. The create path also loads the body before the index, so a failed
body write cannot leave an entry with no text.
Commits: the sync chain swallowed every commit failure with '|| true', so a
failing pre-commit hook or a signing failure pushed an unchanged HEAD and
reported success. It now stages, commits only when something is staged, and
lets 'set -e' fail the chain, with stderr folded in for the whole chain
rather than just the push.
Duplicate notes: the 'awaiting commit' state lived only in a 3 second
timer, so a slower second click re-entered create() and appended a second
note. It is now a page property that outlives the timer, and the button
follows it.
Preview: the shared Switch writes checked itself, dropping the binding, so
the switch stopped following page.preview; resynced on change, the way
StatusRow.qml does.
Also validates a note's file name as digits before read, write or rm, and
clears the index error once the index reads again.
|