fix: design

This commit is contained in:
Fredrik Burmester
2024-12-31 13:35:59 +01:00
parent c753e33f38
commit a936916da4
2 changed files with 156 additions and 94 deletions

View File

@@ -38,7 +38,7 @@ import {Tag} from "@/components/GenreTags";
import DiscoverSlide from "@/components/jellyseerr/DiscoverSlide";
import { sortBy } from "lodash";
type SearchType = 'Library' | 'Discover';
type SearchType = "Library" | "Discover";
const exampleSearches = [
"Lord of the rings",
@@ -153,29 +153,41 @@ export default function search() {
const response = await jellyseerrApi?.search({
query: new URLSearchParams(debouncedSearch).toString(),
page: 1, // todo: maybe rework page & page-size if first results are not enough...
language: 'en'
})
language: "en",
});
return response?.results;
},
enabled: !!jellyseerrApi && searchType === "Discover" && debouncedSearch.length > 0,
enabled:
!!jellyseerrApi &&
searchType === "Discover" &&
debouncedSearch.length > 0,
});
const { data: jellyseerrDiscoverSettings, isFetching: j2 } = useQuery({
queryKey: ["search", "jellyseerrDiscoverSettings", debouncedSearch],
queryFn: async () => jellyseerrApi?.discoverSettings(),
enabled: !!jellyseerrApi && searchType === "Discover" && debouncedSearch.length == 0,
enabled:
!!jellyseerrApi &&
searchType === "Discover" &&
debouncedSearch.length == 0,
});
const jellyseerrMovieResults: MovieResult[] | undefined = useMemo(() =>
jellyseerrResults?.filter(r => r.mediaType === MediaType.MOVIE) as MovieResult[],
const jellyseerrMovieResults: MovieResult[] | undefined = useMemo(
() =>
jellyseerrResults?.filter(
(r) => r.mediaType === MediaType.MOVIE
) as MovieResult[],
[jellyseerrResults]
)
);
const jellyseerrTvResults: TvResult[] | undefined = useMemo(() =>
jellyseerrResults?.filter(r => r.mediaType === MediaType.TV) as TvResult[],
const jellyseerrTvResults: TvResult[] | undefined = useMemo(
() =>
jellyseerrResults?.filter(
(r) => r.mediaType === MediaType.TV
) as TvResult[],
[jellyseerrResults]
)
);
const { data: series, isFetching: l2 } = useQuery({
queryKey: ["search", "series", debouncedSearch],
@@ -260,7 +272,17 @@ export default function search() {
jellyseerrMovieResults?.length ||
jellyseerrTvResults?.length
);
}, [artists, episodes, albums, songs, movies, series, collections, actors, jellyseerrResults]);
}, [
artists,
episodes,
albums,
songs,
movies,
series,
collections,
actors,
jellyseerrResults,
]);
const loading = useMemo(() => {
return l1 || l2 || l3 || l4 || l5 || l6 || l7 || l8 || j1 || j2;
@@ -290,14 +312,24 @@ export default function search() {
</View>
)}
{jellyseerrApi && (
<View className="flex flex-row flex-wrap space-x-2 px-4">
<TouchableOpacity onPress={() => setSearchType('Library')}>
<Tag text="Library" textClass="p-1"
className={searchType === "Library" ? "bg-neutral-600" : undefined}/>
<View className="flex flex-row flex-wrap space-x-2 px-4 mb-2">
<TouchableOpacity onPress={() => setSearchType("Library")}>
<Tag
text="Library"
textClass="p-1"
className={
searchType === "Library" ? "bg-neutral-600" : undefined
}
/>
</TouchableOpacity>
<TouchableOpacity onPress={() => setSearchType('Discover')}>
<Tag text="Discover" textClass="p-1"
className={searchType === "Discover" ? "bg-neutral-600" : undefined}/>
<TouchableOpacity onPress={() => setSearchType("Discover")}>
<Tag
text="Discover"
textClass="p-1"
className={
searchType === "Discover" ? "bg-neutral-600" : undefined
}
/>
</TouchableOpacity>
</View>
)}
@@ -468,7 +500,7 @@ export default function search() {
"{debouncedSearch}"
</Text>
</View>
) : debouncedSearch.length === 0 && searchType === 'Library' ? (
) : debouncedSearch.length === 0 && searchType === "Library" ? (
<View className="mt-4 flex flex-col items-center space-y-2">
{exampleSearches.map((e) => (
<TouchableOpacity
@@ -480,11 +512,14 @@ export default function search() {
</TouchableOpacity>
))}
</View>
) : debouncedSearch.length === 0 && searchType === 'Discover' ? (
) : debouncedSearch.length === 0 && searchType === "Discover" ? (
<View className="flex flex-col px-4">
{sortBy?.(jellyseerrDiscoverSettings?.filter(s => s.enabled), 'order')
.map((slide) => <DiscoverSlide key={slide.id} slide={slide}/>)
}
{sortBy?.(
jellyseerrDiscoverSettings?.filter((s) => s.enabled),
"order"
).map((slide) => (
<DiscoverSlide key={slide.id} slide={slide} />
))}
</View>
) : null}
</View>
@@ -500,7 +535,12 @@ type Props<T> = {
header?: string;
};
const SearchItemWrapper = <T extends unknown> ({ ids, items, renderItem, header }: PropsWithChildren<Props<T>>) => {
const SearchItemWrapper = <T extends unknown>({
ids,
items,
renderItem,
header,
}: PropsWithChildren<Props<T>>) => {
const [api] = useAtom(apiAtom);
const [user] = useAtom(userAtom);
@@ -540,14 +580,11 @@ const SearchItemWrapper = <T extends unknown> ({ ids, items, renderItem, header
className="px-4 mb-2"
showsHorizontalScrollIndicator={false}
>
{
data && data?.length > 0
{data && data?.length > 0
? data.map((item) => renderItem(item))
:
items && items?.length > 0
? items.map(i => renderItem(i))
: undefined
}
: items && items?.length > 0
? items.map((i) => renderItem(i))
: undefined}
</ScrollView>
</>
);

View File

@@ -1,15 +1,20 @@
import React, { useMemo } from "react";
import DiscoverSlider from "@/utils/jellyseerr/server/entity/DiscoverSlider";
import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover";
import {DiscoverEndpoint, Endpoints, useJellyseerr} from "@/hooks/useJellyseerr";
import {
DiscoverEndpoint,
Endpoints,
useJellyseerr,
} from "@/hooks/useJellyseerr";
import { useInfiniteQuery } from "@tanstack/react-query";
import { MovieResult, TvResult } from "@/utils/jellyseerr/server/models/Search";
import JellyseerrPoster from "@/components/posters/JellyseerrPoster";
import { Text } from "@/components/common/Text";
import { FlashList } from "@shopify/flash-list";
import { View } from "react-native";
interface Props {
slide: DiscoverSlider
slide: DiscoverSlider;
}
const DiscoverSlide: React.FC<Props> = ({ slide }) => {
const { jellyseerrApi } = useJellyseerr();
@@ -19,8 +24,8 @@ const DiscoverSlide: React.FC<Props> = ({slide}) => {
queryFn: async ({ pageParam }) => {
let endpoint: DiscoverEndpoint | undefined = undefined;
let params: any = {
page: Number(pageParam)
}
page: Number(pageParam),
};
switch (slide.type) {
case DiscoverSliderType.TRENDING:
@@ -28,48 +33,68 @@ const DiscoverSlide: React.FC<Props> = ({slide}) => {
break;
case DiscoverSliderType.POPULAR_MOVIES:
case DiscoverSliderType.UPCOMING_MOVIES:
endpoint = Endpoints.DISCOVER_MOVIES
endpoint = Endpoints.DISCOVER_MOVIES;
if (slide.type === DiscoverSliderType.UPCOMING_MOVIES)
params = { ...params, primaryReleaseDateGte: new Date().toISOString().split('T')[0]}
params = {
...params,
primaryReleaseDateGte: new Date().toISOString().split("T")[0],
};
break;
case DiscoverSliderType.POPULAR_TV:
case DiscoverSliderType.UPCOMING_TV:
endpoint = Endpoints.DISCOVER_TV
endpoint = Endpoints.DISCOVER_TV;
if (slide.type === DiscoverSliderType.UPCOMING_TV)
params = {...params, firstAirDateGte: new Date().toISOString().split('T')[0]}
params = {
...params,
firstAirDateGte: new Date().toISOString().split("T")[0],
};
break;
}
return endpoint ? jellyseerrApi?.discover(endpoint, params) : null;
},
initialPageParam: 1,
getNextPageParam: (lastPage, pages) => ((lastPage?.page || pages?.findLast(p => p?.results.length)?.page) || 1) + 1,
getNextPageParam: (lastPage, pages) =>
(lastPage?.page || pages?.findLast((p) => p?.results.length)?.page || 1) +
1,
enabled: !!jellyseerrApi,
staleTime: 0
staleTime: 0,
});
const flatData = useMemo(() => data?.pages?.filter(p => p?.results.length).flatMap(p => p?.results), [data])
const flatData = useMemo(
() =>
data?.pages?.filter((p) => p?.results.length).flatMap((p) => p?.results),
[data]
);
return (
(flatData && flatData?.length > 0) && <>
<Text className="mt-4 font-bold text-lg mb-2">{DiscoverSliderType[slide.type].toString().toTitle()}</Text>
flatData &&
flatData?.length > 0 && (
<View className="mb-4">
<Text className="font-bold text-lg mb-2">
{DiscoverSliderType[slide.type].toString().toTitle()}
</Text>
<FlashList
horizontal
showsHorizontalScrollIndicator={false}
keyExtractor={item => item!!.id.toString()}
keyExtractor={(item) => item!!.id.toString()}
estimatedItemSize={250}
data={flatData}
onEndReachedThreshold={1}
onEndReached={() => {
if (hasNextPage)
fetchNextPage()
if (hasNextPage) fetchNextPage();
}}
renderItem={({ item }) =>
(item ? <JellyseerrPoster item={item as MovieResult | TvResult} /> : <></>)
}
/>
</>
item ? (
<JellyseerrPoster item={item as MovieResult | TvResult} />
) : (
<></>
)
}
/>
</View>
)
);
};
export default DiscoverSlide;