feat(design): players on touch and the C5 control set, restart on the card (E28 S3f2)

Plex player: a finger's tap on the picture only shows or hides the controls,
the hide timer starts with playback, a double-tap on a side third skips 10 s,
the seek bar is a 2.75rem touch-none hit area with its head shown on touch.
The row is play/pause, Back by position, Next only with a next item, mute,
time, tracks, a fixed ⋯ (settings, media info, stats, shortcuts, download)
and fullscreen; Stop, Restart and the ±10 s buttons are gone.

A started card shows the video card's Continue + Restart pair (one shared
MediaResumeButtons, beside the picture's button), and its menu lists the
restart; the player opens that item at 0 (fromStart). YouTube modal: the
description opens from an ⓘ, the queue arrows sit inside the screen.
This commit is contained in:
2026-09-27 02:12:54 +02:00
parent 17916b411a
commit 89e65ca331
33 changed files with 1100 additions and 282 deletions
+8 -3
View File
@@ -71,7 +71,7 @@ export function PlexInfoView({
id: string;
onBack: () => void;
onPlay: () => void;
onPlayItem: (id: string) => void;
onPlayItem: (id: string, fromStart?: boolean) => void;
onFilter: (patch: Partial<PlexFilters>) => void;
onOpenPerson: (name: string) => void;
}) {
@@ -119,12 +119,14 @@ export function PlexPersonView({
name,
onBack,
onOpenCard,
onRestartCard,
onInfoCard,
onFilter,
}: {
name: string;
onBack: () => void;
onOpenCard: (card: PlexCard) => void;
onRestartCard: (card: PlexCard) => void;
onInfoCard: (card: PlexCard) => void;
onFilter: (patch: Partial<PlexFilters>) => void;
}) {
@@ -170,10 +172,11 @@ export function PlexPersonView({
});
const actions = usePlexCardActions(
{ onOpen: onOpenCard, onInfo: onInfoCard, onToggleWatched: toggle },
{ onOpen: onOpenCard, onRestart: onRestartCard, onInfo: onInfoCard, onToggleWatched: toggle },
menu.open,
);
const cardMenu = (c: PlexCard) => ({
onRestart: () => onRestartCard(c),
onAdd: actions.add,
menuProps: menu.triggerProps,
menuButtonProps: menu.buttonProps,
@@ -654,7 +657,7 @@ export function PlexSeasonView({
showId: string;
seasonId: string;
onBack: () => void;
onPlay: (epRk: string, queue: string[]) => void;
onPlay: (epRk: string, queue: string[], fromStart?: boolean) => void;
}) {
const { t } = useTranslation();
const qc = useQueryClient();
@@ -706,6 +709,7 @@ export function PlexSeasonView({
const episodes = usePlexCardActions(
{
onOpen: (ep) => onPlay(ep.id, allKeys),
onRestart: (ep) => onPlay(ep.id, allKeys, true),
onToggleWatched: (ep) => void markEpisode(ep),
},
epMenu.open,
@@ -796,6 +800,7 @@ export function PlexSeasonView({
navIndex={i}
ep={ep}
onPlay={() => onPlay(ep.id, allKeys)}
onRestart={() => onPlay(ep.id, allKeys, true)}
onAdd={() => episodes.add(ep)}
onToggleWatched={() => markEpisode(ep)}
menuProps={epMenu.triggerProps}