UAT round: hymnal bar, read gates, plan chip + pause, viz grouping, portrait weave map (v0.49.0) - #26
Merged
Merged
Conversation
…ortrait weave map (v0.49.0)
Reader & reading map:
- A destination no longer wears the reader's passage: the header subtitle
hides off the Read screen (the Hymnal advertised "1 Corinthians 7").
- Reading is tracked only with the text in front of the reader: Android now
also gates on Present and the map overlays (web already did).
- A chapter completes at 85% dwell AND the last verse reached — the snap is a
tolerance on the clock, not permission to skip the end of the chapter.
- Overscroll (last line to the top of the pane) is a phone affordance: web
keeps it under the 700px breakpoint and stops it AT the last line, so the
text can never slide off entirely; Android same stop, all its modes.
Plans (web UI; core+ABI shared):
- The nav-strip chip retires for the rest of the day once a full plan-day
finishes today — even when it was yesterday's leftovers (plan::done_today,
doneToday on the plans wire, dated by the chapters' last_read).
- Plans pause and resume (paused in the plan file, additive; new
plan_set_paused ABI fn): a paused plan keeps its progress and class but
asks nothing — no chip, no today card — and its card reads name + start
day ("Started 3 Aug 2026 · paused").
Study hub:
- One ≡ above 700px: the ScreenBar's menu hides where the app header (with
its own ≡) is still visible — two stacked menus in different colours.
- Constellation and Weave map fold under one expanding Visualizations card
(both shells) — two views of one thing, not two more tools.
Maps & boot:
- The weave map flips in a portrait viewport (both shells): canon axis down
the left edge, ribbons bulging right, taps mapped y→book.
- The canon strip carries its own background from the first frame and fades
its detail in — no more differently-coloured bar the minimap pops onto.
Also: README rearrange + the themeable screenshot (maintainer), version to
0.49.0, FEATURE-MANIFEST updates, EN+DE strings, bindings regenerated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Notes card copy (pick C): "Browse every note you've left in the text."
("search" trimmed — the notes browser has no search field yet, and the
card must not promise one.) EN + DE.
- Darcula retired as a near-duplicate of One Dark. Both parses ALIAS the
stored token to one-dark, so an existing config opens on its nearest
neighbour instead of snapping to System. Pinned by test.
- Four house themes, none of them editor ports, all clearing the same
WCAG-AA contrast test as the rest (18 themes now):
scriptorium — parchment, iron-gall ink, RUBRICATED accents (light)
blueprint — cyanotype: Prussian blue, chalk ink, gold divine name
phosphor — green CRT with the classic amber second phosphor
high-contrast — pure black on white, the deliberate low-vision option
- Atkinson Hyperlegible (Braille Institute, OFL) as the fifth face, both
shells, optical scale 0.90 (x-height 0.496, same half-correction as the
others). It is the one STATIC family, so Font::static_bold enters the
vocabulary: the web declares each face at its single weight (a static 400
declared 400-700 paints bold text regular), keeps the 700s out of the
engine worker's measurement list, and precaches them via the new
FONT_ALL_FILES; Android's FontSpec carries bold/boldItalic asset paths.
Whole family: 87 KB woff2.
- BIBLIOGRAPHY credits all five faces; FEATURE-MANIFEST updated.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
…n a verse Three asks, and the first two are NOT the same kind of thing — which is most of the work here: - VERSE NUMBERS OFF is a LAYOUT input (`LayoutConfig.verse_numbers`, and +4 bytes on the by-value `PlumblineLayoutConfig`). A shell that merely declined to paint them would flow every verse around an invisible marker: the number's box AND the gap after it belong to the line. So the core emits no number items and reclaims the width, and the field joins both turn-cache keys (`engine.worker.ts`, Android's `ChapterKey`) while staying out of `font_identity` — like `verse_break`, it moves boxes, never a glyph's advance. The web hand-marshals the struct, so its size moved 28 → 32 in lockstep. - SUPPLIED-WORD ITALICS OFF is PAINT ONLY. The measure callback is font-blind, so the engine already measures those words upright and the layout is untouched: deliberately absent from both cache keys, present in Android's ChapterPaintKey (the Picture bakes the face) and named as an explicit dependency of the web's paint effect. That last one was a real bug the new e2e caught: `draw` runs in a rAF callback, outside the effect's tracking scope, so reading the flag down there registered nothing and the italics stayed on screen until something else happened to repaint. - A VERSE NOW NAMES THE WEAVES IT IS IN, above the partner list and separate from it. The two answer different questions and the partner list buries the first: a verse with six links into one weave read as six rows repeating a name, and a verse in three weaves gave no way to see the three at all. Both switches default ON and are written as explicit booleans, so every read is `!== false` — an absent key is a config from before they existed, not an opt-out. Tests, each mutation-tested against the defect it describes: - core: numbers off emits no boxes AND reclaims their width (the mutation that keeps the gap moves the first word to x=4, and the test fails); - core: membership dedupes by name across an interleaved partner list, is singular at one and absent at none; - web e2e: both switches driven through Settings › Advanced, asserting the display list for numbers and the CANVAS PIXELS for italics — dropping the paint dependency or the cache-key field each kills exactly its own test. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
… bar The hub was eight identical rectangles of FIXED text — the same on install day as after a year of study. Plans tells you today's chapters; the Hymnal is full of hymns; this screen had nothing that could change, which is what "a bunch of boring brown cards, not like the other pages" was describing. Informative first, per the ask: - an IN PROGRESS band, drawing only rows that have something to say (a hub reading "0 due · 0 to review" every day would be the fixed text again): the running plan with today's chapters, the memorize queue when anything is due, the review queue when anything waits. Nothing running at all gets one invitation rather than an empty box, and a PAUSED plan says so and names no chapters — promising chapters it is not asking for reads as asking for them. - a count on every card that holds a collection, absent at zero so an empty tool reads as quiet rather than as a score of nought. Plans and Memorize carry none: they are activities, and the band speaks for them. Visual, as the bonus and where it costs nothing: the reading map as one number and one bar — chapters read of 1,189, the map's own readDone over a faint readUnread track, so it is correct in all eighteen themes for free and taps through to the navigator. The first cut used the unread gold at 22% and an unread reader's empty bar looked FULL; it is 12% with a hairline now. No new engine calls: every number is a query another screen already makes, so the web reads them through the session cache and they move on an authoring write. That is the failure worth pinning — a count fetched once looks perfect until the reader writes something — so the e2e writes first and then looks, and the mutation that snapshots the counts instead of deriving them kills exactly that test and no other. Two traps this hit, both worth the note: the band first rendered as EXPLORE.INPROGRESS because the i18n catalogue lives in the ENGINE and only the bundle had been rebuilt; and the "quiet at zero" assertion first passed because `q` answers null before its fetch lands, which is indistinguishable from an empty tool — it now waits on the stock set's own weave count as the signal that the queries have resolved, and asserts a DELTA where the stock set seeds data. Android gets the same band and counts (plans stay web-only, per the manifest's shell deltas), refetching on the note epoch and on every entry to the hub. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.
Reader & reading map
Plans
plan::done_today,doneTodayon the wire, dated by the chapters'last_read). The navigator's today card still shows where the plan stands.pausedin the plan file (additive), newplan_set_pausedABI fn, bindings regenerated. A paused plan keeps its progress and class but asks nothing; its card reads plan name + start day ("Started 3 Aug 2026 · paused"), with Resume beside Stop. EN + DE strings.Study hub
Maps & boot
--stripBg) from the first frame; the minimap detail fades in instead of popping onto a differently-coloured bar.Housekeeping
themeable.pngscreenshot (maintainer's), replacedreader-weaves.png.Verification
pack:datare-staged.compileDebugKotlin+ JVM unit tests — green.🤖 Generated with Claude Code