mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-01 04:34:50 -04:00
Fix hover issues on android
This commit is contained in:
parent
4993ae50fe
commit
72e74cea32
@ -77,7 +77,7 @@ export const Hover = ({
|
|||||||
show: boolean;
|
show: boolean;
|
||||||
} & ViewProps) => {
|
} & ViewProps) => {
|
||||||
// TODO animate show
|
// TODO animate show
|
||||||
const opacity = !show && { opacity: 0 };
|
const opacity = !show && (Platform.OS === "web" ? { opacity: 0 } : { display: "none" as const});
|
||||||
return (
|
return (
|
||||||
<ContrastArea mode="dark">
|
<ContrastArea mode="dark">
|
||||||
{({ css }) => (
|
{({ css }) => (
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
import { QueryIdentifier, QueryPage, WatchItem, WatchItemP, useFetch } from "@kyoo/models";
|
import { QueryIdentifier, QueryPage, WatchItem, WatchItemP, useFetch } from "@kyoo/models";
|
||||||
import { Head } from "@kyoo/primitives";
|
import { Head } from "@kyoo/primitives";
|
||||||
import { useState, useEffect, ComponentProps } from "react";
|
import { useState, useEffect, ComponentProps } from "react";
|
||||||
import { Platform, Pressable, StyleSheet, View } from "react-native";
|
import { Platform, Pressable, PressableProps, StyleSheet, View } from "react-native";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useRouter } from "solito/router";
|
import { useRouter } from "solito/router";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
@ -59,6 +59,17 @@ const mapData = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PressView =
|
||||||
|
Platform.OS === "web"
|
||||||
|
? View
|
||||||
|
: ({
|
||||||
|
onPointerDown,
|
||||||
|
onMobilePress,
|
||||||
|
...props
|
||||||
|
}: PressableProps & { onMobilePress: PressableProps["onPress"] }) => (
|
||||||
|
<Pressable focusable={false} onPress={(e) => onMobilePress?.(e)} {...props} />
|
||||||
|
);
|
||||||
|
|
||||||
// Callback used to hide the controls when the mouse goes iddle. This is stored globally to clear the old timeout
|
// Callback used to hide the controls when the mouse goes iddle. This is stored globally to clear the old timeout
|
||||||
// if the mouse moves again (if this is stored as a state, the whole page is redrawn on mouse move)
|
// if the mouse moves again (if this is stored as a state, the whole page is redrawn on mouse move)
|
||||||
let mouseCallback: NodeJS.Timeout;
|
let mouseCallback: NodeJS.Timeout;
|
||||||
@ -148,9 +159,33 @@ export const Player: QueryPage<{ slug: string }> = ({ slug }) => {
|
|||||||
next={next}
|
next={next}
|
||||||
previous={previous}
|
previous={previous}
|
||||||
/>
|
/>
|
||||||
<View
|
<PressView
|
||||||
focusable={false}
|
focusable={false}
|
||||||
onPointerLeave={(e) => { if (e.nativeEvent.pointerType === "mouse") setMouseMoved(false) }}
|
onMobilePress={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
displayControls ? setMouseMoved(false) : show();
|
||||||
|
}}
|
||||||
|
onStartShouldSetResponder={(e) => true}
|
||||||
|
onPointerDown={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (e.nativeEvent.pointerType !== "mouse") {
|
||||||
|
displayControls ? setMouseMoved(false) : show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
touchCount++;
|
||||||
|
if (touchCount == 2) {
|
||||||
|
touchCount = 0;
|
||||||
|
setFullscreen(!isFullscreen);
|
||||||
|
clearTimeout(touchTimeout);
|
||||||
|
} else
|
||||||
|
touchTimeout = setTimeout(() => {
|
||||||
|
touchCount = 0;
|
||||||
|
}, 400);
|
||||||
|
setPlay(!isPlaying);
|
||||||
|
}}
|
||||||
|
onPointerLeave={(e) => {
|
||||||
|
if (e.nativeEvent.pointerType === "mouse") setMouseMoved(false);
|
||||||
|
}}
|
||||||
{...css({
|
{...css({
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
bg: "black",
|
bg: "black",
|
||||||
@ -158,51 +193,33 @@ export const Player: QueryPage<{ slug: string }> = ({ slug }) => {
|
|||||||
cursor: displayControls ? "unset" : "none",
|
cursor: displayControls ? "unset" : "none",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<View
|
<Video
|
||||||
onPointerDown={(e) => {
|
links={data?.link}
|
||||||
if (e.nativeEvent.pointerType !== "mouse") {
|
setError={setPlaybackError}
|
||||||
displayControls ? setMouseMoved(false) : show();
|
fonts={data?.fonts}
|
||||||
return;
|
onEnd={() => {
|
||||||
}
|
if (!data) return;
|
||||||
e.preventDefault();
|
if (data.isMovie) router.push(`/movie/${data.slug}`);
|
||||||
touchCount++;
|
else
|
||||||
if (touchCount == 2) {
|
router.push(
|
||||||
touchCount = 0;
|
data.nextEpisode ? `/watch/${data.nextEpisode.slug}` : `/show/${data.showSlug}`,
|
||||||
setFullscreen(!isFullscreen);
|
);
|
||||||
clearTimeout(touchTimeout);
|
|
||||||
} else
|
|
||||||
touchTimeout = setTimeout(() => {
|
|
||||||
touchCount = 0;
|
|
||||||
}, 400);
|
|
||||||
setPlay(!isPlaying);
|
|
||||||
}}
|
}}
|
||||||
{...css(StyleSheet.absoluteFillObject)}
|
{...css(StyleSheet.absoluteFillObject)}
|
||||||
>
|
/>
|
||||||
<Video
|
|
||||||
links={data?.link}
|
|
||||||
setError={setPlaybackError}
|
|
||||||
fonts={data?.fonts}
|
|
||||||
onEnd={() => {
|
|
||||||
if (!data) return;
|
|
||||||
if (data.isMovie) router.push(`/movie/${data.slug}`);
|
|
||||||
else
|
|
||||||
router.push(
|
|
||||||
data.nextEpisode ? `/watch/${data.nextEpisode.slug}` : `/show/${data.showSlug}`,
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
{...css(StyleSheet.absoluteFillObject)}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<LoadingIndicator />
|
<LoadingIndicator />
|
||||||
<Hover
|
<Hover
|
||||||
{...mapData(data, previous, next)}
|
{...mapData(data, previous, next)}
|
||||||
onPointerEnter={(e) => { if (e.nativeEvent.pointerType === "mouse") setHover(true) }}
|
onPointerEnter={(e) => {
|
||||||
onPointerLeave={(e) => { if (e.nativeEvent.pointerType === "mouse") setHover(false) }}
|
if (e.nativeEvent.pointerType === "mouse") setHover(true);
|
||||||
|
}}
|
||||||
|
onPointerLeave={(e) => {
|
||||||
|
if (e.nativeEvent.pointerType === "mouse") setHover(false);
|
||||||
|
}}
|
||||||
onPointerDown={(e) => {
|
onPointerDown={(e) => {
|
||||||
// also handle touch here because if we dont, the area where the hover should be will catch touches
|
// Prevent clicks on the hover to play/pause.
|
||||||
// without openning the hover.
|
e.preventDefault();
|
||||||
if (e.nativeEvent.pointerType !== "mouse")
|
e.stopPropagation();
|
||||||
displayControls ? setMouseMoved(false) : show();
|
|
||||||
}}
|
}}
|
||||||
onMenuOpen={() => setMenuOpen(true)}
|
onMenuOpen={() => setMenuOpen(true)}
|
||||||
onMenuClose={() => {
|
onMenuClose={() => {
|
||||||
@ -212,7 +229,7 @@ export const Player: QueryPage<{ slug: string }> = ({ slug }) => {
|
|||||||
}}
|
}}
|
||||||
show={displayControls}
|
show={displayControls}
|
||||||
/>
|
/>
|
||||||
</View>
|
</PressView>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
import { Track, WatchItem, Font } from "@kyoo/models";
|
import { Track, WatchItem, Font } from "@kyoo/models";
|
||||||
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
|
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
|
||||||
import { memo, useEffect, useLayoutEffect, useRef, useState } from "react";
|
import { ElementRef, memo, useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||||
import NativeVideo, { VideoProperties as VideoProps } from "./video";
|
import NativeVideo, { VideoProperties as VideoProps } from "./video";
|
||||||
import { Platform } from "react-native";
|
import { Platform } from "react-native";
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ export const Video = memo(function _Video({
|
|||||||
setError: (error: string | undefined) => void;
|
setError: (error: string | undefined) => void;
|
||||||
fonts?: Font[];
|
fonts?: Font[];
|
||||||
} & Partial<VideoProps>) {
|
} & Partial<VideoProps>) {
|
||||||
const ref = useRef<NativeVideo | null>(null);
|
const ref = useRef<ElementRef<typeof NativeVideo> | null>(null);
|
||||||
const [isPlaying, setPlay] = useAtom(playAtom);
|
const [isPlaying, setPlay] = useAtom(playAtom);
|
||||||
const setLoad = useSetAtom(loadAtom);
|
const setLoad = useSetAtom(loadAtom);
|
||||||
const [source, setSource] = useState<string | null>(null);
|
const [source, setSource] = useState<string | null>(null);
|
||||||
|
@ -33,7 +33,7 @@ export * from "react-native-video";
|
|||||||
|
|
||||||
import { Font } from "@kyoo/models";
|
import { Font } from "@kyoo/models";
|
||||||
import { IconButton, Menu } from "@kyoo/primitives";
|
import { IconButton, Menu } from "@kyoo/primitives";
|
||||||
import { ComponentProps, useRef } from "react";
|
import { ComponentProps, forwardRef } from "react";
|
||||||
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
|
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
|
||||||
import NativeVideo, { OnLoadData } from "react-native-video";
|
import NativeVideo, { OnLoadData } from "react-native-video";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@ -43,17 +43,17 @@ const infoAtom = atom<OnLoadData | null>(null);
|
|||||||
const videoAtom = atom(0);
|
const videoAtom = atom(0);
|
||||||
const audioAtom = atom(0);
|
const audioAtom = atom(0);
|
||||||
|
|
||||||
const Video = ({ onLoad, ...props }: ComponentProps<typeof NativeVideo>) => {
|
const Video = forwardRef<NativeVideo, ComponentProps<typeof NativeVideo>>(function _NativeVideo(
|
||||||
const player = useRef<NativeVideo | null>(null);
|
{ onLoad, ...props },
|
||||||
|
ref,
|
||||||
|
) {
|
||||||
const setInfo = useSetAtom(infoAtom);
|
const setInfo = useSetAtom(infoAtom);
|
||||||
const video = useAtomValue(videoAtom);
|
const video = useAtomValue(videoAtom);
|
||||||
const audio = useAtomValue(audioAtom);
|
const audio = useAtomValue(audioAtom);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NativeVideo
|
<NativeVideo
|
||||||
ref={(ref) => {
|
ref={ref}
|
||||||
player.current = ref;
|
|
||||||
}}
|
|
||||||
onLoad={(info) => {
|
onLoad={(info) => {
|
||||||
setInfo(info);
|
setInfo(info);
|
||||||
onLoad?.(info);
|
onLoad?.(info);
|
||||||
@ -63,7 +63,7 @@ const Video = ({ onLoad, ...props }: ComponentProps<typeof NativeVideo>) => {
|
|||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export default Video;
|
export default Video;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user