test #16

Merged
brian merged 3 commits from test into main 2026-08-11 06:54:22 +00:00
Owner
No description provided.
Rotating went back to the home screen. The route lived in a plain remember,
and Android's default is to destroy and recreate the activity on a
configuration change, so the composition restarted at Route.Home.

The reset was the visible half. Recreation also tore down the ink surfaces
being written on and cancelled rememberCoroutineScope, which owns the 400ms
debounced save of a typed document — a rotation a moment after a keystroke
took the sentence with it. So MainActivity now declares the rotation and
resize configuration changes and handles them itself. Compose reads the
configuration through LocalConfiguration and recomposes, so the layout still
adapts: the permanent sidebar still appears past 840dp, and both ink views
already handled onSizeChanged. uiMode and the rest are deliberately absent.

The route is also rememberSaveable now, against the rebuilds configChanges
can't cover — the process being reclaimed in the background. RouteSaver
flattens it to Bundle primitives, carrying the notebook field by field so a
restored route draws without a database round trip mid-launch, and falling
back to Home on a shape this build no longer parses rather than crashing the
launch it is restoring.

The toolbar goes with it: reaching for the eraser again after every
interruption is the sort of friction that makes a tablet feel unlike paper.
The tool is saved by name, since a Bundle only takes an enum as a Java
Serializable.

The zoom deliberately doesn't survive. Now that the view isn't recreated it
was carrying its transform across, and a pan is in view pixels while a zoom
is relative to a fit taken from the width — at a new width the page came
back scrolled to a corner that had moved, with nothing re-clamping it, since
only setZoom does that. A width change resets to the fitted view. Only a
width change: the sheet also grows in height as a document gets longer, and
losing the zoom every few lines while writing would be its own bug.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fix(web): the sync stopped pushing anything at all
All checks were successful
Build and Deploy / test (push) Successful in 28s
Build and Deploy / build (push) Successful in 11s
Build and Deploy / deploy-main (push) Has been skipped
Build and Deploy / deploy (push) Successful in 14s
15f4621156
flush() iterated notebooks and then reached for `m`. The memories rewrite in
48ca560 overwrote the body of the notebook loop with the body of the memory
loop, and took the page upsert, the page delete and the notebook delete with
it. Nothing in the function bound `m` or `memories`.

So every notebook push threw a ReferenceError, swallowed by the per-record
retry wrapper as "sync push failed (will retry)". The memories-delete loop at
the end threw outside that wrapper, which rejected flush() — and sync() awaits
flush() before pull(), so the pull never ran either. The web client had been
silently offline in both directions since 48ca560: local edits stayed in
IndexedDB, and nothing from another device arrived.

Nothing was lost. The records were still there with _dirty set, so the first
sync after this lands pushes the backlog.

Restored the four loops and gave the memory push back its own function. The
bodies send the whole record: both upsert routes replace the fields they are
given and default the rest, so the old "only send changed fields" shape would
have blanked a journal's type and icon on any push that omitted them.

sync-push.test.mjs pins it, in the style of memory-shape.test.mjs — it reads
the shipped source and insists each store still reaches the server and that
each loop only touches the records its own function loaded. It fails 16 checks
against the commit before this one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
feat: writing defaults — paper, pen and typed text, per account and per notebook
All checks were successful
Build and Deploy / build (push) Successful in 11s
Build and Deploy / deploy-main (push) Has been skipped
Build and Deploy / test (push) Successful in 28s
Build and Deploy / deploy (push) Successful in 13s
34f94f690e
How a new page starts out is now a preference rather than a constant: its
ruling and sheet size, the pen's colour and thickness, and the font, size and
colour of typed text.

Two levels. The account carries a set; any journal or notebook overrides any
part of it. Overrides are stored sparse and null means *inherit*, not "unset"
— a sketchbook that takes graph paper still follows the account for the pen,
including later changes to it, rather than being frozen at whatever the
account said the day the override was made. That distinction is the whole
design, and it is what the tests on all three clients are mostly about.

One JSON object per row rather than a column per preference, so the next
preference needs no migration on the server, in IndexedDB or in Room — the
same reasoning that keeps PAGE_TYPES a tuple of strings instead of a database
enum. Postgres gets writing_defaults JSONB on users and notebooks (idempotent
ADD COLUMN, as the others), Room gets a nullable TEXT column at version 6.

Values are canonical, not one client's spelling. The font is "sans" and not a
CSS stack, because Android takes a single family and would fall back to its
default on anything else. "auto" is a value and not an absence in two places:
the sheet follows the screen, and typed text follows the theme's ink — a
notebook could never hand the colour back to the theme if that were null.

Graph paper has no compact twin (PageType.swapSize has said so for a while),
so a compact graph default stays a full sheet rather than naming a type
nothing renders.

The server applies the resolved defaults itself when a client creates a page
without naming a type. It has no screen, so it reads "auto" as the full sheet;
a client that knows its own width still decides for itself.

Backups carry a notebook's overrides, validated through the same schema on the
way back in — a backup file is editable by hand, and a colour the renderers
can't parse would otherwise be stored and only fail later, on the page.

Also wires the two new frontend test files into CI, which ran only
memory-shape.test.mjs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
brian merged commit 67745037c3 into main 2026-08-11 06:54:22 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
brian/Journal!16
No description provided.