mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-30 19:54:16 -04:00
Resume to the last watched position
This commit is contained in:
parent
9c03bac804
commit
0e10f29cd2
@ -36,7 +36,7 @@ import { useRouter } from "solito/router";
|
|||||||
import { useSetAtom } from "jotai";
|
import { useSetAtom } from "jotai";
|
||||||
import { useYoshiki } from "yoshiki/native";
|
import { useYoshiki } from "yoshiki/native";
|
||||||
import { Back, Hover, LoadingIndicator } from "./components/hover";
|
import { Back, Hover, LoadingIndicator } from "./components/hover";
|
||||||
import { fullscreenAtom, Video } from "./state";
|
import { fullscreenAtom, progressAtom, Video } from "./state";
|
||||||
import { episodeDisplayNumber } from "../details/episode";
|
import { episodeDisplayNumber } from "../details/episode";
|
||||||
import { useVideoKeyboard } from "./keyboard";
|
import { useVideoKeyboard } from "./keyboard";
|
||||||
import { MediaSessionManager } from "./media-session";
|
import { MediaSessionManager } from "./media-session";
|
||||||
@ -140,6 +140,7 @@ export const Player = ({ slug, type }: { slug: string; type: "episode" | "movie"
|
|||||||
subtitles={info?.subtitles}
|
subtitles={info?.subtitles}
|
||||||
setError={setPlaybackError}
|
setError={setPlaybackError}
|
||||||
fonts={info?.fonts}
|
fonts={info?.fonts}
|
||||||
|
startTime={data?.watchStatus?.watchedTime}
|
||||||
onEnd={() => {
|
onEnd={() => {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
if (data.type === "movie")
|
if (data.type === "movie")
|
||||||
@ -167,12 +168,15 @@ Player.query = (type: "episode" | "movie", slug: string): QueryIdentifier<Item>
|
|||||||
? {
|
? {
|
||||||
path: ["episode", slug],
|
path: ["episode", slug],
|
||||||
params: {
|
params: {
|
||||||
fields: ["nextEpisode", "previousEpisode", "show"],
|
fields: ["nextEpisode", "previousEpisode", "show", "watchStatus"],
|
||||||
},
|
},
|
||||||
parser: EpisodeP.transform((x) => ({ ...x, type: "episode" })),
|
parser: EpisodeP.transform((x) => ({ ...x, type: "episode" })),
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
path: ["movie", slug],
|
path: ["movie", slug],
|
||||||
|
params: {
|
||||||
|
fields: ["watchStatus"],
|
||||||
|
},
|
||||||
parser: MovieP.transform((x) => ({ ...x, type: "movie" })),
|
parser: MovieP.transform((x) => ({ ...x, type: "movie" })),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,12 +88,14 @@ export const Video = memo(function Video({
|
|||||||
subtitles,
|
subtitles,
|
||||||
setError,
|
setError,
|
||||||
fonts,
|
fonts,
|
||||||
|
startTime,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
links?: Episode["links"];
|
links?: Episode["links"];
|
||||||
subtitles?: Subtitle[];
|
subtitles?: Subtitle[];
|
||||||
setError: (error: string | undefined) => void;
|
setError: (error: string | undefined) => void;
|
||||||
fonts?: string[];
|
fonts?: string[];
|
||||||
|
startTime?: number | null;
|
||||||
} & Partial<VideoProps>) {
|
} & Partial<VideoProps>) {
|
||||||
const ref = useRef<ElementRef<typeof NativeVideo> | null>(null);
|
const ref = useRef<ElementRef<typeof NativeVideo> | null>(null);
|
||||||
const [isPlaying, setPlay] = useAtom(playAtom);
|
const [isPlaying, setPlay] = useAtom(playAtom);
|
||||||
@ -148,6 +150,7 @@ export const Video = memo(function Video({
|
|||||||
{...props}
|
{...props}
|
||||||
source={{
|
source={{
|
||||||
uri: source,
|
uri: source,
|
||||||
|
startPosition: startTime ? startTime * 1000 : undefined,
|
||||||
...links,
|
...links,
|
||||||
}}
|
}}
|
||||||
paused={!isPlaying}
|
paused={!isPlaying}
|
||||||
|
@ -28,7 +28,7 @@ declare module "react-native-video" {
|
|||||||
onMediaUnsupported?: () => void;
|
onMediaUnsupported?: () => void;
|
||||||
}
|
}
|
||||||
export type VideoProps = Omit<VideoProperties, "source"> & {
|
export type VideoProps = Omit<VideoProperties, "source"> & {
|
||||||
source: { uri: string; hls: string | null };
|
source: { uri: string; hls: string | null; startPosition?: number | null };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ import { VideoProps } from "react-native-video";
|
|||||||
import { useAtomValue, useSetAtom, useAtom } from "jotai";
|
import { useAtomValue, useSetAtom, useAtom } from "jotai";
|
||||||
import { useYoshiki } from "yoshiki";
|
import { useYoshiki } from "yoshiki";
|
||||||
import Jassub from "jassub";
|
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 Hls, { Level, LoadPolicy } from "hls.js";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Menu } from "@kyoo/primitives";
|
import { Menu } from "@kyoo/primitives";
|
||||||
@ -77,7 +77,6 @@ const initHls = async (): Promise<Hls> => {
|
|||||||
},
|
},
|
||||||
autoStartLoad: false,
|
autoStartLoad: false,
|
||||||
// debug: true,
|
// debug: true,
|
||||||
startPosition: 0,
|
|
||||||
fragLoadPolicy: {
|
fragLoadPolicy: {
|
||||||
default: {
|
default: {
|
||||||
maxTimeToFirstByteMs: Infinity,
|
maxTimeToFirstByteMs: Infinity,
|
||||||
@ -167,7 +166,7 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
|
|||||||
ref.current.src = source.uri;
|
ref.current.src = source.uri;
|
||||||
} else {
|
} else {
|
||||||
hls.attachMedia(ref.current);
|
hls.attachMedia(ref.current);
|
||||||
hls.startLoad(0);
|
hls.startLoad(source.startPosition ?? 0);
|
||||||
hls.on(Hls.Events.ERROR, (_, d) => {
|
hls.on(Hls.Events.ERROR, (_, d) => {
|
||||||
if (!d.fatal || !hls?.media) return;
|
if (!d.fatal || !hls?.media) return;
|
||||||
console.warn("Hls error", d);
|
console.warn("Hls error", d);
|
||||||
@ -188,6 +187,8 @@ const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function
|
|||||||
setPlay(!ref.current.paused);
|
setPlay(!ref.current.paused);
|
||||||
}, [setPlay]);
|
}, [setPlay]);
|
||||||
|
|
||||||
|
const setProgress = useSetAtom(progressAtom);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<video
|
<video
|
||||||
ref={ref}
|
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.
|
// 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)}
|
// onPlay={() => onPlayPause?.call(null, true)}
|
||||||
// onPause={() => onPlayPause?.call(null, false)}
|
// onPause={() => onPlayPause?.call(null, false)}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user