This commit is contained in:
Fredrik Burmester
2024-10-02 22:07:13 +02:00
parent 1df7d8e8fe
commit 60981504fc
15 changed files with 199 additions and 92 deletions

View File

@@ -5,6 +5,7 @@ import { useAtom } from "jotai";
import { useMemo, useState } from "react";
import { View } from "react-native";
import { WatchedIndicator } from "./WatchedIndicator";
import React from "react";
type ContinueWatchingPosterProps = {
item: BaseItemDto;
@@ -14,7 +15,6 @@ type ContinueWatchingPosterProps = {
const ContinueWatchingPoster: React.FC<ContinueWatchingPosterProps> = ({
item,
width = 176,
useEpisodePoster = false,
}) => {
const [api] = useAtom(apiAtom);
@@ -47,21 +47,11 @@ const ContinueWatchingPoster: React.FC<ContinueWatchingPosterProps> = ({
if (!url)
return (
<View
className="aspect-video border border-neutral-800"
style={{
width,
}}
></View>
<View className="aspect-video border border-neutral-800 w-44"></View>
);
return (
<View
style={{
width,
}}
className="relative aspect-video rounded-lg overflow-hidden border border-neutral-800"
>
<View className="relative w-44 aspect-video rounded-lg overflow-hidden border border-neutral-800">
<Image
key={item.Id}
id={item.Id}

View File

@@ -23,7 +23,11 @@ export const ListItem: React.FC<PropsWithChildren<Props>> = ({
>
<View className="flex flex-col">
<Text className="font-bold ">{title}</Text>
{subTitle && <Text className="text-xs">{subTitle}</Text>}
{subTitle && (
<Text className="text-xs" selectable>
{subTitle}
</Text>
)}
</View>
{iconAfter}
</View>

View File

@@ -21,11 +21,17 @@ export const PlayedStatus: React.FC<Props> = ({ item, ...props }) => {
const invalidateQueries = () => {
queryClient.invalidateQueries({
queryKey: ["item"],
queryKey: ["item", item.Id],
});
queryClient.invalidateQueries({
queryKey: ["resumeItems"],
});
queryClient.invalidateQueries({
queryKey: ["continueWatching"],
});
queryClient.invalidateQueries({
queryKey: ["nextUp-all"],
});
queryClient.invalidateQueries({
queryKey: ["nextUp"],
});

View File

@@ -98,7 +98,6 @@ export const HorizontalScroll = forwardRef<
</Text>
</View>
)}
{...props}
/>
);
}

View File

@@ -6,12 +6,13 @@ import {
type QueryFunction,
type QueryKey,
} from "@tanstack/react-query";
import { View, ViewProps } from "react-native";
import { ScrollView, View, ViewProps } from "react-native";
import ContinueWatchingPoster from "../ContinueWatchingPoster";
import { ItemCardText } from "../ItemCardText";
import { HorizontalScroll } from "../common/HorrizontalScroll";
import { TouchableItemRouter } from "../common/TouchableItemRouter";
import SeriesPoster from "../posters/SeriesPoster";
import { FlashList } from "@shopify/flash-list";
interface Props extends ViewProps {
title?: string | null;
@@ -39,40 +40,56 @@ export const ScrollingCollectionList: React.FC<Props> = ({
if (disabled || !title) return null;
return (
<View {...props}>
<View {...props} className="">
<Text className="px-4 text-lg font-bold mb-2 text-neutral-100">
{title}
</Text>
<HorizontalScroll
data={data}
extraData={[orientation, isLoading]}
loading={isLoading}
renderItem={(item, index) => (
<TouchableItemRouter
item={item}
key={index}
style={{
width: orientation === "horizontal" ? 176 : 112,
zIndex: 100,
}}
>
{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>
)}
/>
{isLoading ? (
<View
className={`
flex flex-row gap-2 px-4
`}
>
{[1, 2, 3].map((i) => (
<View className="w-44 mb-2">
<View className="bg-neutral-800 h-24 w-full rounded-md mb-2"></View>
<View className="bg-neutral-800 h-4 w-full rounded-md mb-2"></View>
<View className="bg-neutral-800 h-4 w-1/2 rounded-md"></View>
</View>
))}
</View>
) : (
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View className="px-4 flex flex-row">
{data?.map((item, index) => (
<TouchableItemRouter
item={item}
key={index}
className={`
mr-2
${orientation === "horizontal" ? "w-44" : "w-28"}
`}
>
{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>
))}
</View>
</ScrollView>
)}
</View>
);
};

View File

@@ -36,7 +36,7 @@ const MoviePoster: React.FC<MoviePosterProps> = ({
}, [item]);
return (
<View className="relative rounded-lg overflow-hidden border border-neutral-900">
<View className="relative rounded-lg overflow-hidden border border-neutral-900 w-28 aspect-[10/15]">
<Image
placeholder={{
blurhash,
@@ -57,7 +57,6 @@ const MoviePoster: React.FC<MoviePosterProps> = ({
width: "100%",
}}
/>
<WatchedIndicator item={item} />
{showProgress && progress > 0 && (
<View className="h-1 bg-red-600 w-full"></View>

View File

@@ -32,7 +32,7 @@ const SeriesPoster: React.FC<MoviePosterProps> = ({ item }) => {
}, [item]);
return (
<View className="relative rounded-lg overflow-hidden border border-neutral-900">
<View className="w-28 aspect-[10/15] relative rounded-lg overflow-hidden border border-neutral-900 ">
<Image
placeholder={{
blurhash,
@@ -49,7 +49,7 @@ const SeriesPoster: React.FC<MoviePosterProps> = ({ item }) => {
cachePolicy={"memory-disk"}
contentFit="cover"
style={{
aspectRatio: "10/15",
height: "100%",
width: "100%",
}}
/>

View File

@@ -1,5 +1,9 @@
import { useDownload } from "@/providers/DownloadProvider";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import {
apiAtom,
getOrSetDeviceId,
userAtom,
} from "@/providers/JellyfinProvider";
import { ScreenOrientationEnum, useSettings } from "@/utils/atoms/settings";
import {
BACKGROUND_FETCH_TASK,
@@ -28,6 +32,8 @@ import { Input } from "../common/Input";
import { Text } from "../common/Text";
import { Loader } from "../Loader";
import { MediaToggles } from "./MediaToggles";
import axios from "axios";
import { getStatistics } from "@/utils/optimize-server";
interface Props extends ViewProps {}
@@ -44,6 +50,21 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
const queryClient = useQueryClient();
const { data: optimizeServerStatistics } = useQuery({
queryKey: ["optimize-server", settings?.optimizedVersionsServerUrl],
queryFn: async () =>
getStatistics({
url: settings?.optimizedVersionsServerUrl,
authHeader: api?.accessToken,
deviceId: await getOrSetDeviceId(),
}),
refetchInterval: 1000,
staleTime: 0,
enabled:
!!settings?.optimizedVersionsServerUrl &&
settings.optimizedVersionsServerUrl.length > 0,
});
/********************
* Background task
*******************/
@@ -568,11 +589,24 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
>
<View className="flex flex-col bg-neutral-900 px-4 py-4">
<View className="flex flex-col shrink mb-2">
<Text className="font-semibold">Optimized versions server</Text>
<View className="flex flex-row justify-between items-center">
<Text className="font-semibold">
Optimized versions server
</Text>
<View
className={`
w-3 h-3 rounded-full
${
optimizeServerStatistics ? "bg-green-600" : "bg-red-600"
}
`}
></View>
</View>
<Text className="text-xs opacity-50">
Set the URL for the optimized versions server for downloads.
</Text>
</View>
<View></View>
<View className="flex flex-col">
<Input
placeholder="Optimized versions server URL..."
@@ -587,7 +621,7 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
color="purple"
className="h-12 mt-2"
onPress={() => {
toast.success("Saved");
toast.info("Saved");
updateSettings({
optimizedVersionsServerUrl:
optimizedVersionsServerUrl.length === 0