This commit is contained in:
Fredrik Burmester
2024-08-06 14:48:23 +02:00
parent 8592f5d22f
commit 165a9ddde7
17 changed files with 318 additions and 77 deletions

View File

@@ -13,6 +13,8 @@ import {
import ContinueWatchingPoster from "./ContinueWatchingPoster";
import { ItemCardText } from "./ItemCardText";
import { Text } from "./common/Text";
import MoviePoster from "./MoviePoster";
import { useMemo } from "react";
type SimilarItemsProps = {
itemId: string;
@@ -38,6 +40,11 @@ export const SimilarItems: React.FC<SimilarItemsProps> = ({ itemId }) => {
staleTime: Infinity,
});
const movies = useMemo(
() => similarItems?.filter((i) => i.Type === "Movie") || [],
[similarItems]
);
return (
<View>
<Text className="px-4 text-2xl font-bold mb-2">Similar items</Text>
@@ -48,22 +55,20 @@ export const SimilarItems: React.FC<SimilarItemsProps> = ({ itemId }) => {
) : (
<ScrollView horizontal>
<View className="px-4 flex flex-row gap-x-2">
{similarItems?.map((item) => (
{movies.map((item) => (
<TouchableOpacity
key={item.Id}
onPress={() => router.push(`/items/${item.Id}/page`)}
className="flex flex-col w-48"
className="flex flex-col w-32"
>
<ContinueWatchingPoster item={item} />
<MoviePoster item={item} />
<ItemCardText item={item} />
</TouchableOpacity>
))}
</View>
</ScrollView>
)}
{similarItems?.length === 0 && (
<Text className="px-4">No similar items</Text>
)}
{movies.length === 0 && <Text className="px-4">No similar items</Text>}
</View>
);
};

View File

@@ -0,0 +1,23 @@
import { TouchableOpacity, View } from "react-native";
import { Text } from "../common/Text";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { router } from "expo-router";
export const EpisodeCard: React.FC<{ item: BaseItemDto }> = ({ item }) => {
const open = () => {
router.back();
router.push(
`/(auth)/player/offline/page?url=${item.Id}.${item.MediaSources?.[0].Container}&itemId=${item.Id}`
);
};
return (
<TouchableOpacity
onPress={open}
className="bg-neutral-800 border border-neutral-900 rounded-2xl p-4"
>
<Text className=" font-bold">{item.Name}</Text>
<Text className=" text-xs opacity-50">Episode {item.IndexNumber}</Text>
</TouchableOpacity>
);
};

View File

@@ -0,0 +1,18 @@
import { View } from "react-native";
import { Text } from "../common/Text";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { runtimeTicksToMinutes } from "@/utils/time";
export const MovieCard: React.FC<{ item: BaseItemDto }> = ({ item }) => {
return (
<View className="bg-neutral-800 border border-neutral-900 rounded-2xl p-4">
<Text className=" font-bold">{item.Name}</Text>
<View className="flex flex-row items-center justify-between">
<Text className=" text-xs opacity-50">{item.ProductionYear}</Text>
<Text className=" text-xs opacity-50">
{runtimeTicksToMinutes(item.RunTimeTicks)}
</Text>
</View>
</View>
);
};

View File

@@ -0,0 +1,49 @@
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { View } from "react-native";
import { EpisodeCard } from "./EpisodeCard";
import { Text } from "../common/Text";
import { useMemo } from "react";
import { SeasonPicker } from "../series/SeasonPicker";
export const SeriesCard: React.FC<{ items: BaseItemDto[] }> = ({ items }) => {
const groupBySeason = useMemo(() => {
const seasons: Record<string, BaseItemDto[]> = {};
items.forEach((item) => {
if (!seasons[item.SeasonName!]) {
seasons[item.SeasonName!] = [];
}
seasons[item.SeasonName!].push(item);
});
return Object.values(seasons).sort(
(a, b) => a[0].IndexNumber! - b[0].IndexNumber!
);
}, [items]);
return (
<View>
<View className="flex flex-row items-center justify-between">
<Text className="text-2xl font-bold">{items[0].SeriesName}</Text>
<View className="bg-purple-600 rounded-full h-6 w-6 flex items-center justify-center">
<Text className="text-xs font-bold">{items.length}</Text>
</View>
</View>
<Text className="opacity-50 mb-2">TV-Series</Text>
{groupBySeason.map((seasonItems, seasonIndex) => (
<View key={seasonIndex}>
<Text className="mb-2 font-semibold">
{seasonItems[0].SeasonName}
</Text>
{seasonItems.map((item, index) => (
<View className="mb-2">
<EpisodeCard item={item} key={item.Id} />
</View>
))}
</View>
))}
</View>
);
};