feat: library list design

This commit is contained in:
Fredrik Burmester
2024-08-25 10:34:54 +02:00
parent 70d0ec4780
commit ec5aab99b8
7 changed files with 443 additions and 110 deletions

View File

@@ -9,7 +9,7 @@ import React, {
useMemo,
useState,
} from "react";
import { FlatList, View } from "react-native";
import { FlatList, RefreshControl, View } from "react-native";
import { Text } from "@/components/common/Text";
import { TouchableItemRouter } from "@/components/common/TouchableItemRouter";
@@ -38,6 +38,7 @@ import {
getUserLibraryApi,
} from "@jellyfin/sdk/lib/utils/api";
import { FlashList } from "@shopify/flash-list";
import { Loader } from "@/components/Loader";
const MemoizedTouchableItemRouter = React.memo(TouchableItemRouter);
@@ -90,7 +91,7 @@ const Page = () => {
};
}, []);
const { data: library } = useQuery({
const { data: library, isLoading: isLibraryLoading } = useQuery({
queryKey: ["library", libraryId],
queryFn: async () => {
if (!api) return null;
@@ -101,7 +102,7 @@ const Page = () => {
return response.data;
},
enabled: !!api && !!user?.Id && !!libraryId,
staleTime: 0,
staleTime: 60 * 1000,
});
const fetchItems = useCallback(
@@ -112,28 +113,6 @@ const Page = () => {
}): Promise<BaseItemDtoQueryResult | null> => {
if (!api || !library) return null;
let includeItemTypes: BaseItemKind[] | undefined = [];
console.log("Page:", pageParam);
// switch (library?.CollectionType) {
// case "movies":
// includeItemTypes.push("Movie");
// break;
// case "boxsets":
// includeItemTypes.push("BoxSet");
// break;
// case "tvshows":
// includeItemTypes.push("Series");
// break;
// case "music":
// includeItemTypes.push("MusicAlbum");
// break;
// default:
// includeItemTypes = ["Series", "Movie", "CollectionFolder"];
// break;
// }
const response = await getItemsApi(api).getItems({
userId: user?.Id,
parentId: libraryId,
@@ -141,7 +120,6 @@ const Page = () => {
startIndex: pageParam,
sortBy: [sortBy[0].key, "SortName", "ProductionYear"],
sortOrder: [sortOrder[0].key],
includeItemTypes,
enableImageTypes: ["Primary", "Backdrop", "Banner", "Thumb"],
recursive: false,
imageTypeLimit: 1,
@@ -166,40 +144,41 @@ const Page = () => {
]
);
const { data, isFetching, fetchNextPage, hasNextPage } = useInfiniteQuery({
queryKey: [
"library-items",
libraryId,
selectedGenres,
selectedYears,
selectedTags,
sortBy,
sortOrder,
],
queryFn: fetchItems,
getNextPageParam: (lastPage, pages) => {
if (
!lastPage?.Items ||
!lastPage?.TotalRecordCount ||
lastPage?.TotalRecordCount === 0
)
return undefined;
const { data, isFetching, fetchNextPage, hasNextPage, isLoading } =
useInfiniteQuery({
queryKey: [
"library-items",
libraryId,
selectedGenres,
selectedYears,
selectedTags,
sortBy,
sortOrder,
],
queryFn: fetchItems,
getNextPageParam: (lastPage, pages) => {
if (
!lastPage?.Items ||
!lastPage?.TotalRecordCount ||
lastPage?.TotalRecordCount === 0
)
return undefined;
const totalItems = lastPage.TotalRecordCount;
const accumulatedItems = pages.reduce(
(acc, curr) => acc + (curr?.Items?.length || 0),
0
);
const totalItems = lastPage.TotalRecordCount;
const accumulatedItems = pages.reduce(
(acc, curr) => acc + (curr?.Items?.length || 0),
0
);
if (accumulatedItems < totalItems) {
return lastPage?.Items?.length * pages.length;
} else {
return undefined;
}
},
initialPageParam: 0,
enabled: !!api && !!user?.Id && !!library,
});
if (accumulatedItems < totalItems) {
return lastPage?.Items?.length * pages.length;
} else {
return undefined;
}
},
initialPageParam: 0,
enabled: !!api && !!user?.Id && !!library,
});
const flatData = useMemo(() => {
return (
@@ -396,7 +375,19 @@ const Page = () => {
]
);
if (!library) return null;
if (isLoading || isLibraryLoading)
return (
<View className="w-full h-full flex items-center justify-center">
<Loader />
</View>
);
if (flatData.length === 0)
return (
<View className="h-full w-full flex justify-center items-center">
<Text className="text-lg text-neutral-500">No items found</Text>
</View>
);
return (
<FlashList