Files
bookshelf/app/app
Spriteandclaude 356f639cdd Fix six on-device issues found in the first real phone test
The cover one is the interesting bug. BookCover branched on
`painter.state`, but in coil3 that is a StateFlow<State>, not a State —
so every `is AsyncImagePainter.State.X` arm was always false. A `when`
used as a statement needs no else, so it compiled clean and drew
NOTHING: no cover, no placeholder, no error icon. That is why a
successfully looked-up book showed as a bare title floating in space.
Collect the flow before matching on it.

Two more cover defects sat behind that one:
- OpenLibraryDtos synthesized covers.openlibrary.org/b/isbn/{isbn}-L.jpg
  unconditionally. For an edition with no art that URL answers 200 with a
  43-byte 1x1 transparent GIF (verified against the live service), which
  an image loader calls a successful load. So even with the state bug
  fixed it would have painted an invisible cover and never fallen back.
  Now the URL comes from OL's own `cover` object, which is present only
  when art actually exists.
- Because that URL was never blank, MetadataMerger's "fill blanks from
  the other source" rule could never reach Google Books' thumbnail. With
  OL reporting null, the fallback works, and MetadataRepository adds the
  by-ISBN URL as a genuine last resort — with `default=false`, so a miss
  is a 404 the loader can report instead of a blank image.

The placeholder itself is now drawn in every non-success state (loading
included, where it previously drew an empty box) and reads as a book:
mahogany spine strip, gold hairline, letterpress panel.

Also:
- SyncStatusBar owns its navigation-bar inset and takes wider horizontal
  padding, so it clears a phone's rounded display corners; it moves into
  Scaffold's bottomBar slot so its height reaches the content padding.
- SetupScreen takes safeDrawingPadding outside verticalScroll, so the IME
  shrinks the viewport instead of covering Password, plus Next/Next/Done
  IME actions.
- Library card titles drop to a 20sp line height with the author given
  its own 4dp gap: at titleSmall's 24sp leading a wrapped title left the
  author closer to the last title line than the title lines were to each
  other, so the byline read as part of the title.
- The scan sheet now names the ISBN it just read and says "Searching…",
  so a decoded barcode is legible as decoded and the user can lower the
  book instead of holding it to the camera at a bare spinner.

assembleDebug + assembleRelease exit 0; 106 unit tests, 0 failures;
verifyPaparazziDebug green against re-recorded snapshots.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CDcPottghJXEvfYKqFM7zf
2026-09-09 09:55:53 +00:00
..