diff --git a/front/src/ui/player/controls/bottom-controls.tsx b/front/src/ui/player/controls/bottom-controls.tsx
index 343c8f1c..8bc0e9bb 100644
--- a/front/src/ui/player/controls/bottom-controls.tsx
+++ b/front/src/ui/player/controls/bottom-controls.tsx
@@ -1,5 +1,6 @@
import SkipNext from "@material-symbols/svg-400/rounded/skip_next-fill.svg";
import SkipPrevious from "@material-symbols/svg-400/rounded/skip_previous-fill.svg";
+import type { ComponentProps } from "react";
import { useTranslation } from "react-i18next";
import { Platform, View, type ViewProps } from "react-native";
import type { VideoPlayer } from "react-native-video";
@@ -9,6 +10,7 @@ import {
H2,
IconButton,
Link,
+ type Menu,
noTouch,
Poster,
tooltip,
@@ -23,12 +25,18 @@ export const BottomControls = ({
poster,
name,
chapters,
+ previous,
+ next,
+ setMenu,
...props
}: {
player: VideoPlayer;
poster: KImage;
name: string;
chapters: Chapter[];
+ previous: string | null;
+ next: string | null;
+ setMenu: (isOpen: boolean) => void;
} & ViewProps) => {
const { css } = useYoshiki();
@@ -69,7 +77,12 @@ export const BottomControls = ({
name
-
+
);
@@ -79,16 +92,23 @@ const ControlButtons = ({
player,
previous,
next,
+ setMenu,
...props
}: {
player: VideoPlayer;
- previous: string;
- next: string;
+ previous: string | null;
+ next: string | null;
+ setMenu: (isOpen: boolean) => void;
}) => {
const { css } = useYoshiki();
const { t } = useTranslation();
const spacing = css({ marginHorizontal: ts(1) });
+ const menuProps = {
+ onMenuOpen: () => setMenu(true),
+ onMenuClose: () => setMenu(false),
+ ...spacing,
+ } satisfies Partial>;
return (
-
-
-
+
+
+
{Platform.OS === "web" && }
diff --git a/front/src/ui/player/controls/index.tsx b/front/src/ui/player/controls/index.tsx
index 9ab306cd..4bdd9a95 100644
--- a/front/src/ui/player/controls/index.tsx
+++ b/front/src/ui/player/controls/index.tsx
@@ -1,6 +1,8 @@
+import { useState } from "react";
+import type { ViewProps } from "react-native";
import type { VideoPlayer } from "react-native-video";
import { useYoshiki } from "yoshiki/native";
-import type { KImage } from "~/models";
+import type { Chapter, KImage } from "~/models";
import { Back } from "./back";
import { BottomControls } from "./bottom-controls";
import { TouchControls } from "./touch";
@@ -8,54 +10,75 @@ import { TouchControls } from "./touch";
export const Controls = ({
player,
title,
+ subTitle,
poster,
+ chapters,
+ previous,
+ next,
}: {
player: VideoPlayer;
title: string;
- description: string | null;
- poster: KImage | null;
+ subTitle: string;
+ poster: KImage;
+ chapters: Chapter[];
+ previous: string | null;
+ next: string | null;
}) => {
const { css } = useYoshiki();
+ const [hover, setHover] = useState(false);
+ const [menuOpenned, setMenu] = useState(false);
+
//
+
+ const hoverControls = {
+ onPointerEnter: (e) => {
+ if (e.nativeEvent.pointerType === "mouse") setHover(true);
+ },
+ onPointerLeave: (e) => {
+ if (e.nativeEvent.pointerType === "mouse") setHover(false);
+ },
+ } satisfies ViewProps;
+
return (
- {
- // if (e.nativeEvent.pointerType === "mouse")
- // setHover((x) => ({ ...x, mouseHover: true }));
- // }}
- // onPointerLeave={(e) => {
- // if (e.nativeEvent.pointerType === "mouse")
- // setHover((x) => ({ ...x, mouseHover: false }));
- // }}
- >
+
theme.darkOverlay,
- })}
+ {...css(
+ {
+ // pointerEvents: "auto",
+ position: "absolute",
+ top: 0,
+ left: 0,
+ right: 0,
+ bg: (theme) => theme.darkOverlay,
+ },
+ hoverControls,
+ )}
/>
theme.darkOverlay,
- })}
+ name={subTitle}
+ poster={poster}
+ chapters={chapters}
+ previous={previous}
+ next={next}
+ setMenu={setMenu}
+ {...css(
+ {
+ // Fixed is used because firefox android make the hover disapear under the navigation bar in absolute
+ // position: Platform.OS === "web" ? ("fixed" as any) : "absolute",
+ position: "absolute",
+ bottom: 0,
+ left: 0,
+ right: 0,
+ bg: (theme) => theme.darkOverlay,
+ },
+ hoverControls,
+ )}
/>
);
};
+
+export { LoadingIndicator } from "./misc";
diff --git a/front/src/ui/player/controls/touch.tsx b/front/src/ui/player/controls/touch.tsx
index 54d46969..a330c2a6 100644
--- a/front/src/ui/player/controls/touch.tsx
+++ b/front/src/ui/player/controls/touch.tsx
@@ -12,13 +12,15 @@ import { useIsTouch } from "~/primitives";
export const TouchControls = ({
player,
children,
+ forceShow = false,
...props
-}: { player: VideoPlayer } & PressableProps) => {
+}: { player: VideoPlayer; forceShow?: boolean } & PressableProps) => {
const { css } = useYoshiki();
const isTouch = useIsTouch();
- const [shouldShow, setShow] = useState(true);
+ const [_show, setShow] = useState(true);
const hideTimeout = useRef(null);
+ const shouldShow = forceShow || _show;
const show = useCallback((val: boolean = true) => {
setShow(val);
if (hideTimeout.current) clearTimeout(hideTimeout.current);
@@ -27,7 +29,6 @@ export const TouchControls = ({
setShow(false);
}, 2500);
}, []);
- // TODO: handle mouse hover & seek
// On mouse move
useEffect(() => {
diff --git a/front/src/ui/player/index.tsx b/front/src/ui/player/index.tsx
index bef34123..c9c9749b 100644
--- a/front/src/ui/player/index.tsx
+++ b/front/src/ui/player/index.tsx
@@ -8,7 +8,7 @@ import { useToken } from "~/providers/account-context";
import { useLocalSetting } from "~/providers/settings";
import { type QueryIdentifier, useFetch } from "~/query";
import { useQueryState } from "~/utils";
-import { LoadingIndicator } from "./controls";
+import { Controls, LoadingIndicator } from "./controls";
const mapMetadata = (item: FullVideo | undefined) => {
if (!item) return null;
@@ -134,7 +134,11 @@ export const Player = () => {
/>
-
+
);