Autosave the board and restore it at the next start - #123
Merged
Merged
Conversation
Closes #121. The board is copied into a session slot every thirty seconds and again on the way out, and the next start brings it back. Nothing on this path writes to the .wboard the person named. Knowing whether the board has changed came first, since all three parts need it and nothing in the application could answer it: ConfirmDiscardUnsaved stood in by asking whether the board was empty, so it nagged right after a save and stayed silent when everything had been erased. The command history now carries a save point, so undoing back to what was saved stops counting as a change and undoing past it starts counting again; the handful of places that change the document without a command set a flag instead. LiveView sets neither, so a frame arriving on its own cannot raise the question. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Closes #122, and reworks the unsaved-changes question so each answer carries its own consequence. Opening a board now asks the slots whether anything newer is waiting for it. Without this the moment somebody most wants their recovered work - opening the very board they lost - is the moment the application says nothing, because the offer only appeared at startup and only for the newest slot. Every route in goes through OpenPathAsync, so the Open dialog, a drop and a double-click in Explorer are all covered once. The exit question was four buttons explained in two paragraphs of prose, which made the reader map sentences onto buttons before they could act. It is now four rows, each with its own one-line consequence, and no prose at all. The LiveView line appears only on a board that has a LiveView container, so the common case does not carry a sentence about a feature nobody in it is using. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #121. Closes #122.
The board is copied into a session slot every thirty seconds and again on the way out, and
the next start brings it back. Nothing on this path writes to the
.wboardthe personnamed — that file changes when they ask for it to change, and every call below follows
from it. The reasoning is decision 30 in
docs/decisions.md.Knowing whether the board has changed came first
All three parts of #121 need it, and the application could not answer it.
ConfirmDiscardUnsavedstood in by asking whether the board was empty, so it nagged rightafter a save and said nothing when everything had just been erased.
It is two signals, because one cannot cover it:
CommandHistorycarries a save point — the command on top of the undo stack when thefile was written. Undoing back to what was saved stops counting as a change; undoing
past it starts counting again. A counter cannot express that, since undo moves it the
same way drawing does.
audit: a
.wimportopened as a new board, which clears the history around content no fileholds. The LiveView paths deliberately set neither signal, so a frame arriving on its own
cannot put an unasked question in front of someone who left the application running beside
a feed.
The window title now shows the board and an asterisk, so the question asked on the way out
has something on screen explaining it.
The exit question
Four answers, each a row carrying its own one-line consequence: Save, Keep for next time,
Discard changes, Cancel. There is no prose above them — an earlier draft explained the four
in two paragraphs, which made the reader map sentences onto buttons before they could act.
The LiveView line appears only on a board that has a LiveView container.
Keep is
IsDefault, which decision 24 refused for the mouse mode offer. The difference isthat there both answers changed something, so neither could be primed; here Keep decides
nothing — the file is untouched and the board returns — so Enter landing on it is never the
wrong outcome. Decision 30 records this so it does not read as an oversight to be tidied up.
Cancel stays, and LiveView is the reason. Keep and Cancel look interchangeable, but a
restored LiveView container comes back as its last frame and has to be reconnected by hand.
Cancel is the only answer that keeps a feed live — which matters most in the case where the
window gets closed by accident, mid-recording. The camera position is carried in the session
to narrow what is left of the gap.
One slot per running copy
Each copy takes a slot named by a GUID and holds a lock file open while it runs, so two
windows never write to the same files. Forbidding a second window was considered and
rejected: two boards side by side is a real thing to want. A slot whose lock can be taken
belonged to a copy that has gone, and its sidecar says whether it went on purpose — which is
what separates a silent restore from an offer of recovery.
Declining a recovery discards that slot, and the question says so. The alternative is asking
the same person the same thing at every start for thirty days.
Opening a board asks the slots too (#122)
The startup offer only covers the newest slot, so without this the moment somebody most wants
their recovered work — opening the very board they lost — is the moment the application says
nothing. Every route into a board goes through
OpenPathAsync, so the Open dialog, a drop,and a double-click in Explorer are covered once rather than three times. Yes takes the
changes, No opens the saved file and discards them, Cancel opens neither and keeps the slot.
Checks
dotnet build Whiteboard.sln -c Releaseclean, both smoke harnesses pass. The Core harnesscovers the save point through the cases that actually come up — save, undo, redo, undo back
onto the point, a different action at the same depth — plus the snapshot autosave writes, the
sidecar round-trip and what it does with damaged input, and the clamping on a restored camera.
Also walked through the built application rather than trusting the tests:
Untitled board *, thecamera where the sidecar put it, the slot re-homed into this copy's own before the old one
was released, and the sidecar flipping to
exitedCleanlyon the way out.file. Opening the file offered the changes; answering Yes gave
demo.wboard *in the titleand a board of five strokes, while the file on disk still held one. Killing the process
then left a slot that correctly read as a crash.
Prunenow sweepsorphans.
VersionPrefixmoves to 1.5.0 with the matchingCHANGELOG.mdsection, andsite/guide.htmlgets one paragraph.
🤖 Generated with Claude Code