Adding a web compatibility layer

This commit is contained in:
Zoe Roux 2022-12-30 18:24:26 +09:00
parent 84b4c998a7
commit 39ae631cf1
3 changed files with 118 additions and 10 deletions

View File

@ -18,13 +18,10 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { Font, Track, WatchItem } from "@kyoo/models";
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
import { RefObject, useEffect, useLayoutEffect, useRef, useState } from "react";
import { createParam } from "solito";
import NativeVideo, { VideoProperties as VideoProps } from "react-native-video";
import SubtitleOctopus from "libass-wasm";
import Hls from "hls.js";
import { Track, WatchItem } from "@kyoo/models";
import { atom, useAtomValue, useSetAtom } from "jotai";
import { useEffect, useLayoutEffect, useRef } from "react";
import NativeVideo, { VideoProperties as VideoProps } from "./video";
import { bakedAtom } from "../jotai-utils";
import { Platform } from "react-native";
@ -73,8 +70,6 @@ export const [privateFullscreen, fullscreenAtom] = bakedAtom(
export const subtitleAtom = atom<Track | null>(null);
let hls: Hls | null = null;
export const Video = ({
links,
setError,
@ -153,7 +148,6 @@ export const Video = ({
setBuffered(progress.playableDuration);
}}
onLoad={(info) => {
console.log(info);
setDuration(info.duration);
}}
selectedTextTrack={

View File

@ -0,0 +1,24 @@
/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
export * from "react-native-video";
import Video from "react-native-video";
export default Video;

View File

@ -0,0 +1,90 @@
/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
import { VideoProperties } from "react-native-video";
import { useYoshiki } from "yoshiki";
// import SubtitleOctopus from "libass-wasm";
// import Hls from "hls.js";
// let hls: Hls | null = null;
// TODO fallback via links and hls.
// TODO: Subtitle (vtt, srt and ass)
const Video = forwardRef<{ seek: (value: number) => void }, VideoProperties>(function _Video(
{ source, paused, muted, volume, onBuffer, onLoad, onProgress, onError },
forwaredRef,
) {
const ref = useRef<HTMLVideoElement>(null);
const { css } = useYoshiki();
useImperativeHandle(
forwaredRef,
() => ({
seek: (value: number) => {
if (ref.current) ref.current.currentTime = value;
},
}),
[],
);
useEffect(() => {
if (paused) ref.current?.pause();
else ref.current?.play();
}, [paused]);
useEffect(() => {
if (!ref.current || !volume) return;
ref.current.volume = Math.max(0, Math.min(volume, 100)) / 100;
}, [volume]);
return (
<video
ref={ref}
src={typeof source === "number" ? undefined : source.uri}
muted={muted}
autoPlay={!paused}
onCanPlay={() => onBuffer?.call(null, { isBuffering: false })}
onWaiting={() => onBuffer?.call(null, { isBuffering: true })}
onDurationChange={() => {
if (!ref.current) return;
onLoad?.call(null, { duration: ref.current.duration } as any);
}}
onProgress={() => {
if (!ref.current) return;
onProgress?.call(null, {
currentTime: ref.current.currentTime,
playableDuration: ref.current.buffered.length
? ref.current.buffered.end(ref.current.buffered.length - 1)
: 0,
seekableDuration: 0,
});
}}
onError={() =>
onError?.call(null, {
error: { "": "", errorString: ref.current?.error?.message ?? "Unknown error" },
})
}
{...css({ width: "100%", height: "100%" })}
/>
);
});
export default Video;