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:
2026-07-19 03:46:31 +02:00
parent 6f28ce36a7
commit 05105197e9
5 changed files with 114 additions and 2 deletions
+8
View File
@@ -828,6 +828,11 @@ export interface PlexCastMember {
role?: string | null;
thumb?: string | null; // proxied person-image url, or null when Plex has no photo
}
export interface PlexPersonCard {
name: string;
photo?: string | null; // proxied person-image url, or null (placeholder)
count: number; // in-scope movies/shows featuring them
}
// The expanded Plex browse filters (movie libraries). Persisted per-account as JSON.
export interface PlexFilters {
genres: string[];
@@ -1351,6 +1356,9 @@ export const api = {
req(`/api/plex/season/${encodeURIComponent(rk)}/state`, { method: "POST", body: JSON.stringify({ watched }) }),
plexItem: (id: string): Promise<PlexItemDetail> =>
req(`/api/plex/item/${encodeURIComponent(id)}`),
// Cards for the actor filter-chips currently applied: name + cached headshot + in-scope film/show count.
plexPeopleCards: (names: string[], scope: string): Promise<{ people: PlexPersonCard[] }> =>
req(`/api/plex/people/cards?scope=${encodeURIComponent(scope)}&names=${encodeURIComponent(names.join(","))}`),
plexSession: (id: string, start = 0, audio?: number | null, aoff = 0, multi = false): Promise<PlexPlaySession> => {
const p = new URLSearchParams({ start: String(Math.max(0, Math.floor(start))) });
if (audio != null) p.set("audio", String(audio));