diff --git a/app/(auth)/(tabs)/(watchlists)/[watchlistId].tsx b/app/(auth)/(tabs)/(watchlists)/[watchlistId].tsx
index 831feac7..b8a31190 100644
--- a/app/(auth)/(tabs)/(watchlists)/[watchlistId].tsx
+++ b/app/(auth)/(tabs)/(watchlists)/[watchlistId].tsx
@@ -8,6 +8,7 @@ import { useTranslation } from "react-i18next";
import {
ActivityIndicator,
Alert,
+ Platform,
RefreshControl,
TouchableOpacity,
useWindowDimensions,
@@ -16,9 +17,17 @@ import {
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { HeaderBackButton } from "@/components/common/HeaderBackButton";
import { Text } from "@/components/common/Text";
-import { TouchableItemRouter } from "@/components/common/TouchableItemRouter";
+import {
+ getItemNavigation,
+ TouchableItemRouter,
+} from "@/components/common/TouchableItemRouter";
import { ItemCardText } from "@/components/ItemCardText";
import { ItemPoster } from "@/components/posters/ItemPoster";
+import MoviePoster, {
+ TV_POSTER_WIDTH,
+} from "@/components/posters/MoviePoster.tv";
+import SeriesPoster from "@/components/posters/SeriesPoster.tv";
+import { TVFocusablePoster } from "@/components/tv/TVFocusablePoster";
import useRouter from "@/hooks/useAppRouter";
import { useOrientation } from "@/hooks/useOrientation";
import {
@@ -32,6 +41,20 @@ import {
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { userAtom } from "@/providers/JellyfinProvider";
+const TV_ITEM_GAP = 16;
+const TV_SCALE_PADDING = 20;
+
+const TVItemCardText: React.FC<{ item: BaseItemDto }> = ({ item }) => (
+
+
+ {item.Name}
+
+
+ {item.ProductionYear}
+
+
+);
+
export default function WatchlistDetailScreen() {
const { t } = useTranslation();
const router = useRouter();
@@ -47,6 +70,14 @@ export default function WatchlistDetailScreen() {
: undefined;
const nrOfCols = useMemo(() => {
+ if (Platform.isTV) {
+ // Calculate columns based on TV poster width + gap
+ const itemWidth = TV_POSTER_WIDTH + TV_ITEM_GAP;
+ return Math.max(
+ 1,
+ Math.floor((screenWidth - TV_SCALE_PADDING * 2) / itemWidth),
+ );
+ }
if (screenWidth < 300) return 2;
if (screenWidth < 500) return 3;
if (screenWidth < 800) return 5;
@@ -153,6 +184,37 @@ export default function WatchlistDetailScreen() {
[removeFromWatchlist, watchlistIdNum, watchlist?.name, t],
);
+ const renderTVItem = useCallback(
+ ({ item, index }: { item: BaseItemDto; index: number }) => {
+ const handlePress = () => {
+ const navigation = getItemNavigation(item, "(watchlists)");
+ router.push(navigation as any);
+ };
+
+ return (
+
+
+ {item.Type === "Movie" && }
+ {(item.Type === "Series" || item.Type === "Episode") && (
+
+ )}
+
+
+
+ );
+ },
+ [router],
+ );
+
const renderItem = useCallback(
({ item, index }: { item: BaseItemDto; index: number }) => (
}
- renderItem={renderItem}
+ renderItem={Platform.isTV ? renderTVItem : renderItem}
ItemSeparatorComponent={() => (