diff --git a/front/packages/ui/src/player/index.tsx b/front/packages/ui/src/player/index.tsx index c870cb24..9b69881f 100644 --- a/front/packages/ui/src/player/index.tsx +++ b/front/packages/ui/src/player/index.tsx @@ -36,7 +36,7 @@ import { useRouter } from "solito/router"; import { useSetAtom } from "jotai"; import { useYoshiki } from "yoshiki/native"; import { Back, Hover, LoadingIndicator } from "./components/hover"; -import { fullscreenAtom, Video } from "./state"; +import { fullscreenAtom, progressAtom, Video } from "./state"; import { episodeDisplayNumber } from "../details/episode"; import { useVideoKeyboard } from "./keyboard"; import { MediaSessionManager } from "./media-session"; @@ -140,6 +140,7 @@ export const Player = ({ slug, type }: { slug: string; type: "episode" | "movie" subtitles={info?.subtitles} setError={setPlaybackError} fonts={info?.fonts} + startTime={data?.watchStatus?.watchedTime} onEnd={() => { if (!data) return; if (data.type === "movie") @@ -167,12 +168,15 @@ Player.query = (type: "episode" | "movie", slug: string): QueryIdentifier ? { path: ["episode", slug], params: { - fields: ["nextEpisode", "previousEpisode", "show"], + fields: ["nextEpisode", "previousEpisode", "show", "watchStatus"], }, parser: EpisodeP.transform((x) => ({ ...x, type: "episode" })), } : { path: ["movie", slug], + params: { + fields: ["watchStatus"], + }, parser: MovieP.transform((x) => ({ ...x, type: "movie" })), }; diff --git a/front/packages/ui/src/player/state.tsx b/front/packages/ui/src/player/state.tsx index eea8fa2d..790f8dd5 100644 --- a/front/packages/ui/src/player/state.tsx +++ b/front/packages/ui/src/player/state.tsx @@ -88,12 +88,14 @@ export const Video = memo(function Video({ subtitles, setError, fonts, + startTime, ...props }: { links?: Episode["links"]; subtitles?: Subtitle[]; setError: (error: string | undefined) => void; fonts?: string[]; + startTime?: number | null; } & Partial) { const ref = useRef | null>(null); const [isPlaying, setPlay] = useAtom(playAtom); @@ -148,6 +150,7 @@ export const Video = memo(function Video({ {...props} source={{ uri: source, + startPosition: startTime ? startTime * 1000 : undefined, ...links, }} paused={!isPlaying} diff --git a/front/packages/ui/src/player/video.tsx b/front/packages/ui/src/player/video.tsx index 666e2197..17675fda 100644 --- a/front/packages/ui/src/player/video.tsx +++ b/front/packages/ui/src/player/video.tsx @@ -28,7 +28,7 @@ declare module "react-native-video" { onMediaUnsupported?: () => void; } export type VideoProps = Omit & { - source: { uri: string; hls: string | null }; + source: { uri: string; hls: string | null; startPosition?: number | null }; }; } diff --git a/front/packages/ui/src/player/video.web.tsx b/front/packages/ui/src/player/video.web.tsx index fdc74aa8..fcd05947 100644 --- a/front/packages/ui/src/player/video.web.tsx +++ b/front/packages/ui/src/player/video.web.tsx @@ -33,7 +33,7 @@ import { VideoProps } from "react-native-video"; import { useAtomValue, useSetAtom, useAtom } from "jotai"; import { useYoshiki } from "yoshiki"; import Jassub from "jassub"; -import { playAtom, PlayMode, playModeAtom, subtitleAtom } from "./state"; +import { playAtom, PlayMode, playModeAtom, progressAtom, subtitleAtom } from "./state"; import Hls, { Level, LoadPolicy } from "hls.js"; import { useTranslation } from "react-i18next"; import { Menu } from "@kyoo/primitives"; @@ -77,7 +77,6 @@ const initHls = async (): Promise => { }, autoStartLoad: false, // debug: true, - startPosition: 0, fragLoadPolicy: { default: { maxTimeToFirstByteMs: Infinity, @@ -167,7 +166,7 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function ref.current.src = source.uri; } else { hls.attachMedia(ref.current); - hls.startLoad(0); + hls.startLoad(source.startPosition ?? 0); hls.on(Hls.Events.ERROR, (_, d) => { if (!d.fatal || !hls?.media) return; console.warn("Hls error", d); @@ -188,6 +187,8 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function setPlay(!ref.current.paused); }, [setPlay]); + const setProgress = useSetAtom(progressAtom); + return (