Resume to the last watched position

This commit is contained in:
Zoe Roux 2024-01-26 11:38:23 +01:00
parent 9c03bac804
commit 0e10f29cd2
4 changed files with 17 additions and 6 deletions

View File

@ -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<Item>
? {
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" })),
};

View File

@ -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<VideoProps>) {
const ref = useRef<ElementRef<typeof NativeVideo> | 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}

View File

@ -28,7 +28,7 @@ declare module "react-native-video" {
onMediaUnsupported?: () => void;
}
export type VideoProps = Omit<VideoProperties, "source"> & {
source: { uri: string; hls: string | null };
source: { uri: string; hls: string | null; startPosition?: number | null };
};
}

View File

@ -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<Hls> => {
},
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 (
<video
ref={ref}
@ -221,6 +222,9 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
});
}
}}
onLoadedMetadata={() => {
if (source.startPosition) setProgress(source.startPosition / 1000);
}}
// BUG: If this is enabled, switching to fullscreen or opening a menu make a play/pause loop until firefox crash.
// onPlay={() => onPlayPause?.call(null, true)}
// onPause={() => onPlayPause?.call(null, false)}