diff --git a/front/packages/primitives/src/utils/touchonly.tsx b/front/packages/primitives/src/utils/touchonly.tsx index 98cb6040..7972037c 100644 --- a/front/packages/primitives/src/utils/touchonly.tsx +++ b/front/packages/primitives/src/utils/touchonly.tsx @@ -18,6 +18,7 @@ * along with Kyoo. If not, see . */ +import { useEffect } from "react"; import { Platform, ViewProps } from "react-native"; export const TouchOnlyCss = () => { @@ -39,3 +40,10 @@ export const touchOnly: ViewProps = { export const noTouch: ViewProps = { style: Platform.OS === "web" ? ({ $$css: true, noTouch: "noTouch" } as any) : { display: "none" }, }; + +export const useIsTouch = () => { + if (Platform.OS !== "web") return true; + if (typeof window === "undefined") return false; + // TODO: Subscribe to the change. + return document.body.classList.contains("noHover"); +}; diff --git a/front/packages/ui/src/player/components/hover.tsx b/front/packages/ui/src/player/components/hover.tsx index eb651579..54871a7e 100644 --- a/front/packages/ui/src/player/components/hover.tsx +++ b/front/packages/ui/src/player/components/hover.tsx @@ -33,12 +33,13 @@ import { Tooltip, tooltip, ts, + useIsTouch, } from "@kyoo/primitives"; import { Chapter, KyooImage, Subtitle, Audio } from "@kyoo/models"; import { useAtomValue, useSetAtom, useAtom } from "jotai"; import { ImageStyle, Platform, Pressable, View, ViewProps } from "react-native"; import { useTranslation } from "react-i18next"; -import { percent, rem, useYoshiki } from "yoshiki/native"; +import { percent, rem, useYoshiki, vh } from "yoshiki/native"; import { useRouter } from "solito/router"; import ArrowBack from "@material-symbols/svg-400/rounded/arrow_back-fill.svg"; import { LeftButtons, TouchControls } from "./left-buttons"; @@ -63,6 +64,7 @@ const hoverReasonAtom = atom({ export const hoverAtom = atom((get) => [!get(playAtom), ...Object.values(get(hoverReasonAtom))].includes(true), ); +export const seekingAtom = atom(false); export const Hover = ({ isLoading, @@ -93,6 +95,10 @@ export const Hover = ({ }) => { const show = useAtomValue(hoverAtom); const setHover = useSetAtom(hoverReasonAtom); + const isSeeking = useAtomValue(seekingAtom); + const isTouch = useIsTouch(); + + const showBottomSeeker = isSeeking && isTouch; return ( @@ -150,32 +156,37 @@ export const Hover = ({ maxWidth: percent(100), })} > -

- {isLoading ? : name} -

- - - - - setHover((x) => ({ ...x, menuOpened: true }))} - onMenuClose={() => { - // Disable hover since the menu overlay makes the mouseout unreliable. - setHover((x) => ({ ...x, menuOpened: false, mouseHover: false })); - }} - /> - + {!showBottomSeeker && ( +

+ {isLoading ? : name} +

+ )} + + {showBottomSeeker ? ( + + ) : ( + + + setHover((x) => ({ ...x, menuOpened: true }))} + onMenuClose={() => { + // Disable hover since the menu overlay makes the mouseout unreliable. + setHover((x) => ({ ...x, menuOpened: false, mouseHover: false })); + }} + /> + + )} @@ -318,13 +329,20 @@ const ProgressBar = ({ url, chapters }: { url: string; chapters?: Chapter[] }) = const setPlay = useSetAtom(playAtom); const [hoverProgress, setHoverProgress] = useState(null); const [layout, setLayout] = useState({ x: 0, y: 0, width: 0, height: 0 }); + const setSeeking = useSetAtom(seekingAtom); return ( <> setPlay(false)} - endSeek={() => setTimeout(() => setPlay(true), 10)} + startSeek={() => { + setPlay(false); + setSeeking(true); + }} + endSeek={() => { + setSeeking(false); + setTimeout(() => setPlay(true), 10); + }} onHover={(progress, layout) => { setHoverProgress(progress); setLayout(layout);