diff --git a/components/persons/TVActorPage.tsx b/components/persons/TVActorPage.tsx
index eacfd7b1..f7062c61 100644
--- a/components/persons/TVActorPage.tsx
+++ b/components/persons/TVActorPage.tsx
@@ -19,17 +19,19 @@ import {
Dimensions,
Easing,
FlatList,
- Pressable,
ScrollView,
View,
} from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { Text } from "@/components/common/Text";
import { getItemNavigation } from "@/components/common/TouchableItemRouter";
-import { ItemCardText } from "@/components/ItemCardText";
import { Loader } from "@/components/Loader";
import MoviePoster from "@/components/posters/MoviePoster.tv";
+import SeriesPoster from "@/components/posters/SeriesPoster.tv";
+import { TVFocusablePoster } from "@/components/tv/TVFocusablePoster";
+import { TVItemCardText } from "@/components/tv/TVItemCardText";
import { useScaledTVPosterSizes } from "@/constants/TVPosterSizes";
+import { useScaledTVTypography } from "@/constants/TVTypography";
import useRouter from "@/hooks/useAppRouter";
import { useTVItemActionModal } from "@/hooks/useTVItemActionModal";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
@@ -44,64 +46,6 @@ const ACTOR_IMAGE_SIZE = 250;
const ITEM_GAP = 16;
const SCALE_PADDING = 20;
-// Focusable poster wrapper component for TV
-const TVFocusablePoster: React.FC<{
- children: React.ReactNode;
- onPress: () => void;
- onLongPress?: () => void;
- hasTVPreferredFocus?: boolean;
- onFocus?: () => void;
- onBlur?: () => void;
-}> = ({
- children,
- onPress,
- onLongPress,
- hasTVPreferredFocus,
- onFocus,
- onBlur,
-}) => {
- const [focused, setFocused] = useState(false);
- const scale = useRef(new Animated.Value(1)).current;
-
- const animateTo = (value: number) =>
- Animated.timing(scale, {
- toValue: value,
- duration: 150,
- easing: Easing.out(Easing.quad),
- useNativeDriver: true,
- }).start();
-
- return (
- {
- setFocused(true);
- animateTo(1.05);
- onFocus?.();
- }}
- onBlur={() => {
- setFocused(false);
- animateTo(1);
- onBlur?.();
- }}
- hasTVPreferredFocus={hasTVPreferredFocus}
- >
-
- {children}
-
-
- );
-};
-
interface TVActorPageProps {
personId: string;
}
@@ -114,6 +58,7 @@ export const TVActorPage: React.FC = ({ personId }) => {
const segments = useSegments();
const from = (segments as string[])[2] || "(home)";
const posterSizes = useScaledTVPosterSizes();
+ const typography = useScaledTVTypography();
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
@@ -294,29 +239,48 @@ export const TVActorPage: React.FC = ({ personId }) => {
[],
);
- // Render filmography item
- const renderFilmographyItem = useCallback(
- (
- { item: filmItem, index }: { item: BaseItemDto; index: number },
- isFirstSection: boolean,
- ) => (
+ // Render movie filmography item
+ const renderMovieItem = useCallback(
+ ({ item: filmItem, index }: { item: BaseItemDto; index: number }) => (
handleItemPress(filmItem)}
onLongPress={() => showItemActions(filmItem)}
onFocus={() => setFocusedItem(filmItem)}
- hasTVPreferredFocus={isFirstSection && index === 0}
+ hasTVPreferredFocus={index === 0}
>
-
-
+
+
),
- [handleItemPress, showItemActions],
+ [handleItemPress, showItemActions, posterSizes.poster],
+ );
+
+ // Render series filmography item
+ const renderSeriesItem = useCallback(
+ ({ item: filmItem, index }: { item: BaseItemDto; index: number }) => (
+
+ handleItemPress(filmItem)}
+ onLongPress={() => showItemActions(filmItem)}
+ onFocus={() => setFocusedItem(filmItem)}
+ hasTVPreferredFocus={movies.length === 0 && index === 0}
+ >
+
+
+
+
+
+
+
+
+ ),
+ [handleItemPress, showItemActions, posterSizes.poster, movies.length],
);
if (isLoadingActor) {
@@ -386,28 +350,16 @@ export const TVActorPage: React.FC = ({ personId }) => {
)}
- {/* Gradient overlays for readability */}
+ {/* Gradient overlay for readability */}
-
@@ -471,7 +423,7 @@ export const TVActorPage: React.FC = ({ personId }) => {
{/* Actor name */}
= ({ personId }) => {
{item.ProductionYear && (
= ({ personId }) => {
{item.Overview && (
= ({ personId }) => {
= ({ personId }) => {
horizontal
data={movies}
keyExtractor={(filmItem) => filmItem.Id!}
- renderItem={(props) => renderFilmographyItem(props, true)}
+ renderItem={renderMovieItem}
showsHorizontalScrollIndicator={false}
initialNumToRender={6}
maxToRenderPerBatch={4}
@@ -575,7 +527,7 @@ export const TVActorPage: React.FC = ({ personId }) => {
= ({ personId }) => {
horizontal
data={series}
keyExtractor={(filmItem) => filmItem.Id!}
- renderItem={(props) =>
- renderFilmographyItem(props, movies.length === 0)
- }
+ renderItem={renderSeriesItem}
showsHorizontalScrollIndicator={false}
initialNumToRender={6}
maxToRenderPerBatch={4}
@@ -615,7 +565,7 @@ export const TVActorPage: React.FC = ({ personId }) => {