fix: type errors and design

This commit is contained in:
Fredrik Burmester
2024-12-08 15:59:03 +01:00
parent 15073f47db
commit 5e9b28f2eb
2 changed files with 74 additions and 56 deletions

View File

@@ -1,37 +1,48 @@
import {Text} from "@/components/common/Text";
import {useDownload} from "@/providers/DownloadProvider";
import {router, useLocalSearchParams, useNavigation} from "expo-router";
import React, {useCallback, useEffect, useMemo, useState} from "react";
import {ScrollView, TouchableOpacity, View} from "react-native";
import {EpisodeCard} from "@/components/downloads/EpisodeCard";
import {BaseItemDto} from "@jellyfin/sdk/lib/generated-client/models";
import {SeasonDropdown, SeasonIndexState} from "@/components/series/SeasonDropdown";
import {storage} from "@/utils/mmkv";
import {Ionicons} from "@expo/vector-icons";
import { Text } from "@/components/common/Text";
import { useDownload } from "@/providers/DownloadProvider";
import { router, useLocalSearchParams, useNavigation } from "expo-router";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { ScrollView, TouchableOpacity, View } from "react-native";
import { EpisodeCard } from "@/components/downloads/EpisodeCard";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import {
SeasonDropdown,
SeasonIndexState,
} from "@/components/series/SeasonDropdown";
import { storage } from "@/utils/mmkv";
import { Ionicons } from "@expo/vector-icons";
export default function page() {
const navigation = useNavigation();
const local = useLocalSearchParams();
const {seriesId, episodeSeasonIndex} = local as {
seriesId: string,
episodeSeasonIndex: number | string | undefined
const { seriesId, episodeSeasonIndex } = local as {
seriesId: string;
episodeSeasonIndex: number | string | undefined;
};
const [seasonIndexState, setSeasonIndexState] = useState<SeasonIndexState>({});
const {downloadedFiles, deleteItems} = useDownload();
const [seasonIndexState, setSeasonIndexState] = useState<SeasonIndexState>(
{}
);
const { downloadedFiles, deleteItems } = useDownload();
const series = useMemo(() => {
try {
return downloadedFiles
return (
downloadedFiles
?.filter((f) => f.item.SeriesId == seriesId)
?.sort((a, b) => a?.item.ParentIndexNumber! - b.item.ParentIndexNumber!)
|| [];
?.sort(
(a, b) => a?.item.ParentIndexNumber! - b.item.ParentIndexNumber!
) || []
);
} catch {
return [];
}
}, [downloadedFiles]);
const seasonIndex = seasonIndexState[series?.[0]?.item?.ParentId ?? ""] || episodeSeasonIndex || "";
const seasonIndex =
seasonIndexState[series?.[0]?.item?.ParentId ?? ""] ||
episodeSeasonIndex ||
"";
const groupBySeason = useMemo<BaseItemDto[]>(() => {
const seasons: Record<string, BaseItemDto[]> = {};
@@ -43,13 +54,16 @@ export default function page() {
seasons[episode.item.ParentIndexNumber!].push(episode.item);
});
return seasons[seasonIndex]
?.sort((a, b) => a.IndexNumber! - b.IndexNumber!)
?? []
return (
seasons[seasonIndex]?.sort((a, b) => a.IndexNumber! - b.IndexNumber!) ??
[]
);
}, [series, seasonIndex]);
const initialSeasonIndex = useMemo(() =>
Object.values(groupBySeason)?.[0]?.ParentIndexNumber ?? series?.[0]?.item?.ParentIndexNumber,
const initialSeasonIndex = useMemo(
() =>
Object.values(groupBySeason)?.[0]?.ParentIndexNumber ??
series?.[0]?.item?.ParentIndexNumber,
[groupBySeason]
);
@@ -58,8 +72,7 @@ export default function page() {
navigation.setOptions({
title: series[0].item.SeriesName,
});
}
else {
} else {
storage.delete(seriesId);
router.back();
}
@@ -70,37 +83,38 @@ export default function page() {
[groupBySeason]
);
return (
<>
{series.length > 0 && <View className="my-4 flex flex-row items-center justify-start">
<SeasonDropdown
item={series[0].item}
seasons={series.map(s => s.item)}
state={seasonIndexState}
initialSeasonIndex={initialSeasonIndex!}
onSelect={(season) => {
setSeasonIndexState((prev) => ({
...prev,
[series[0].item.ParentId ?? ""]: season.ParentIndexNumber,
}));
}}/>
<View className="flex flex-row items-center justify-between w-72">
<View className="bg-purple-600 rounded-full h-6 w-6 flex items-center justify-center">
<Text className="text-xs font-bold">{groupBySeason.length}</Text>
</View>
<View className="bg-neutral-800/80 rounded-full h-10 w-10 flex items-center justify-center">
<TouchableOpacity onPress={deleteSeries}>
<Ionicons name="trash" size={22} color="white"/>
</TouchableOpacity>
</View>
<View className="px-4 flex-1">
{series.length > 0 && (
<View className="flex flex-row items-center justify-start my-2">
<SeasonDropdown
item={series[0].item}
seasons={series.map((s) => s.item)}
state={seasonIndexState}
initialSeasonIndex={initialSeasonIndex!}
onSelect={(season) => {
setSeasonIndexState((prev) => ({
...prev,
[series[0].item.ParentId ?? ""]: season.ParentIndexNumber,
}));
}}
/>
<View className="bg-purple-600 rounded-full h-6 w-6 flex items-center justify-center ml-2">
<Text className="text-xs font-bold">{groupBySeason.length}</Text>
</View>
</View>}
<View className="bg-neutral-800/80 rounded-full h-10 w-10 flex items-center justify-center ml-auto">
<TouchableOpacity onPress={deleteSeries}>
<Ionicons name="trash" size={22} color="white" />
</TouchableOpacity>
</View>
</View>
)}
<ScrollView key={seasonIndex}>
{groupBySeason.map((episode, index) => (
<View className="px-4 flex flex-col my-4" key={index}>
<EpisodeCard item={episode}/>
<View className="flex flex-col mb-4" key={index}>
<EpisodeCard item={episode} />
</View>
))}
</ScrollView>
</>
</View>
);
}
}

View File

@@ -44,7 +44,11 @@ export const SeasonDropdown: React.FC<Props> = ({
},
[item]
);
const seasonIndex = useMemo(() => state[item[keys.id] ?? ""], [state]);
const seasonIndex = useMemo(
() => state[(item[keys.id] as string) ?? ""],
[state]
);
useEffect(() => {
if (seasons && seasons.length > 0 && seasonIndex === undefined) {
@@ -80,12 +84,12 @@ export const SeasonDropdown: React.FC<Props> = ({
}, [seasons, seasonIndex, item[keys.id], initialSeasonIndex]);
const sortByIndex = (a: BaseItemDto, b: BaseItemDto) =>
a[keys.index] - b[keys.index];
Number(a[keys.index]) - Number(b[keys.index]);
return (
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<View className="flex flex-row px-4">
<View className="flex flex-row">
<TouchableOpacity className="bg-neutral-900 rounded-2xl border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between">
<Text>Season {seasonIndex}</Text>
</TouchableOpacity>