perf(tv): optimize focus animations and disable native glass effect

This commit is contained in:
Fredrik Burmester
2026-01-31 21:34:49 +01:00
parent f549e8eaed
commit e6598f0944
8 changed files with 78 additions and 53 deletions

View File

@@ -6,7 +6,7 @@ import {
useInfiniteQuery,
} from "@tanstack/react-query";
import { useSegments } from "expo-router";
import { useCallback, useMemo, useRef, useState } from "react";
import { useCallback, useMemo, useRef } from "react";
import { useTranslation } from "react-i18next";
import {
ActivityIndicator,
@@ -134,27 +134,16 @@ export const InfiniteScrollingCollectionList: React.FC<Props> = ({
const segments = useSegments();
const from = (segments as string[])[2] || "(home)";
// Track focus within section for item focus/blur callbacks
const flatListRef = useRef<FlatList<BaseItemDto>>(null);
const [_focusedCount, setFocusedCount] = useState(0);
// Pass through focus callbacks without tracking internal state
const handleItemFocus = useCallback(
(item: BaseItemDto) => {
setFocusedCount((c) => c + 1);
onItemFocus?.(item);
},
[onItemFocus],
);
const handleItemBlur = useCallback(() => {
setFocusedCount((c) => Math.max(0, c - 1));
}, []);
// Focus handler for See All card (doesn't need item parameter)
const handleSeeAllFocus = useCallback(() => {
setFocusedCount((c) => c + 1);
}, []);
const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage } =
useInfiniteQuery({
queryKey: queryKey,
@@ -234,7 +223,6 @@ export const InfiniteScrollingCollectionList: React.FC<Props> = ({
onLongPress={() => showItemActions(item)}
hasTVPreferredFocus={isFirstItem}
onFocus={() => handleItemFocus(item)}
onBlur={handleItemBlur}
width={itemWidth}
/>
</View>
@@ -247,7 +235,6 @@ export const InfiniteScrollingCollectionList: React.FC<Props> = ({
handleItemPress,
showItemActions,
handleItemFocus,
handleItemBlur,
ITEM_GAP,
],
);
@@ -370,8 +357,6 @@ export const InfiniteScrollingCollectionList: React.FC<Props> = ({
onPress={handleSeeAllPress}
orientation={orientation}
disabled={disabled}
onFocus={handleSeeAllFocus}
onBlur={handleItemBlur}
typography={typography}
posterSizes={posterSizes}
/>

View File

@@ -157,6 +157,8 @@ const HeroCard: React.FC<HeroCardProps> = React.memo(
borderRadius: 24,
overflow: "hidden",
transform: [{ scale }],
borderWidth: 2,
borderColor: focused ? "#FFFFFF" : "transparent",
shadowColor: "#FFFFFF",
shadowOffset: { width: 0, height: 0 },
shadowOpacity: focused ? 0.6 : 0,

View File

@@ -56,8 +56,8 @@ export const TVActorCard = React.forwardRef<View, TVActorCardProps>(
overflow: "hidden",
backgroundColor: "rgba(255,255,255,0.1)",
marginBottom: 14,
borderWidth: focused ? 3 : 0,
borderColor: "#fff",
borderWidth: 2,
borderColor: focused ? "#FFFFFF" : "transparent",
}}
>
{imageUrl ? (

View File

@@ -397,6 +397,8 @@ export const TVPosterCard: React.FC<TVPosterCardProps> = ({
aspectRatio,
borderRadius: 24,
backgroundColor: "#1a1a1a",
borderWidth: 2,
borderColor: focused ? "#FFFFFF" : "transparent",
}}
/>
);
@@ -432,6 +434,8 @@ export const TVPosterCard: React.FC<TVPosterCardProps> = ({
borderRadius: 24,
overflow: "hidden",
backgroundColor: "#1a1a1a",
borderWidth: 2,
borderColor: focused ? "#FFFFFF" : "transparent",
}}
>
<Image

View File

@@ -69,6 +69,8 @@ export const TVSeriesSeasonCard: React.FC<TVSeriesSeasonCardProps> = ({
borderRadius: 24,
overflow: "hidden",
backgroundColor: "rgba(255,255,255,0.1)",
borderWidth: 2,
borderColor: focused ? "#FFFFFF" : "transparent",
}}
>
{imageUrl ? (