mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-04-22 08:44:41 +01:00
fix
This commit is contained in:
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
23
components/downloads/EpisodeCard.tsx
Normal file
23
components/downloads/EpisodeCard.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
18
components/downloads/MovieCard.tsx
Normal file
18
components/downloads/MovieCard.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
49
components/downloads/SeriesCard.tsx
Normal file
49
components/downloads/SeriesCard.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user