diff --git a/front/packages/models/src/resources/watch-item.ts b/front/packages/models/src/resources/watch-item.ts index 620530d4..e063f749 100644 --- a/front/packages/models/src/resources/watch-item.ts +++ b/front/packages/models/src/resources/watch-item.ts @@ -119,7 +119,7 @@ const WatchMovieP = z.preprocess( /** * The title of this episode. */ - name: z.string(), + name: z.string().nullable(), /** * The sumarry of this episode. */ @@ -179,15 +179,15 @@ const WatchEpisodeP = WatchMovieP.and( /** * The season in witch this episode is in. */ - seasonNumber: z.number(), + seasonNumber: z.number().nullable(), /** * The number of this episode is it's season. */ - episodeNumber: z.number(), + episodeNumber: z.number().nullable(), /** * The absolute number of this episode. It's an episode number that is not reset to 1 after a new season. */ - absoluteNumber: z.number(), + absoluteNumber: z.number().nullable(), /** * The episode that come before this one if you follow usual watch orders. If this is the first * episode or this is a movie, it will be null. diff --git a/front/packages/primitives/src/progress.tsx b/front/packages/primitives/src/progress.tsx index e95b2c3c..aa44e61d 100644 --- a/front/packages/primitives/src/progress.tsx +++ b/front/packages/primitives/src/progress.tsx @@ -18,19 +18,21 @@ * along with Kyoo. If not, see . */ -import { Platform, View, ViewProps } from "react-native"; +import { ActivityIndicator, Platform, View } from "react-native"; import { Circle, Svg } from "react-native-svg"; -import { px, useYoshiki } from "yoshiki/native"; +import { px, Stylable, useYoshiki } from "yoshiki/native"; -// TODO: Use moti on native export const CircularProgress = ({ size = 48, tickness = 5, color, ...props -}: { size?: number; tickness?: number; color?: string } & ViewProps) => { +}: { size?: number; tickness?: number; color?: string } & Stylable) => { const { css, theme } = useYoshiki(); + if (Platform.OS !== "web") + return ; + return ( */} - setMouseMoved(false)} + setMouseMoved(false)} + onPress={Platform.OS === "web" ? () => setPlay(!isPlaying) : show} {...css({ flexGrow: 1, // @ts-ignore - // cursor: displayControls ? "unset" : "none", bg: "black", })} > + ); }; diff --git a/front/packages/ui/src/player/state.tsx b/front/packages/ui/src/player/state.tsx index c38a679b..1683bce7 100644 --- a/front/packages/ui/src/player/state.tsx +++ b/front/packages/ui/src/player/state.tsx @@ -20,7 +20,7 @@ import { Font, Track, WatchItem } from "@kyoo/models"; import { atom, useAtom, useSetAtom } from "jotai"; -import { RefObject, useEffect, useRef, useState } from "react"; +import { RefObject, useEffect, useLayoutEffect, useRef, useState } from "react"; import { createParam } from "solito"; import { ResizeMode, Video as NativeVideo, VideoProps } from "expo-av"; import SubtitleOctopus from "libass-wasm"; @@ -34,8 +34,7 @@ enum PlayMode { const playModeAtom = atom(PlayMode.Direct); -export const playAtom = atom(true); - +export const playAtom = atom(true); export const loadAtom = atom(false); export const progressAtom = atom(0); export const bufferedAtom = atom(0); @@ -69,10 +68,13 @@ export const [_, fullscreenAtom] = bakedAtom(false, async (_, set, value, baker) let hls: Hls | null = null; -export const Video = ({ links, ...props }: { links?: WatchItem["link"] } & VideoProps) => { +export const Video = ({ + links, + setError, + ...props +}: { links?: WatchItem["link"]; setError: (error: string | undefined) => void } & VideoProps) => { // const player = useRef(null); // const setPlayer = useSetAtom(playerAtom); - // const setLoad = useSetAtom(loadAtom); // const setVolume = useSetAtom(_volumeAtom); // const setMuted = useSetAtom(_mutedAtom); // const setFullscreen = useSetAtom(fullscreenAtom); @@ -80,6 +82,12 @@ export const Video = ({ links, ...props }: { links?: WatchItem["link"] } & Video const ref = useRef(null); const [isPlaying, setPlay] = useAtom(playAtom); + const setLoad = useSetAtom(loadAtom); + + useLayoutEffect(() => { + setLoad(true); + }, []) + const [progress, setProgress] = useAtom(progressAtom); const [buffered, setBuffered] = useAtom(bufferedAtom); const [duration, setDuration] = useAtom(durationAtom); @@ -134,9 +142,13 @@ export const Video = ({ links, ...props }: { links?: WatchItem["link"] } & Video source={links ? { uri: links.direct } : undefined} shouldPlay={isPlaying} onPlaybackStatusUpdate={(status) => { - // TODO: Handle error state - if (!status.isLoaded) return; + if (!status.isLoaded) { + setLoad(true); + if (status.error) setError(status.error); + return; + } + setLoad(status.isPlaying !== status.shouldPlay); setPlay(status.shouldPlay); setProgress(status.positionMillis); setBuffered(status.playableDurationMillis ?? 0);