Skip to content

UAT round: hymnal bar, read gates, plan chip + pause, viz grouping, portrait weave map (v0.49.0) - #26

Merged
glendonjklassen merged 5 commits into
mainfrom
hymnal-bar-and-read-tracking
Aug 13, 2026
Merged

UAT round: hymnal bar, read gates, plan chip + pause, viz grouping, portrait weave map (v0.49.0)#26
glendonjklassen merged 5 commits into
mainfrom
hymnal-bar-and-read-tracking

Conversation

@glendonjklassen

Copy link
Copy Markdown
Owner

Reader & reading map

  • Destinations no longer wear the reader's passage — the header subtitle hides off the Read screen (the Hymnal was advertising the current chapter top-left).
  • Reading tracked only on the Read tab — Android now also suspends the tracker under Present and the full-screen map overlays (web already gated these).
  • Completion needs the bottom of the chapter — a pass completes at 85% dwell and the last verse reached. The 85% snap stays what it was meant to be: a tolerance on the clock, not on the chapter. Core test + mutation-checked.
  • Overscroll is a phone affordance — web keeps it under the 700px breakpoint; both shells now stop at the last line (its top at the pane's top), so overscroll can never leave a text-free screen.

Plans

  • The chip stands down the day a day's worth is read — finishing a plan-day today (even yesterday's leftovers) retires the nav-strip chip until tomorrow (plan::done_today, doneToday on the wire, dated by the chapters' last_read). The navigator's today card still shows where the plan stands.
  • Pause / resumepaused in the plan file (additive), new plan_set_paused ABI 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.
  • New e2e: chip retirement on a completed day (mutation-tested against the filter), pause → nothing asked → resume.

Study hub

  • One ≡ — above 700px the ScreenBar's menu hides where the app header (with its own ≡) is still visible; on a phone it remains the only way to Settings.
  • Visualizations — Constellation and Weave map fold under one expanding card in both shells (two views of one thing, not two more tools).

Maps & boot

  • Portrait flips the weave map (both shells): canon axis down the left edge (Genesis at top), ribbons bulge right, taps map y→book. Landscape is unchanged, one rotation transform, so the orientations can't drift.
  • Canon strip boot polish — the strip carries its own background (--stripBg) from the first frame; the minimap detail fades in instead of popping onto a differently-coloured bar.

Housekeeping

  • README rearrange + new themeable.png screenshot (maintainer's), replaced reader-weaves.png.
  • Version → 0.49.0 (workspace + web), FEATURE-MANIFEST updated (plans ABI now 6 fns, completion gate, viz grouping, portrait map).

Verification

  • Full portable-crate battery, rnd featureless + featured, FFI binding-drift check — green.
  • wasm rebuilt and packed before the web suite (per the stale-engine rule); pack:data re-staged.
  • Targeted Playwright: plans-today, maps, reading, hymnal, navbar, text-scale, touch-targets, destinations — green (one known-racy reading test passed solo/first-run).
  • Android compileDebugKotlin + JVM unit tests — green.

🤖 Generated with Claude Code

…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)
- 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)
@glendonjklassen
glendonjklassen merged commit 4b9b47b into main Aug 13, 2026
8 checks passed
@glendonjklassen
glendonjklassen deleted the hymnal-bar-and-read-tracking branch August 13, 2026 17:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant