feat(plex): person cards in the grid for the filtered actors (S3)
The actors currently in the filter now render as cards above the poster grid — headshot + name + in-scope title count + a remove x — so you SEE who you're exploring, not just chips in the rail (generalises the old search-only person cards to the applied filter). New GET /plex/people/cards (photo from the plex_people cache, count live against cast_names); PlexBrowse fetches + renders them; i18n en/hu. Verified: John Goodman (11) / Douglas M. Griffin (1) / Bradley Cooper (14) with photos + counts. (Plex cast-explore S3)
This commit is contained in:
@@ -1677,6 +1677,51 @@ def _enrich_people_from_rich(db: Session, row, rich: dict) -> bool:
|
||||
return dirty
|
||||
|
||||
|
||||
@router.get("/people/cards")
|
||||
def people_cards(
|
||||
names: str,
|
||||
scope: str = "both",
|
||||
user: User = Depends(current_user),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
"""Cards for the actor filter-chips currently applied: each name + its cached headshot + how many
|
||||
movies/shows (in the given scope) feature them. Photos come from the plex_people cache (populated
|
||||
as items are rich-fetched — info-page view + the rich re-sync); counts are live against cast_names.
|
||||
A name with no cached photo yet still returns a card (the UI shows a placeholder)."""
|
||||
wanted = _csv(names)[:16]
|
||||
if not wanted:
|
||||
return {"people": []}
|
||||
libs = db.query(PlexLibrary).filter_by(enabled=True).all()
|
||||
movie_lib_ids = [lb.id for lb in libs if lb.kind == "movie"]
|
||||
show_lib_ids = [lb.id for lb in libs if lb.kind == "show"]
|
||||
want_movies = scope in ("movie", "both") and bool(movie_lib_ids)
|
||||
want_shows = scope in ("show", "both") and bool(show_lib_ids)
|
||||
photos = {p.name: p.photo_thumb for p in db.query(PlexPerson).filter(PlexPerson.name.in_(wanted))}
|
||||
out = []
|
||||
for nm in wanted:
|
||||
count = 0
|
||||
if want_movies:
|
||||
count += (
|
||||
db.query(func.count(PlexItem.id))
|
||||
.filter(
|
||||
PlexItem.kind == "movie",
|
||||
PlexItem.library_id.in_(movie_lib_ids),
|
||||
PlexItem.cast_names.contains([nm]),
|
||||
)
|
||||
.scalar()
|
||||
or 0
|
||||
)
|
||||
if want_shows:
|
||||
count += (
|
||||
db.query(func.count(PlexShow.id))
|
||||
.filter(PlexShow.library_id.in_(show_lib_ids), PlexShow.cast_names.contains([nm]))
|
||||
.scalar()
|
||||
or 0
|
||||
)
|
||||
out.append({"name": nm, "photo": photos.get(nm), "count": count})
|
||||
return {"people": out}
|
||||
|
||||
|
||||
@router.get("/person-image")
|
||||
def person_image(u: str, request: Request) -> Response:
|
||||
"""Proxy a cast/crew photo from Plex's public metadata CDN (host-whitelisted; no token needed).
|
||||
|
||||
Reference in New Issue
Block a user