Integrate libraries and correct Home review blockers

This commit is contained in:
justinzeus 2026-11-05 19:03:33 +01:00
commit 14a74ac43b
642 changed files with 2377 additions and 169 deletions

View file

@ -0,0 +1,494 @@
{
"id": "library",
"title": "Libraries: Movies, Shows, Anime (one continuous 6-column grid)",
"specSection": "6.4",
"source": "index.html:1403-1426, 1563-1611",
"layout": [
{
"id": "lhead",
"type": "lhead",
"token": null,
"title": "Movies",
"yPx": 0,
"heightPx": 236,
"cards": null,
"focusable": false,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "ltools",
"type": "chips",
"token": null,
"title": "",
"yPx": 236,
"heightPx": 104,
"cards": null,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g0",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 340,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g1",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 828,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g2",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 1316,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g3",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 1804,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g4",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 2292,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g5",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 2780,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g6",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 3268,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g7",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 3756,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g8",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 4244,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g9",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 4732,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g10",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 5220,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g11",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 5708,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g12",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 6196,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
},
{
"id": "g13",
"type": "grid",
"token": "poster",
"title": "",
"yPx": 6684,
"heightPx": 488,
"cards": 6,
"focusable": true,
"endsInSeeAll": false,
"sampleFill": false
}
],
"states": [
{
"id": "st-021",
"name": "Shared Movies: 84, continuous grid",
"statesGroup": "Libraries",
"capture": "st-021-shared-movies-84-continuous-grid.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-021-shared-movies-84-continuous-grid.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "shared",
"focusReadout": "State: Shared Movies: 84, continuous grid · Person: Shared · Screen: Movies · Focus: g0 › American Gangster"
},
{
"id": "st-022",
"name": "Shared Movies sorted by Rating (G10)",
"statesGroup": "Libraries",
"capture": "st-022-shared-movies-sorted-by-rating-g10.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-022-shared-movies-sorted-by-rating-g10.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "shared",
"focusReadout": "State: Shared Movies sorted by Rating (G10) · Person: Shared · Screen: Movies · Focus: g0 › Grave of the Fireflies"
},
{
"id": "st-023",
"name": "Right at a row end clamps (no letter rail below 200)",
"statesGroup": "Libraries",
"capture": "st-023-right-at-a-row-end-clamps-no-letter-rail-below-200.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-023-right-at-a-row-end-clamps-no-letter-rail-below-200.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "shared",
"focusReadout": "State: Right at a row end clamps (no letter rail below 200) · Person: Shared · Screen: Movies · Focus: g0 › Bohemian Rhapsody"
},
{
"id": "st-024",
"name": "Justin Anime: 18 series",
"statesGroup": "Libraries",
"capture": "st-024-justin-anime-18-series.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-024-justin-anime-18-series.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "justin",
"focusReadout": "State: Justin Anime: 18 series · Person: Justin · Screen: Anime · Focus: g0 › Bleach"
},
{
"id": "st-025",
"name": "Unwatched filter",
"statesGroup": "Libraries",
"capture": "st-025-unwatched-filter.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-025-unwatched-filter.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "shared",
"focusReadout": "State: Unwatched filter · Person: Shared · Screen: Movies · Focus: g0 › Annie Hall"
},
{
"id": "st-026",
"name": "Empty destination",
"statesGroup": "Libraries",
"capture": "st-026-empty-destination.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-026-empty-destination.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "mindel",
"focusReadout": "State: Empty destination · Person: Mindel · Screen: Movies · Focus: Nothing in Movies yet › Open Discover"
},
{
"id": "st-027",
"name": "Jellyfin unreachable (error)",
"statesGroup": "Libraries",
"capture": "st-027-jellyfin-unreachable-error.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-027-jellyfin-unreachable-error.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "mindel",
"focusReadout": "State: Jellyfin unreachable (error) · Person: Mindel · Screen: Shows · Focus: Couldn’t reach your library › Try again"
},
{
"id": "st-028",
"name": "Loading (skeleton, no saved copy)",
"statesGroup": "Libraries",
"capture": "st-028-loading-skeleton-no-saved-copy.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-028-loading-skeleton-no-saved-copy.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "nav",
"person": "shared",
"focusReadout": "State: Loading (skeleton, no saved copy) · Person: Shared · Screen: Movies · Focus: nav › Movies"
},
{
"id": "st-095",
"name": "Plate: widest real set on a 256 px poster",
"statesGroup": "Ratings: one-line plate (round 3)",
"capture": "st-095-plate-widest-real-set-on-a-256-px-poster.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-095-plate-widest-real-set-on-a-256-px-poster.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "shared",
"focusReadout": "State: Plate: widest real set on a 256 px poster · Person: Shared · Screen: Movies · Focus: g4 › Grave of the Fireflies"
},
{
"id": "st-097",
"name": "Poster: RT critics on a library grid (Shared Movies)",
"statesGroup": "Ratings (round 2)",
"capture": "st-097-poster-rt-critics-on-a-library-grid-shared-movies.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-097-poster-rt-critics-on-a-library-grid-shared-movies.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "shared",
"focusReadout": "State: Poster: RT critics on a library grid (Shared Movies) · Person: Shared · Screen: Movies · Focus: g0 › American Gangster"
},
{
"id": "st-098",
"name": "Poster: TMDB only (Justin Anime)",
"statesGroup": "Ratings (round 2)",
"capture": "st-098-poster-tmdb-only-justin-anime.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-098-poster-tmdb-only-justin-anime.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "justin",
"focusReadout": "State: Poster: TMDB only (Justin Anime) · Person: Justin · Screen: Anime · Focus: g0 › Chainsaw Man"
},
{
"id": "st-112",
"name": "Conductarr down: a cached rating still shows",
"statesGroup": "Ratings (round 2)",
"capture": "st-112-conductarr-down-a-cached-rating-still-shows.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-112-conductarr-down-a-cached-rating-still-shows.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "shared",
"focusReadout": "State: Conductarr down: a cached rating still shows · Person: Shared · Screen: Movies · Focus: g0 › American Gangster"
},
{
"id": "st-113",
"name": "Conductarr down: an uncached title shows nothing",
"statesGroup": "Ratings (round 2)",
"capture": "st-113-conductarr-down-an-uncached-title-shows-nothing.jpg",
"captureUrl": "https://pages.justinvisser.org/wolfskin/tv-spec/img/st-113-conductarr-down-an-uncached-title-shows-nothing.jpg",
"screenKind": "library",
"overlay": null,
"focusZone": "content",
"person": "shared",
"focusReadout": "State: Conductarr down: an uncached title shows nothing · Person: Shared · Screen: Movies · Focus: g0 › American Gangster"
}
],
"focusMap": {
"entry": "first grid card (not the toolbar); returning: remembered card per person",
"zones": {
"toolbar": {
"up": "nav",
"down": "grid",
"left": "previous chip",
"right": "next chip",
"ok": "Sort cycles A–Z -> Recently added -> Rating; Filter toggles All / Unwatched; focus returns to the toolbar",
"back": "nav",
"source": "index.html:445"
},
"grid": {
"up": "row above, same column (top row -> toolbar)",
"down": "row below, same column (shorter last row: its last card)",
"left": "previous column (column 0: stays)",
"right": "next column; at the row end: stays (no rail below 200 titles)",
"ok": "title page (key-up)",
"back": "nav, place kept",
"ratings": "one-line plate after 350 ms",
"source": "index.html:446"
},
"letterRail": "only at >= 200 titles and A–Z sort: Right at a row end enters; Up/Down move letters and scroll live; OK or Left drops focus on that letter's first title; Back returns to where you were (index.html:1586-1605)"
},
"exit": [
"Up from toolbar -> nav",
"Back -> nav"
]
},
"pressPaths": [
{
"goal": "Reach “Spirited Away” (68th of 84) in Shared Movies by scrolling",
"keys": [
"RIGHT",
"RIGHT",
"OK",
"UP",
"RIGHT",
"RIGHT",
"OK",
"DOWN",
"DOWN",
"DOWN",
"DOWN",
"DOWN",
"DOWN",
"DOWN",
"DOWN",
"DOWN",
"DOWN",
"DOWN",
"RIGHT",
"RIGHT"
],
"presses": 20,
"note": "",
"start": "app launch: Who's watching with Justin focused (index.html:357)",
"replayed": "PASS",
"source": "index.html:2152-2174 PRESSES, replayed 2026-11-05"
}
],
"data": [
{
"component": "Library grid",
"source": "Jellyfin /Users/{id}/Items?ParentId=…&SortBy=SortName over the destination's libraries, read in full in 200-item chunks ahead of focus",
"fields": [
"SortName",
"ProductionYear",
"ImageTags.Primary",
"UserData.Played",
"UserData.PlaybackPositionTicks",
"ProviderIds.Tmdb"
],
"cache": "LKG snapshot per destination; refresh on open if older than 10 min",
"states": [
"empty",
"Jellyfin unreachable (LKG + Saved chip, or state row)",
"missing art"
],
"pageRow": "index.html:469"
},
{
"component": "Destinations",
"source": "Conductarr GET /curation/library-audiences (owner, media_type, is_anime, libraries[], users[]); until sign-in, the name rule (parked board mapping-source = name-rule)",
"pageRow": "index.html:468"
}
],
"strings": {
"count": "{n} films | {n} series",
"empty": [
"Nothing in {Destination} yet",
"Titles you or others request for you land here.",
"Open Discover"
],
"emptyUnwatched": [
"Nothing unwatched in {Destination}",
"Everything here has been watched.",
"Show all"
],
"down": [
"Couldn’t reach your library",
"Jellyfin isn’t answering. Nothing here is lost; try again in a moment.",
"Try again"
],
"sort": [
"A–Z",
"Recently added",
"Rating"
],
"filter": [
"All",
"Unwatched"
]
},
"ratingScoreFormat": {
"rule": "TMDB, IMDb and \"Ep\" scores (0-10) are formatted with the TV locale and exactly one decimal, e.g. String.format(Locale.getDefault(), \"%.1f\", x): 7,8 on a Dutch-locale box, 7.8 on an English one. RT percentages unchanged (87%). The page prints 7.8 always: a stand-in for the English locale, not authoritative.",
"acceptance": "on a Dutch-locale emulator a TMDB 7.8 renders 7,8 and the one-line plate rule (spec 4.8) still holds because the width is unchanged [INFERENCE: comma and point advance widths not measured]; on an English-locale emulator it renders 7.8 as in the captures",
"source": "Justin 2026-11-05, corr=c248698d8546e1ab; spec 4.7 rule 5, 10.1 check 8"
},
"$schema": "wolfskin-tv-spec/screen@1",
"tokens": "data/tv-spec/tokens.json",
"captures": [
"st-021-shared-movies-84-continuous-grid.jpg",
"st-022-shared-movies-sorted-by-rating-g10.jpg",
"st-023-right-at-a-row-end-clamps-no-letter-rail-below-200.jpg",
"st-024-justin-anime-18-series.jpg",
"st-025-unwatched-filter.jpg",
"st-026-empty-destination.jpg",
"st-027-jellyfin-unreachable-error.jpg",
"st-028-loading-skeleton-no-saved-copy.jpg",
"st-095-plate-widest-real-set-on-a-256-px-poster.jpg",
"st-097-poster-rt-critics-on-a-library-grid-shared-movies.jpg",
"st-098-poster-tmdb-only-justin-anime.jpg",
"st-112-conductarr-down-a-cached-rating-still-shows.jpg",
"st-113-conductarr-down-an-uncached-title-shows-nothing.jpg"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Some files were not shown because too many files have changed in this diff Show more