Reuse shared artwork and correct title focus edges

This commit is contained in:
justinzeus 2026-11-05 19:58:36 +01:00
parent 3bfb8cd779
commit a8951827ba
41 changed files with 581 additions and 438 deletions

View file

@ -59,8 +59,9 @@ cover the Wolfskin nav.
The independent `:wolfskin-design` module owns the shell components, fixed person
colours, focus policy, per-person root-view memory, palette and motion. Its
`tokens.json` is the copied approved TV-spec source, retaining the locked prototype
SHA and provenance. `shell-tokens.json` adds shell and grid measurements from that
same prototype. Generate the committed Kotlin, CSS and checksum manifest together:
SHA and provenance. `shell-tokens.json` adds shell and grid measurements;
`title-tokens.json` adds title, performer and playback-sheet measurements from
that same prototype. Generate the committed Kotlin, CSS and checksum manifest together:
```sh
python3 wolfskin-design/generate_tokens.py
@ -149,8 +150,10 @@ Home/Discover shelves open a full list through
The optional suspend page provider returns `LibraryPage(items, hasMore)` using the
generated Conductarr client. The grid reads within ten cards of its end, deduplicates
title identities, and pauses on Try again or Show more rather than looping.
Title activation pushes the explicitly named `library-title/{id}` destination for
the title-screen implementation; this slice does not implement title pages.
Title activation opens `title/{id}` through `Destination.Wolfskin` for prototype
identities, or the existing typed media destination for real Jellyfin identities.
Movies, series, episodes and people use the native title family; collections and
music keep their upstream destinations.
`LibraryCaptureTest` renders the sixteen approved library/See all states offline.
`LibraryKeysTest` reads the approved JSON path and reaches Spirited Away in exactly
@ -158,6 +161,57 @@ the title-screen implementation; this slice does not implement title pages.
failure/retry, stale copies, and person/server isolation. Captures are written to
the same `build/wolfskin-captures/` directory as the shell captures.
## Title pages and people
`TitleSurface` owns the film/series/episode header, season chips, episode tiles,
cast and related shelves. `PersonSurface` owns the real biography and continuous
six-column filmography. Both reuse the shell/nav/back ladder, `LibraryPoster`,
the adaptive `LibraryRatingPlate`, shared captions and the single bounded
`LibraryImages` loader. Image requests use exact slot sizes, RGB565 for opaque
posters, no crossfade, four concurrent reads and next-row prefetch. The fixed
title backdrop remains visible behind deep rows; only off-screen row images
leave composition.
The options row preserves complete labels beyond the copy-column measure.
Version choices close after selection; Audio and subtitles stays open, including
an explicit Off choice. Real source IDs use the Jellyfin SDK UUID parser, and
stream indexes remain the server's indexes rather than positions in a list.
Selections persist through the same playback repository as the upstream player.
Marking a whole series asks first; an explicit episode remains the exact play and
watched target even while another season is selected. Nested person/title visits
retain their entry's focus and selection state.
Hardware and remote Back share the sheet/picker/request-overlay precedence, then
pop a pushed title/person from content **or** nav. Initial loading has no content
target: Down stays in nav, while Back can still leave the title. A missing rating
set emits no layout node, so it cannot reserve an invisible extra facts gap.
`TitleReadFacade` confines SDK reads, server/user-scoped last-good disk copies,
person credits and playback mutations to one boundary. Cached content appears
before refresh. Production ratings stay hidden until Conductarr sign-in exists.
Debug-only `wolfskin-titles.json` and local `wolfskin-titles/assets/` project the
locked household fixture, including portraits; release never packages them.
Those synthetic IDs are not invented Jellyfin playback IDs. Real held-title
playback uses the existing player; debug catalogue identities cannot play a file.
Held trailers use Jellyfin remote/local trailer data. YouTube URLs target an
installed YouTube handler such as SmartTube, never a browser. No handler leaves
the title visible with a calm message. Titles nobody holds have no Trailer
button until Conductarr's trailer field exists. Conductarr sign-in and request
submission/receipt workflows belong to their separate slices; title pages do not
pretend those operations succeeded or fall back to Seerr.
`TitleCaptureTest` writes the 34 approved title/person/options frames and native
heading layout measurements at 1920×1080, density 2.0. The approved typeface ruling
keeps platform Roboto rather than bundling the browser's DejaVu Sans: there is no
per-title compensation and no wrapping-parity claim. `TitleKeysTest` replays
real Android key events from title entry, including modal Back, held OK, nearest
row entry, remembered columns, pending seasons and mouse-wheel re-entry.
`title-press-paths.json` also retains the complete launch paths and their entry
boundaries; their Home prefixes require the Home surface before end-to-end replay.
SDK cache, exact-episode, track-index, identity, locale-layout and trailer-handler
tests run entirely offline with in-process service replies and local art.
## Toolchain and disk use
`Dockerfile` pins Temurin JDK `21.0.11+10` by image digest, command-line tools