Switch seamlessly between pristine and auto quality

This commit is contained in:
Zoe Roux 2024-01-29 13:10:03 +01:00
parent f65e4bc417
commit af6436c3d8
2 changed files with 20 additions and 9 deletions

View File

@ -20,7 +20,8 @@
import { Episode, Subtitle } from "@kyoo/models"; import { Episode, Subtitle } from "@kyoo/models";
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai"; import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
import { ElementRef, memo, useEffect, useLayoutEffect, useRef, useState } from "react"; import { useAtomCallback } from "jotai/utils";
import { ElementRef, memo, useEffect, useLayoutEffect, useRef, useState, useCallback } from "react";
import NativeVideo, { VideoProperties as VideoProps } from "./video"; import NativeVideo, { VideoProperties as VideoProps } from "./video";
import { Platform } from "react-native"; import { Platform } from "react-native";
@ -88,7 +89,7 @@ export const Video = memo(function Video({
subtitles, subtitles,
setError, setError,
fonts, fonts,
startTime, startTime: startTimeP,
...props ...props
}: { }: {
links?: Episode["links"]; links?: Episode["links"];
@ -103,6 +104,11 @@ export const Video = memo(function Video({
const [source, setSource] = useState<string | null>(null); const [source, setSource] = useState<string | null>(null);
const [mode, setPlayMode] = useAtom(playModeAtom); const [mode, setPlayMode] = useAtom(playModeAtom);
const startTime = useRef(startTimeP);
useLayoutEffect(() => {
startTime.current = startTimeP;
}, [startTimeP]);
const publicProgress = useAtomValue(publicProgressAtom); const publicProgress = useAtomValue(publicProgressAtom);
const setPrivateProgress = useSetAtom(privateProgressAtom); const setPrivateProgress = useSetAtom(privateProgressAtom);
const setPublicProgress = useSetAtom(publicProgressAtom); const setPublicProgress = useSetAtom(publicProgressAtom);
@ -112,14 +118,21 @@ export const Video = memo(function Video({
ref.current?.seek(publicProgress); ref.current?.seek(publicProgress);
}, [publicProgress]); }, [publicProgress]);
const getProgress = useAtomCallback(useCallback((get) => get(progressAtom), []));
const oldLinks = useRef(links);
useLayoutEffect(() => { useLayoutEffect(() => {
// Reset the state when a new video is loaded. // Reset the state when a new video is loaded.
setSource((mode === PlayMode.Direct ? links?.direct : links?.hls) ?? null); setSource((mode === PlayMode.Direct ? links?.direct : links?.hls) ?? null);
setLoad(true); setLoad(true);
setPrivateProgress(0); if (oldLinks.current !== links) {
setPublicProgress(0); setPrivateProgress(startTime.current ?? 0);
setPublicProgress(startTime.current ?? 0);
} else {
startTime.current = getProgress();
}
oldLinks.current = links;
setPlay(true); setPlay(true);
}, [mode, links, setLoad, setPrivateProgress, setPublicProgress, setPlay]); }, [mode, links, setLoad, setPrivateProgress, setPublicProgress, setPlay, getProgress]);
const [subtitle, setSubtitle] = useAtom(subtitleAtom); const [subtitle, setSubtitle] = useAtom(subtitleAtom);
useEffect(() => { useEffect(() => {
@ -150,7 +163,7 @@ export const Video = memo(function Video({
{...props} {...props}
source={{ source={{
uri: source, uri: source,
startPosition: startTime ? startTime * 1000 : undefined, startPosition: startTime.current ? startTime.current * 1000 : undefined,
...links, ...links,
}} }}
paused={!isPlaying} paused={!isPlaying}

View File

@ -158,9 +158,7 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
if (hls) hls.destroy(); if (hls) hls.destroy();
hls = null; hls = null;
hls = await initHls(); hls = await initHls();
// Still load the hls source to list available qualities. hls.loadSource(source.hls!);
// Note: This may ask the server to transmux the audio/video by loading the index.m3u8
hls.loadSource(source.hls);
oldHls.current = source.hls; oldHls.current = source.hls;
} }
if (!source.uri.endsWith(".m3u8")) { if (!source.uri.endsWith(".m3u8")) {