feat(plex): redesign browse tiles — 2-poster montage top, readable label band
The full-bleed 4-poster collage drowned the on-tile text. Split PosterTile in two: the top half shows up to 2 montage posters, the bottom half is a solid colour-hash band that carries the label, so the text is always readable. Genre tiles drop the count (just the label now); collection tiles show the name on one truncated line plus a sub-line of item count · total runtime. A group with no art falls back to an all-colour tile. Backend: `/collections` cards gain `total_runtime_s` (a new `runtime_by_key` grouped sum) and their montage art is capped at 2. Frontend: PosterTile reworked; a `collectionMeta` helper builds the count·runtime sub-line via the existing formatRuntime. Verified live: collection and genre tiles render 2 posters over a readable colour band with the right sub-lines; colour fallback intact for art-less groups. Gate: tsc/lint/knip/prettier clean, 423 vitest; backend ruff clean, collections tests green (+ a new art/runtime assertion).
This commit is contained in:
@@ -16,7 +16,7 @@ from app.models import (
|
||||
from app.plex import sync as plex_sync
|
||||
from app.plex.client import PlexClient, PlexError, PlexNotConfigured
|
||||
from app.plex.lookups import by_rating_key
|
||||
from app.plex.query import like_escape, top_art_keys
|
||||
from app.plex.query import like_escape, runtime_by_key, top_art_keys
|
||||
from app.routes.plex._shared import _content_libs
|
||||
|
||||
router = APIRouter(prefix="/api/plex", tags=["plex"])
|
||||
@@ -95,11 +95,22 @@ def collections(
|
||||
func.lower(PlexCollection.title),
|
||||
)
|
||||
).scalars().all()
|
||||
# A 2×2 poster collage per tile: the top movies in each collection (color hash is the client
|
||||
# fallback for show-only / empty collections). One windowed query across the content movie libs.
|
||||
# A montage of the top films per tile + the collection's total runtime (color hash + no-runtime is
|
||||
# the client fallback for show-only / empty collections). Two grouped queries over the movie libs.
|
||||
movie_ids, _show_ids = _content_libs(db)
|
||||
art = top_art_keys(db, PlexItem, movie_ids, PlexItem.collection_keys, [c.rating_key for c in rows])
|
||||
return {"collections": [{**_collection_card(c), "art": art.get(c.rating_key, [])} for c in rows]}
|
||||
keys = [c.rating_key for c in rows]
|
||||
art = top_art_keys(db, PlexItem, movie_ids, PlexItem.collection_keys, keys, per=2)
|
||||
runtime = runtime_by_key(db, PlexItem, movie_ids, PlexItem.collection_keys, keys)
|
||||
return {
|
||||
"collections": [
|
||||
{
|
||||
**_collection_card(c),
|
||||
"art": art.get(c.rating_key, []),
|
||||
"total_runtime_s": runtime.get(c.rating_key, 0),
|
||||
}
|
||||
for c in rows
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def _editable_collection_or_403(db: Session, rating_key: str) -> PlexCollection:
|
||||
|
||||
Reference in New Issue
Block a user