This commit is contained in:
Fredrik Burmester
2024-09-25 08:28:36 +02:00
parent 8936a559de
commit 09dafea4ad
5 changed files with 148 additions and 144 deletions

View File

@@ -157,43 +157,34 @@ export default function index() {
if (!api || !user?.Id) return [];
const ss: Section[] = [
{
title: "Continue Watching",
queryKey: ["resumeItems", user.Id],
queryFn: async () =>
(
await getItemsApi(api).getResumeItems({
userId: user.Id,
enableImageTypes: ["Primary", "Backdrop", "Thumb"],
})
).data.Items || [],
type: "ScrollingCollectionList",
orientation: "horizontal",
},
{
title: "Next Up",
queryKey: ["nextUp-all", user?.Id],
queryFn: async () =>
(
await getTvShowsApi(api).getNextUp({
userId: user?.Id,
fields: ["MediaSourceCount"],
limit: 20,
enableImageTypes: ["Primary", "Backdrop", "Thumb"],
})
).data.Items || [],
type: "ScrollingCollectionList",
orientation: "horizontal",
},
...(mediaListCollections?.map(
(ml) =>
({
title: ml.Name || "",
queryKey: ["mediaList", ml.Id],
queryFn: async () => ml,
type: "MediaListSection",
} as MediaListSection)
) || []),
// {
// title: "Continue Watching",
// queryKey: ["resumeItems", user.Id],
// queryFn: async () =>
// (
// await getItemsApi(api).getResumeItems({
// userId: user.Id,
// enableImageTypes: ["Primary", "Backdrop", "Thumb"],
// })
// ).data.Items || [],
// type: "ScrollingCollectionList",
// orientation: "horizontal",
// },
// {
// title: "Next Up",
// queryKey: ["nextUp-all", user?.Id],
// queryFn: async () =>
// (
// await getTvShowsApi(api).getNextUp({
// userId: user?.Id,
// fields: ["MediaSourceCount"],
// limit: 20,
// enableImageTypes: ["Primary", "Backdrop", "Thumb"],
// })
// ).data.Items || [],
// type: "ScrollingCollectionList",
// orientation: "horizontal",
// },
{
title: "Recently Added in Movies",
queryKey: ["recentlyAddedInMovies", user?.Id, movieCollectionId],
@@ -228,6 +219,15 @@ export default function index() {
).data || [],
type: "ScrollingCollectionList",
},
...(mediaListCollections?.map(
(ml) =>
({
title: ml.Name || "",
queryKey: ["mediaList", ml.Id],
queryFn: async () => ml,
type: "MediaListSection",
} as MediaListSection)
) || []),
{
title: "Suggested Movies",
queryKey: ["suggestedMovies", user?.Id],
@@ -317,7 +317,7 @@ export default function index() {
const insets = useSafeAreaInsets();
if (e1 || e2)
if (e1 || e2 || !api)
return (
<View className="flex flex-col items-center justify-center h-full -mt-6">
<Text className="text-3xl font-bold mb-2">Oops!</Text>
@@ -341,39 +341,69 @@ export default function index() {
refreshControl={
<RefreshControl refreshing={loading} onRefresh={refetch} />
}
key={"home"}
contentContainerStyle={{
paddingLeft: insets.left,
paddingRight: insets.right,
}}
className="flex flex-col space-y-4 mb-20"
>
<View
style={{
paddingLeft: insets.left,
paddingRight: insets.right,
}}
className="flex flex-col pt-4 pb-24 gap-y-2"
>
<LargeMovieCarousel />
<LargeMovieCarousel />
{sections.map((section, index) => {
if (section.type === "ScrollingCollectionList") {
return (
<ScrollingCollectionList
key={index}
title={section.title}
queryKey={section.queryKey}
queryFn={section.queryFn}
orientation={section.orientation}
/>
);
} else if (section.type === "MediaListSection") {
return (
<MediaListSection
key={index}
queryKey={section.queryKey}
queryFn={section.queryFn}
/>
);
}
return null;
})}
</View>
<ScrollingCollectionList
key="nextUp"
title={"Next Up"}
queryKey={["nextUp-all", user?.Id]}
queryFn={async () =>
(
await getTvShowsApi(api).getNextUp({
userId: user?.Id,
fields: ["MediaSourceCount"],
limit: 20,
enableImageTypes: ["Primary", "Backdrop", "Thumb"],
})
).data.Items|| []
}
orientation={"horizontal"}
/>
<ScrollingCollectionList
key="continueWatching"
title={"Continue Watching"}
queryKey={["continueWatching", user?.Id]}
queryFn={async () =>
(
await getItemsApi(api).getResumeItems({
userId: user?.Id,
enableImageTypes: ["Primary", "Backdrop", "Thumb"],
})
).data.Items || []
}
orientation={"horizontal"}
/>
{sections.map((section, index) => {
if (section.type === "ScrollingCollectionList") {
return (
<ScrollingCollectionList
key={index}
title={section.title}
queryKey={section.queryKey}
queryFn={section.queryFn}
orientation={section.orientation}
/>
);
} else if (section.type === "MediaListSection") {
return (
<MediaListSection
key={index}
queryKey={section.queryKey}
queryFn={section.queryFn}
/>
);
}
return null;
})}
</ScrollView>
);
}

View File

@@ -76,10 +76,7 @@ const ContinueWatchingPoster: React.FC<ContinueWatchingPosterProps> = ({
{progress > 0 && (
<>
<View
style={{
width: `100%`,
}}
className={`absolute bottom-0 left-0 h-1 bg-neutral-700 opacity-80 w-full`}
className={`absolute w-100 bottom-0 left-0 h-1 bg-neutral-700 opacity-80 w-full`}
></View>
<View
style={{

View File

@@ -1,51 +1,41 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
View,
TouchableOpacity,
Alert,
Dimensions,
BackHandler,
Pressable,
Touchable,
} from "react-native";
import Video, { OnProgressData } from "react-native-video";
import { Slider } from "react-native-awesome-slider";
import { Ionicons } from "@expo/vector-icons";
import { useAdjacentEpisodes } from "@/hooks/useAdjacentEpisodes";
import { useCreditSkipper } from "@/hooks/useCreditSkipper";
import { useIntroSkipper } from "@/hooks/useIntroSkipper";
import { useTrickplay } from "@/hooks/useTrickplay";
import { apiAtom } from "@/providers/JellyfinProvider";
import { usePlayback } from "@/providers/PlaybackProvider";
import { useSettings } from "@/utils/atoms/settings";
import { useAdjacentEpisodes } from "@/hooks/useAdjacentEpisodes";
import { useTrickplay } from "@/hooks/useTrickplay";
import { Text } from "./common/Text";
import { Loader } from "./Loader";
import { getBackdropUrl } from "@/utils/jellyfin/image/getBackdropUrl";
import { getAuthHeaders } from "@/utils/jellyfin/jellyfin";
import { writeToLog } from "@/utils/log";
import { useRouter, useSegments } from "expo-router";
import { itemRouter } from "./common/TouchableItemRouter";
import orientationToOrientationLock from "@/utils/OrientationLockConverter";
import { secondsToTicks } from "@/utils/secondsToTicks";
import { formatTimeString, ticksToSeconds } from "@/utils/time";
import { Ionicons } from "@expo/vector-icons";
import { Image } from "expo-image";
import { StatusBar } from "expo-status-bar";
import { useRouter, useSegments } from "expo-router";
import * as ScreenOrientation from "expo-screen-orientation";
import { useAtom } from "jotai";
import { apiAtom } from "@/providers/JellyfinProvider";
import { useQuery } from "@tanstack/react-query";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
Alert,
BackHandler,
Dimensions,
Pressable,
TouchableOpacity,
View,
} from "react-native";
import { Slider } from "react-native-awesome-slider";
import {
runOnJS,
useAnimatedReaction,
useSharedValue,
} from "react-native-reanimated";
import { secondsToTicks } from "@/utils/secondsToTicks";
import { getAuthHeaders } from "@/utils/jellyfin/jellyfin";
import { getBackdropUrl } from "@/utils/jellyfin/image/getBackdropUrl";
import {
useSafeAreaFrame,
useSafeAreaInsets,
} from "react-native-safe-area-context";
import orientationToOrientationLock from "@/utils/OrientationLockConverter";
import {
formatTimeString,
runtimeTicksToSeconds,
ticksToSeconds,
} from "@/utils/time";
import { useIntroSkipper } from "@/hooks/useIntroSkipper";
import { useCreditSkipper } from "@/hooks/useCreditSkipper";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import Video, { OnProgressData } from "react-native-video";
import { Text } from "./common/Text";
import { itemRouter } from "./common/TouchableItemRouter";
import { Loader } from "./Loader";
const windowDimensions = Dimensions.get("window");
const screenDimensions = Dimensions.get("screen");
@@ -56,7 +46,6 @@ export const FullScreenVideoPlayer: React.FC = () => {
pauseVideo,
playVideo,
stopPlayback,
setVolume,
setIsPlaying,
isPlaying,
videoRef,
@@ -77,7 +66,6 @@ export const FullScreenVideoPlayer: React.FC = () => {
const [showControls, setShowControls] = useState(true);
const [isBuffering, setIsBufferingState] = useState(true);
const [ignoreSafeArea, setIgnoreSafeArea] = useState(false);
const [isStatusBarHidden, setIsStatusBarHidden] = useState(false);
// Seconds
const [currentTime, setCurrentTime] = useState(0);

View File

@@ -84,13 +84,7 @@ export const LargeMovieCarousel: React.FC<Props> = ({ ...props }) => {
const width = Dimensions.get("screen").width;
if (l1 || l2)
return (
<View className="h-[242px] flex items-center justify-center">
<Loader />
</View>
);
if (l1 || l2) return null;
if (!popularItems) return null;
return (

View File

@@ -1,6 +1,5 @@
import { Text } from "@/components/common/Text";
import MoviePoster from "@/components/posters/MoviePoster";
import { useSettings } from "@/utils/atoms/settings";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import {
useQuery,
@@ -17,7 +16,6 @@ import SeriesPoster from "../posters/SeriesPoster";
interface Props extends ViewProps {
title?: string | null;
orientation?: "horizontal" | "vertical";
height?: "small" | "large";
disabled?: boolean;
queryKey: QueryKey;
queryFn: QueryFunction<BaseItemDto[]>;
@@ -26,13 +24,11 @@ interface Props extends ViewProps {
export const ScrollingCollectionList: React.FC<Props> = ({
title,
orientation = "vertical",
height = "small",
disabled = false,
queryFn,
queryKey,
...props
}) => {
const [settings] = useSettings();
const { data, isLoading } = useQuery({
queryKey,
queryFn,
@@ -49,32 +45,31 @@ export const ScrollingCollectionList: React.FC<Props> = ({
</Text>
<HorizontalScroll
data={data}
height={orientation === "vertical" ? 247 : 164}
extraData={[orientation, isLoading]}
loading={isLoading}
renderItem={(item, index) => (
<TouchableItemRouter
key={index}
item={item}
className={`flex flex-col
${orientation === "horizontal" ? "w-44" : "w-28"}
`}
key={index}
style={{
width: orientation === "horizontal" ? 176 : 112,
zIndex: 100,
}}
>
<View>
{item.Type === "Episode" && orientation === "horizontal" && (
<ContinueWatchingPoster item={item} />
)}
{item.Type === "Episode" && orientation === "vertical" && (
<SeriesPoster item={item} />
)}
{item.Type === "Movie" && orientation === "horizontal" && (
<ContinueWatchingPoster item={item} />
)}
{item.Type === "Movie" && orientation === "vertical" && (
<MoviePoster item={item} />
)}
{item.Type === "Series" && <SeriesPoster item={item} />}
<ItemCardText item={item} />
</View>
{item.Type === "Episode" && orientation === "horizontal" && (
<ContinueWatchingPoster item={item} />
)}
{item.Type === "Episode" && orientation === "vertical" && (
<SeriesPoster item={item} />
)}
{item.Type === "Movie" && orientation === "horizontal" && (
<ContinueWatchingPoster item={item} />
)}
{item.Type === "Movie" && orientation === "vertical" && (
<MoviePoster item={item} />
)}
{item.Type === "Series" && <SeriesPoster item={item} />}
<ItemCardText item={item} />
</TouchableItemRouter>
)}
/>