Skip to content

SQLBI Whiteboard 1.5.0 (dev 3333)

Pre-release
Pre-release

Choose a tag to compare

@marcosqlbi marcosqlbi released this 11 Sep 12:08
af7f816
Autosave the board and restore it at the next start (#123)

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
`.wboard` the person
named** — 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.
`ConfirmDiscardUnsaved` stood in by asking whether the board was empty,
so it nagged right
after a save and said nothing when everything had just been erased.

It is two signals, because one cannot cover it:

- **`CommandHistory` carries a save point** — the command on top of the
undo stack when the
file 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.
- **A flag covers what never reaches a command.** In practice only one
caller survived the
audit: a `.wimport` opened as a new board, which clears the history
around content no file
holds. 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 is
that 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 Release` clean, both smoke harnesses
pass. The Core harness
covers 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:

- A crafted session slot restored on launch with the title reading
`Untitled board *`, the
camera 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 `exitedCleanly` on the way
out.
- For #122: a saved board holding one stroke, and a crashed slot holding
five for that same
file. Opening the file offered the changes; answering Yes gave
`demo.wboard *` in the title
and 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.
- One thing only that found: an empty lock file survived each launch, so
`Prune` now sweeps
  orphans.

`VersionPrefix` moves to 1.5.0 with the matching `CHANGELOG.md` section,
and `site/guide.html`
gets one paragraph.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>