feat(tv): change playback options layout to horizontal row

This commit is contained in:
Fredrik Burmester
2026-01-29 18:17:43 +01:00
parent bf3a37c61c
commit 53902aebab
2 changed files with 15 additions and 47 deletions

View File

@@ -184,10 +184,6 @@ export const ItemContentTV: React.FC<ItemContentTVProps> = React.memo(
null,
);
// State for last option button ref (used for upward focus guide from cast)
const [_lastOptionButtonRef, setLastOptionButtonRef] =
useState<View | null>(null);
// Get available audio tracks
const audioTracks = useMemo(() => {
const streams = selectedOptions?.mediaSource?.MediaStreams?.filter(
@@ -442,25 +438,6 @@ export const ItemContentTV: React.FC<ItemContentTVProps> = React.memo(
return `${api.basePath}/Items/${item.SeriesId}/Images/Thumb?fillHeight=700&quality=80`;
}, [api, item]);
// Determine which option button is the last one (for focus guide targeting)
const lastOptionButton = useMemo(() => {
const hasSubtitleOption =
subtitleStreams.length > 0 ||
selectedOptions?.subtitleIndex !== undefined;
const hasAudioOption = audioTracks.length > 0;
const hasMediaSourceOption = mediaSources.length > 1;
if (hasSubtitleOption) return "subtitle";
if (hasAudioOption) return "audio";
if (hasMediaSourceOption) return "mediaSource";
return "quality";
}, [
subtitleStreams.length,
selectedOptions?.subtitleIndex,
audioTracks.length,
mediaSources.length,
]);
// Navigation handlers
const handleActorPress = useCallback(
(personId: string) => {
@@ -658,21 +635,17 @@ export const ItemContentTV: React.FC<ItemContentTVProps> = React.memo(
{/* Playback options */}
<View
style={{
flexDirection: "column",
alignItems: "flex-start",
gap: 10,
flexDirection: "row",
alignItems: "center",
gap: 12,
marginBottom: 24,
}}
>
{/* Quality selector */}
<TVOptionButton
ref={
lastOptionButton === "quality"
? setLastOptionButtonRef
: undefined
}
label={t("item_card.quality")}
value={selectedQualityLabel}
maxWidth={200}
onPress={() =>
showOptions({
title: t("item_card.quality"),
@@ -685,13 +658,9 @@ export const ItemContentTV: React.FC<ItemContentTVProps> = React.memo(
{/* Media source selector (only if multiple sources) */}
{mediaSources.length > 1 && (
<TVOptionButton
ref={
lastOptionButton === "mediaSource"
? setLastOptionButtonRef
: undefined
}
label={t("item_card.video")}
value={selectedMediaSourceLabel}
maxWidth={280}
onPress={() =>
showOptions({
title: t("item_card.video"),
@@ -705,13 +674,9 @@ export const ItemContentTV: React.FC<ItemContentTVProps> = React.memo(
{/* Audio selector */}
{audioTracks.length > 0 && (
<TVOptionButton
ref={
lastOptionButton === "audio"
? setLastOptionButtonRef
: undefined
}
label={t("item_card.audio")}
value={selectedAudioLabel}
maxWidth={280}
onPress={() =>
showOptions({
title: t("item_card.audio"),
@@ -726,13 +691,9 @@ export const ItemContentTV: React.FC<ItemContentTVProps> = React.memo(
{(subtitleStreams.length > 0 ||
selectedOptions?.subtitleIndex !== undefined) && (
<TVOptionButton
ref={
lastOptionButton === "subtitle"
? setLastOptionButtonRef
: undefined
}
label={t("item_card.subtitles.label")}
value={selectedSubtitleLabel}
maxWidth={280}
onPress={() =>
showSubtitleModal({
item,

View File

@@ -10,10 +10,11 @@ export interface TVOptionButtonProps {
value: string;
onPress: () => void;
hasTVPreferredFocus?: boolean;
maxWidth?: number;
}
export const TVOptionButton = React.forwardRef<View, TVOptionButtonProps>(
({ label, value, onPress, hasTVPreferredFocus }, ref) => {
({ label, value, onPress, hasTVPreferredFocus, maxWidth }, ref) => {
const typography = useScaledTVTypography();
const { focused, handleFocus, handleBlur, animatedStyle } =
useTVFocusAnimation({ scaleAmount: 1.02, duration: 120 });
@@ -47,12 +48,14 @@ export const TVOptionButton = React.forwardRef<View, TVOptionButtonProps>(
flexDirection: "row",
alignItems: "center",
gap: 8,
maxWidth,
}}
>
<Text
style={{
fontSize: typography.callout,
color: "#444",
flexShrink: 0,
}}
>
{label}
@@ -62,6 +65,7 @@ export const TVOptionButton = React.forwardRef<View, TVOptionButtonProps>(
fontSize: typography.callout,
color: "#000",
fontWeight: "500",
flexShrink: 1,
}}
numberOfLines={1}
>
@@ -75,6 +79,7 @@ export const TVOptionButton = React.forwardRef<View, TVOptionButtonProps>(
style={{
borderRadius: 8,
overflow: "hidden",
maxWidth,
}}
>
<View
@@ -91,6 +96,7 @@ export const TVOptionButton = React.forwardRef<View, TVOptionButtonProps>(
style={{
fontSize: typography.callout,
color: "#bbb",
flexShrink: 0,
}}
>
{label}
@@ -100,6 +106,7 @@ export const TVOptionButton = React.forwardRef<View, TVOptionButtonProps>(
fontSize: typography.callout,
color: "#E5E7EB",
fontWeight: "500",
flexShrink: 1,
}}
numberOfLines={1}
>