From caeedfbc52e43eeef1beeca489d478ee976ffdc7 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Mon, 19 Aug 2024 21:43:48 +0200 Subject: [PATCH] fix: separate item and show bar state --- app/(auth)/items/[id].tsx | 14 ++- components/CurrentlyPlayingBar.tsx | 65 +++++++------ providers/JellyfinProvider.tsx | 94 +++++++++++++++++-- utils/atoms/playState.ts | 10 ++ utils/atoms/settings.ts | 4 + .../playstate/reportPlaybackProgress.ts | 41 +++++--- .../playstate/reportPlaybackStopped.ts | 7 +- utils/jellyfin/session/capabilities.ts | 48 ++++++++++ 8 files changed, 227 insertions(+), 56 deletions(-) create mode 100644 utils/atoms/playState.ts create mode 100644 utils/jellyfin/session/capabilities.ts diff --git a/app/(auth)/items/[id].tsx b/app/(auth)/items/[id].tsx index 91cbc7cf..05c78a69 100644 --- a/app/(auth)/items/[id].tsx +++ b/app/(auth)/items/[id].tsx @@ -1,10 +1,5 @@ import { AudioTrackSelector } from "@/components/AudioTrackSelector"; import { Bitrate, BitrateSelector } from "@/components/BitrateSelector"; -import { - currentlyPlayingItemAtom, - fullScreenAtom, - playingAtom, -} from "@/components/CurrentlyPlayingBar"; import { DownloadItem } from "@/components/DownloadItem"; import { Loader } from "@/components/Loader"; import { OverviewText } from "@/components/OverviewText"; @@ -42,6 +37,12 @@ import CastContext, { useRemoteMediaClient, } from "react-native-google-cast"; import { ParallaxScrollView } from "../../../components/ParallaxPage"; +import { + currentlyPlayingItemAtom, + fullScreenAtom, + playingAtom, + showCurrentlyPlayingBarAtom, +} from "@/utils/atoms/playState"; const page: React.FC = () => { const local = useLocalSearchParams(); @@ -55,6 +56,7 @@ const page: React.FC = () => { const castDevice = useCastDevice(); const [, setCurrentlyPlying] = useAtom(currentlyPlayingItemAtom); + const [, setShowCurrentlyPlayingBar] = useAtom(showCurrentlyPlayingBarAtom); const [, setPlaying] = useAtom(playingAtom); const [, setFullscreen] = useAtom(fullScreenAtom); @@ -168,6 +170,8 @@ const page: React.FC = () => { playbackUrl, }); setPlaying(true); + setShowCurrentlyPlayingBar(true); + if (settings?.openFullScreenVideoPlayerByDefault === true) { setFullscreen(true); } diff --git a/components/CurrentlyPlayingBar.tsx b/components/CurrentlyPlayingBar.tsx index 5afdf6ae..61854a5f 100644 --- a/components/CurrentlyPlayingBar.tsx +++ b/components/CurrentlyPlayingBar.tsx @@ -1,4 +1,10 @@ import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; +import { + currentlyPlayingItemAtom, + fullScreenAtom, + playingAtom, + showCurrentlyPlayingBarAtom, +} from "@/utils/atoms/playState"; import { getBackdropUrl } from "@/utils/jellyfin/image/getBackdropUrl"; import { getAuthHeaders } from "@/utils/jellyfin/jellyfin"; import { reportPlaybackProgress } from "@/utils/jellyfin/playstate/reportPlaybackProgress"; @@ -6,12 +12,11 @@ import { reportPlaybackStopped } from "@/utils/jellyfin/playstate/reportPlayback import { getUserItemData } from "@/utils/jellyfin/user-library/getUserItemData"; import { writeToLog } from "@/utils/log"; import { Ionicons } from "@expo/vector-icons"; -import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { getMediaInfoApi } from "@jellyfin/sdk/lib/utils/api"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { BlurView } from "expo-blur"; import { useRouter, useSegments } from "expo-router"; -import { atom, useAtom } from "jotai"; +import { useAtom } from "jotai"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Alert, Platform, TouchableOpacity, View } from "react-native"; import Animated, { @@ -23,17 +28,9 @@ import Video, { OnProgressData, VideoRef } from "react-native-video"; import { Text } from "./common/Text"; import { Loader } from "./Loader"; -export const currentlyPlayingItemAtom = atom<{ - item: BaseItemDto; - playbackUrl: string; -} | null>(null); - -export const playingAtom = atom(false); -export const fullScreenAtom = atom(false); - export const CurrentlyPlayingBar: React.FC = () => { - const queryClient = useQueryClient(); const segments = useSegments(); + const queryClient = useQueryClient(); const [api] = useAtom(apiAtom); const [user] = useAtom(userAtom); @@ -42,6 +39,7 @@ export const CurrentlyPlayingBar: React.FC = () => { currentlyPlayingItemAtom ); const [fullScreen, setFullScreen] = useAtom(fullScreenAtom); + const [show, setShow] = useAtom(showCurrentlyPlayingBarAtom); const videoRef = useRef(null); const [progress, setProgress] = useState(0); @@ -120,21 +118,26 @@ export const CurrentlyPlayingBar: React.FC = () => { const onProgress = useCallback( ({ currentTime }: OnProgressData) => { - if ( - !currentTime || - !sessionData?.PlaySessionId || - !playing || - !api || - !currentlyPlaying?.item.Id - ) + if (!sessionData?.PlaySessionId || !api || !currentlyPlaying?.item.Id) return; const newProgress = currentTime * 10000000; setProgress(newProgress); + reportPlaybackProgress({ api, itemId: currentlyPlaying?.item.Id, positionTicks: newProgress, sessionId: sessionData.PlaySessionId, + IsPaused: !playing, + }); + + queryClient.invalidateQueries({ + queryKey: ["nextUp", item?.SeriesId], + refetchType: "all", + }); + queryClient.invalidateQueries({ + queryKey: ["episodes"], + refetchType: "all", }); }, [sessionData?.PlaySessionId, api, playing, currentlyPlaying?.item.Id] @@ -147,13 +150,6 @@ export const CurrentlyPlayingBar: React.FC = () => { videoRef.current?.resume(); } else { videoRef.current?.pause(); - if (progress > 0 && sessionData?.PlaySessionId) - reportPlaybackStopped({ - api, - itemId: item?.Id, - positionTicks: progress, - sessionId: sessionData?.PlaySessionId, - }); queryClient.invalidateQueries({ queryKey: ["nextUp", item?.SeriesId], @@ -174,6 +170,17 @@ export const CurrentlyPlayingBar: React.FC = () => { } }, [fullScreen]); + useEffect(() => { + if (!show && currentlyPlaying && item && sessionData && api) { + reportPlaybackStopped({ + api, + itemId: item?.Id, + sessionId: sessionData?.PlaySessionId, + positionTicks: progress, + }); + } + }, [show]); + const startPosition = useMemo( () => item?.UserData?.PlaybackPositionTicks @@ -193,7 +200,7 @@ export const CurrentlyPlayingBar: React.FC = () => { [item] ); - if (!currentlyPlaying || !api) return null; + if (show === false || !api) return null; return ( { ${item?.Type === "Audio" ? "aspect-square" : "aspect-video"} `} > - {currentlyPlaying.playbackUrl && ( + {currentlyPlaying?.playbackUrl && (