mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-11-04 03:27:14 -05: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