feat(plex): rich media info — info page, in-player info overlay, IMDb + cast photos

Backend (no migration): item_detail now also returns IMDb score + id/url (from the
Plex Rating/Guid arrays), content rating, genres, director(s), studio, tagline, and
cast as {name, role, photo}. New host-whitelisted /person-image proxy serves cast
photos from Plex's public metadata CDN (keeps third-party requests off the browser).

Frontend: reusable PlexInfo component in two forms — a full info page opened from a
card's 'i' button (history subview, art backdrop, Play/Resume + watch controls) and a
lean overlay in the player toggled with 'I' (video keeps playing). Two per-user view
prefs (faint backdrop, cast row) persisted in preferences. Mark-unwatched / clear-resume
cover the watched-reset gap. i18n en/hu/de.
This commit is contained in:
npeter83 2026-07-05 22:57:18 +02:00
parent eed517b475
commit 690e17611c
10 changed files with 568 additions and 9 deletions

View file

@ -53,6 +53,7 @@
"errGeneric": "Die Wiedergabe konnte nicht gestartet werden. Bitte erneut versuchen.",
"stop": "Stopp",
"help": "Tastenkürzel",
"infoBtn": "Medieninfo",
"keys": {
"playPause": "Wiedergabe / Pause",
"seek": "10 Sekunden spulen",
@ -60,10 +61,23 @@
"volume": "Lautstärke lauter / leiser",
"mute": "Stumm",
"fullscreen": "Vollbild",
"info": "Medieninfo",
"back": "Stopp & zurück zum Feed",
"help": "Diese Hilfe anzeigen"
}
},
"info": {
"title": "Medieninfo",
"customize": "Ansicht anpassen",
"prefArtBg": "Dezenter Hintergrund",
"prefCast": "Besetzung",
"openImdb": "Bei IMDb öffnen",
"director": "Regie",
"cast": "Besetzung & Crew",
"markWatched": "Als gesehen markieren",
"markUnwatched": "Gesehen zurücknehmen",
"clearResume": "Fortsetzungsposition löschen"
},
"playable": {
"direct": "Spielt direkt im Browser",
"remux": "Braucht ein leichtes Remux (keine Video-Neucodierung)",

View file

@ -53,6 +53,7 @@
"errGeneric": "Playback couldn't start. Please try again.",
"stop": "Stop",
"help": "Keyboard shortcuts",
"infoBtn": "Media info",
"keys": {
"playPause": "Play / pause",
"seek": "Seek 10 seconds",
@ -60,10 +61,23 @@
"volume": "Volume up / down",
"mute": "Mute",
"fullscreen": "Fullscreen",
"info": "Media info",
"back": "Stop & back to feed",
"help": "Show this help"
}
},
"info": {
"title": "Media info",
"customize": "Customize view",
"prefArtBg": "Faint backdrop",
"prefCast": "Cast & crew",
"openImdb": "Open on IMDb",
"director": "Director",
"cast": "Cast & crew",
"markWatched": "Mark watched",
"markUnwatched": "Mark unwatched",
"clearResume": "Clear resume position"
},
"playable": {
"direct": "Plays directly in the browser",
"remux": "Needs a light remux (no video re-encode)",

View file

@ -53,6 +53,7 @@
"errGeneric": "A lejátszást nem sikerült elindítani. Próbáld újra.",
"stop": "Leállítás",
"help": "Billentyűparancsok",
"infoBtn": "Média infó",
"keys": {
"playPause": "Lejátszás / szünet",
"seek": "Tekerés 10 másodperc",
@ -60,10 +61,23 @@
"volume": "Hangerő fel / le",
"mute": "Némítás",
"fullscreen": "Teljes képernyő",
"info": "Média infó",
"back": "Leállítás és vissza a feedre",
"help": "Súgó megjelenítése"
}
},
"info": {
"title": "Média infó",
"customize": "Nézet testreszabása",
"prefArtBg": "Halvány háttér",
"prefCast": "Szereplők",
"openImdb": "Megnyitás az IMDb-n",
"director": "Rendező",
"cast": "Szereplők & stáb",
"markWatched": "Megjelölés megnézettként",
"markUnwatched": "Megnézett visszavonása",
"clearResume": "Folytatási pozíció törlése"
},
"playable": {
"direct": "Közvetlenül játszható a böngészőben",
"remux": "Könnyű remux kell (nincs videó-újrakódolás)",