19 changed files with 256 additions and 115 deletions
@ -1,3 +1,7 @@
@@ -1,3 +1,7 @@
|
||||
export * from "./atoms"; |
||||
export * from "./base/Container"; |
||||
export * from "./base/TopControls"; |
||||
export * from "./base/BottomControls"; |
||||
export * from "./base/BlackOverlay"; |
||||
export * from "./base/BackLink"; |
||||
export * from "./internals/BookmarkButton"; |
||||
|
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
import { useTranslation } from "react-i18next"; |
||||
|
||||
import { Icon, Icons } from "@/components/Icon"; |
||||
import { useGoBack } from "@/hooks/useGoBack"; |
||||
|
||||
export function BackLink() { |
||||
const { t } = useTranslation(); |
||||
const goBack = useGoBack(); |
||||
|
||||
return ( |
||||
<div className="flex items-center"> |
||||
<span |
||||
onClick={() => goBack()} |
||||
className="flex items-center cursor-pointer text-type-secondary hover:text-white transition-colors duration-200 font-medium" |
||||
> |
||||
<Icon className="mr-2" icon={Icons.ARROW_LEFT} /> |
||||
<span>{t("videoPlayer.backToHomeShort")}</span> |
||||
</span> |
||||
<span className="text mx-3 text-type-secondary">/</span> |
||||
<span>Mr Jeebaloo's Big Ocean Adventure</span> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
import { Transition } from "@/components/Transition"; |
||||
|
||||
export function BlackOverlay(props: { show?: boolean }) { |
||||
return ( |
||||
<Transition |
||||
animation="fade" |
||||
show={props.show} |
||||
className="absolute inset-0 w-full h-full bg-black bg-opacity-20 pointer-events-none" |
||||
/> |
||||
); |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
import { Transition } from "@/components/Transition"; |
||||
|
||||
export function TopControls(props: { |
||||
show?: boolean; |
||||
children: React.ReactNode; |
||||
}) { |
||||
return ( |
||||
<div className="w-full text-white"> |
||||
<Transition |
||||
animation="fade" |
||||
show={props.show} |
||||
className="pointer-events-none flex justify-end pb-32 bg-gradient-to-b from-black to-transparent [margin-bottom:env(safe-area-inset-bottom)] transition-opacity duration-200 absolute top-0 w-full" |
||||
/> |
||||
<Transition |
||||
animation="slide-down" |
||||
show={props.show} |
||||
className="pointer-events-auto px-4 pt-6 absolute top-0 w-full text-white" |
||||
> |
||||
{props.children} |
||||
</Transition> |
||||
</div> |
||||
); |
||||
} |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
import { PlayerHoverState } from "@/stores/player/slices/interface"; |
||||
import { usePlayerStore } from "@/stores/player/store"; |
||||
|
||||
export function useShouldShowControls() { |
||||
const { hovering } = usePlayerStore((s) => s.interface); |
||||
const { isPaused } = usePlayerStore((s) => s.mediaPlaying); |
||||
|
||||
return hovering !== PlayerHoverState.NOT_HOVERING || isPaused; |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
import { Icons } from "@/components/Icon"; |
||||
|
||||
import { VideoPlayerButton } from "./Button"; |
||||
|
||||
export function BookmarkButton() { |
||||
return ( |
||||
<VideoPlayerButton |
||||
onClick={() => window.open("https://youtu.be/TENzstSjsus", "_blank")} |
||||
icon={Icons.BOOKMARK_OUTLINE} |
||||
iconSizeClass="text-base" |
||||
className="p-3" |
||||
/> |
||||
); |
||||
} |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
import { PointerEvent, useCallback } from "react"; |
||||
|
||||
import { useShouldShowVideoElement } from "@/components/player/internals/VideoContainer"; |
||||
import { PlayerHoverState } from "@/stores/player/slices/interface"; |
||||
import { usePlayerStore } from "@/stores/player/store"; |
||||
|
||||
export function VideoClickTarget() { |
||||
const show = useShouldShowVideoElement(); |
||||
const display = usePlayerStore((s) => s.display); |
||||
const isPaused = usePlayerStore((s) => s.mediaPlaying.isPaused); |
||||
const updateInterfaceHovering = usePlayerStore( |
||||
(s) => s.updateInterfaceHovering |
||||
); |
||||
const hovering = usePlayerStore((s) => s.interface.hovering); |
||||
|
||||
const toggleFullscreen = useCallback(() => { |
||||
display?.toggleFullscreen(); |
||||
}, [display]); |
||||
|
||||
const togglePause = useCallback( |
||||
(e: PointerEvent<HTMLDivElement>) => { |
||||
// pause on mouse click
|
||||
if (e.pointerType === "mouse") { |
||||
if (e.button !== 0) return; |
||||
if (isPaused) display?.play(); |
||||
else display?.pause(); |
||||
return; |
||||
} |
||||
|
||||
// toggle on other types of clicks
|
||||
if (hovering !== PlayerHoverState.MOBILE_TAPPED) |
||||
updateInterfaceHovering(PlayerHoverState.MOBILE_TAPPED); |
||||
else updateInterfaceHovering(PlayerHoverState.NOT_HOVERING); |
||||
}, |
||||
[display, isPaused, hovering, updateInterfaceHovering] |
||||
); |
||||
|
||||
if (!show) return null; |
||||
|
||||
return ( |
||||
<div |
||||
className="absolute inset-0" |
||||
onDoubleClick={toggleFullscreen} |
||||
onPointerUp={togglePause} |
||||
/> |
||||
); |
||||
} |
Loading…
Reference in new issue