From 2b7620ded93e1353509f63d0d0b063fba95533a1 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sat, 7 Nov 2026 18:01:15 +0100 Subject: [PATCH] fix(plex): text over the picture sits on a dark panel The player's loading, stall and error text was bare white or red on the video, unreadable over a bright frame. It now sits on the dark panel the subtitle notice and the track OSD already used, one constant for all three. DESIGN.md records it and the slow-connection line. --- docs/DESIGN.md | 5 +++++ frontend/src/modules/plex/PlexPlayer.tsx | 18 +++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/DESIGN.md b/docs/DESIGN.md index 29015542..b3201da0 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -568,6 +568,9 @@ of a full-width panel and nothing on the right. the first tap however long the video played). - **The bars stay up while the pointer rests on them** (F22, owner); leaving starts a fresh 3 s. YouTube and Plex Web do the same: before, the row faded out from under a mouse parked on Next. +- **Text over the picture sits on a dark panel** (2026-11-07): loading, stalls, errors and the notices are + readable on any frame. A stall that lasts 5 s on a link measured slower than the stream says "Slow + connection" with both rates. - **Volume is the native `Slider`** (A6); the hand-drawn bar had no hover, focus, keyboard or screen-reader state. A pointer drag gives the focus back, so Space and the arrows keep driving the player. - **The seek bar:** the track stays thin inside a 2.75rem (44px) hit area with `touch-action: none`, so a finger @@ -870,3 +873,5 @@ of a full-width panel and nothing on the right. | 2026-11-06 | A pick in the open fold closes it (owner a) | Toggling a chip inside the "+N" popover closes the popover; the focus goes with the chip | Keep the popover open and focus the chip now in the picked one's place | The focus never sits outside a popover left open, and a picked chip leads the row anyway | | 2026-11-06 | An expired share link offers no Copy (owner a) | An expired row in the share dialog has a warn badge "expired " and its address struck through; Open and Revoke stay, Copy goes | The warn badge alone, Copy kept | An expired link opens nothing, so it is no link to hand out; Open still lets the owner check it | | 2026-11-06 | The shared page's unlock button is a noun in Hungarian (owner a) | "Megtekintés" for a video, "Megnyitás" for a file or folder | Both verbs, "Megnézem" / "Megnyitom" | The app's Hungarian buttons are nouns; one button should not change grammatical form by link kind | +| 2026-11-07 | A slow link says so, with both rates (owner b1) | After 5 s of stalling on a link measured slower than the stream: "Slow connection" and "This file needs about X, about Y is arriving" under the spinner; no number measured, no claim | The line without numbers; a pill at the bottom | The viewer can tell their connection from a broken player, and by how much it falls short | +| 2026-11-07 | Text over the picture sits on a dark panel (owner a) | The player's loading, stall and error text, the subtitle notice and the track OSD sit on one dark panel (`OVER_VIDEO`, black 75 %, a white 15 % edge) | A shadow behind the letters; bare text as before | Bare white or red text was unreadable over a bright frame (seen live); the panel is the style the notices already had | diff --git a/frontend/src/modules/plex/PlexPlayer.tsx b/frontend/src/modules/plex/PlexPlayer.tsx index eaf1fa76..1d24338e 100644 --- a/frontend/src/modules/plex/PlexPlayer.tsx +++ b/frontend/src/modules/plex/PlexPlayer.tsx @@ -118,6 +118,10 @@ const BACK_TO_PREV_S = 3; const PLAYER_MENU = "rounded-xl border border-white/15 bg-media-chrome/95 media-marks text-sm text-white shadow-2xl"; const PLAYER_ROW = "block w-full rounded-lg px-2 py-1.5 text-left hover:bg-white/10"; +// Text over the picture (the loading/stall/error overlay, the subtitle notice, the track OSD) sits on +// its own dark panel: bare white or red text was unreadable over a bright frame (measured live on a +// white-lit scene). The shape (pill or panel) is each site's own. +const OVER_VIDEO = "border border-white/15 bg-black/75 text-white shadow-2xl"; // A track choice: white like the rest, the chosen one marked by the tick in the leading slot (DESIGN // "one of several"), which `media-marks` paints the media amber — a light theme's accent as the // label's colour was dark on the chrome (Slate 2.84:1), and the highlight's white washed it out. @@ -1328,9 +1332,11 @@ export default function PlexPlayer({ className="absolute inset-0 grid place-items-center px-6 text-center text-sm pointer-events-none" > {loadError ? ( - {loadError} +
+ {loadError} +
) : ( -
+
{/* Announce the stall to assistive tech. Initial load shows visible text; a mid-playback rebuffer/seek (ready, no error) has no visible label, so give it an sr-only one via the @@ -1338,7 +1344,7 @@ export default function PlexPlayer({ {slowRates ? ( <> {t("plex.player.slowLink")} - + {t("plex.player.slowLinkRates", { need: formatMbps(slowRates.need, i18n.language), got: formatMbps(slowRates.got, i18n.language), @@ -1369,7 +1375,9 @@ export default function PlexPlayer({ aria-live="polite" > {selectedSub && subNotice && ( -
+
{subNotice !== "preparing" ? ( {t(`plex.player.subUnavailable.${subNotice}`)} ) : ( @@ -1395,7 +1403,7 @@ export default function PlexPlayer({ aria-live="polite" > {osd && ( -
+
{osd}
)}