Move canPlay to method instead of ref function

This commit is contained in:
Zoe Roux 2024-05-12 16:53:29 +02:00
parent 764fff7677
commit 5de584d6e3
No known key found for this signature in database
5 changed files with 37 additions and 38 deletions

View File

@ -29,7 +29,8 @@ const suboctopus = path.resolve(path.dirname(require.resolve("jassub")), "../dis
*/
const nextConfig = {
swcMinify: true,
reactStrictMode: true,
// can't be true since we would run hls cleanup twice and run on race conditions
reactStrictMode: false,
output: "standalone",
webpack: (config) => {
config.plugins = [

View File

@ -33,7 +33,7 @@ import {
} from "react";
import { useTranslation } from "react-i18next";
import { Platform } from "react-native";
import NativeVideo, { type VideoProps } from "./video";
import NativeVideo, { canPlay, type VideoProps } from "./video";
export const playAtom = atom(true);
export const loadAtom = atom(false);
@ -134,14 +134,12 @@ export const Video = memo(function Video({
}, [publicProgress]);
const getProgress = useAtomCallback(useCallback((get) => get(progressAtom), []));
const oldLinks = useRef<typeof links | null>(null);
useEffect(() => {
// Reset the state when a new video is loaded.
let newMode = getLocalSetting("playmode", "direct") !== "auto" ? PlayMode.Direct : PlayMode.Hls;
// Only allow direct play if the device supports it
console.log(codec, ref.current, ref.current?.canPlay?.(codec!))
if (newMode === PlayMode.Direct && codec && ref.current?.canPlay?.(codec) === false) {
if (newMode === PlayMode.Direct && codec && !canPlay(codec)) {
console.log(`Browser can't natively play ${codec}, switching to hls stream.`);
newMode = PlayMode.Hls;
}
@ -149,25 +147,18 @@ export const Video = memo(function Video({
setSource((newMode === PlayMode.Direct ? links?.direct : links?.hls) ?? null);
setLoad(true);
if (oldLinks.current !== links) {
setPrivateProgress(startTime.current ?? 0);
setPublicProgress(startTime.current ?? 0);
} else {
// keep current time when changing between direct and hls.
startTime.current = getProgress();
}
oldLinks.current = links;
setPrivateProgress(startTime.current ?? 0);
setPublicProgress(startTime.current ?? 0);
setPlay(true);
}, [
links,
codec,
setLoad,
setPrivateProgress,
setPublicProgress,
setPlay,
getProgress,
setPlayMode,
]);
}, [links, codec, setLoad, setPrivateProgress, setPublicProgress, setPlay, setPlayMode]);
// biome-ignore lint/correctness/useExhaustiveDependencies: do not change source when links change, this is done above
useEffect(() => {
setSource((mode === PlayMode.Direct ? links?.direct : links?.hls) ?? null);
// keep current time when changing between direct and hls.
startTime.current = getProgress();
setPlay(true);
}, [mode, getProgress, setPlay]);
const account = useAccount();
const defaultSubLanguage = account?.settings.subtitleLanguage;

View File

@ -29,10 +29,6 @@ declare module "react-native-video" {
export type VideoProps = Omit<ReactVideoProps, "source"> & {
source: { uri: string; hls: string | null; startPosition?: number };
};
interface VideoRef {
canPlay?: (codec: string) => boolean;
}
}
export * from "react-native-video";
@ -133,6 +129,9 @@ const Video = forwardRef<VideoRef, VideoProps>(function Video(
export default Video;
// mobile should be able to play everything
export const canPlay = (codec: string) => true;
type CustomMenu = ComponentProps<typeof Menu<ComponentProps<typeof IconButton>>>;
export const AudiosMenu = ({ audios, ...props }: CustomMenu & { audios?: Audio[] }) => {
const info = useAtomValue(infoAtom);

View File

@ -50,7 +50,7 @@ function uuidv4(): string {
const client_id = typeof window === "undefined" ? "ssr" : uuidv4();
const initHls = (): Hls => {
if (hls !== null) return hls;
if (hls) hls.destroy();
const loadPolicy: LoadPolicy = {
default: {
maxTimeToFirstByteMs: Number.POSITIVE_INFINITY,
@ -104,10 +104,7 @@ const initHls = (): Hls => {
return hls;
};
const Video = forwardRef<
{ seek: (value: number) => void; canPlay: (codec: string) => boolean },
VideoProps
>(function Video(
const Video = forwardRef<{ seek: (value: number) => void }, VideoProps>(function Video(
{
source,
paused,
@ -161,8 +158,6 @@ const Video = forwardRef<
if (!ref?.current || !source.uri) return;
if (!hls || oldHls.current !== source.hls) {
// Reinit the hls player when we change track.
if (hls) hls.destroy();
hls = null;
hls = initHls();
hls.loadSource(source.hls!);
oldHls.current = source.hls;
@ -181,11 +176,15 @@ const Video = forwardRef<
});
});
}
}, [source.uri, source.hls]);
useEffect(() => {
return () => {
console.log("hls cleanup")
if (hls) hls.destroy();
hls = null;
};
}, [source.uri, source.hls]);
}, []);
const mode = useAtomValue(playModeAtom);
const audio = useAtomValue(audioAtom);
@ -256,6 +255,12 @@ const Video = forwardRef<
export default Video;
export const canPlay = (codec: string) => {
const videos = document.getElementsByTagName("video");
const video = videos.item(0) ?? document.createElement("video");
return !!video.canPlayType(codec);
};
const useSubtitle = (
player: RefObject<HTMLVideoElement>,
value: Subtitle | null,
@ -385,11 +390,12 @@ export const QualitiesMenu = (props: ComponentProps<typeof Menu>) => {
const [mode, setPlayMode] = useAtom(playModeAtom);
const rerender = useForceRerender();
// biome-ignore lint/correctness/useExhaustiveDependencies: Inculde hls in dependency array
useEffect(() => {
if (!hls) return;
hls.on(Hls.Events.LEVEL_SWITCHED, rerender);
return () => hls?.off(Hls.Events.LEVEL_SWITCHED, rerender);
});
}, [hls]);
const levelName = (label: Level, auto?: boolean): string => {
const height = `${label.height}p`;

View File

@ -42,7 +42,8 @@ export const WatchStatusObserver = ({
await queryClient.invalidateQueries({ queryKey: [type === "episode" ? "show" : type, slug] }),
});
const mutate = useCallback(
(type: string, slug: string, seconds: number) =>
(type: string, slug: string, seconds: number) => {
if (seconds < 0 || duration <= 0) return;
_mutate({
method: "POST",
path: [type, slug, "watchStatus"],
@ -51,7 +52,8 @@ export const WatchStatusObserver = ({
watchedTime: Math.round(seconds),
percent: Math.round((seconds / duration) * 100),
},
}),
});
},
[_mutate, duration],
);
const readProgress = useAtomCallback(