diff --git a/package.json b/package.json index 58742c0..2babf0f 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@directus/sdk": "^13.0.2", "@types/react": "^18.2.42", "@types/react-dom": "^18.2.17", + "@uidotdev/usehooks": "^2.4.1", "astro": "^4.0.3", "classnames": "^2.3.2", "random-avatar-generator": "^2.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aa109d6..6d65a4c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,9 @@ dependencies: '@types/react-dom': specifier: ^18.2.17 version: 18.2.17 + '@uidotdev/usehooks': + specifier: ^2.4.1 + version: 2.4.1(react-dom@18.2.0)(react@18.2.0) astro: specifier: ^4.0.3 version: 4.0.3(sass@1.69.5)(typescript@5.1.3) @@ -3138,6 +3141,17 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /@uidotdev/usehooks@2.4.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==} + engines: {node: '>=16'} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} diff --git a/src/components/ProgressButton.tsx b/src/components/ProgressButton.tsx index e40e3e7..58eb661 100644 --- a/src/components/ProgressButton.tsx +++ b/src/components/ProgressButton.tsx @@ -7,6 +7,7 @@ type ProgessButtonProps = { icon: string; onClick: () => void; active: boolean; + paused: boolean; duration: number; }; @@ -15,13 +16,14 @@ const ProgressButton = ({ icon, onClick, active, + paused, duration, }: ProgessButtonProps) => { return (
@@ -33,7 +35,9 @@ const ProgressButton = ({
diff --git a/src/components/Video.tsx b/src/components/Video.tsx index 05472a7..89a0778 100644 --- a/src/components/Video.tsx +++ b/src/components/Video.tsx @@ -4,13 +4,15 @@ import { useRef, useEffect, useMemo } from "react"; type Props = { className?: string; - handleLoadedMetadata?: (duration: number) => void; video: string; + paused: boolean; + handleLoadedMetadata?: (duration: number) => void; }; export default function Video({ className, video, + paused, handleLoadedMetadata, }: Props) { const videoRef = useRef(null); @@ -19,6 +21,13 @@ export default function Video({ if (videoRef.current) videoRef.current.defaultMuted = true; }, []); + useEffect(() => { + if (videoRef.current) { + if (paused) videoRef.current.pause(); + else videoRef.current.play(); + } + }, [paused]); + const key = useMemo(() => video, [video]); return ( diff --git a/src/components/VideoPlayer.tsx b/src/components/VideoPlayer.tsx index d8683a0..c5f0864 100644 --- a/src/components/VideoPlayer.tsx +++ b/src/components/VideoPlayer.tsx @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; +import { useIntersectionObserver } from "@uidotdev/usehooks"; import ProgressButton from "./ProgressButton"; import useMediaQuery from "../hooks/useMediaQuery"; import Video from "./Video"; @@ -16,10 +17,15 @@ type Props = { buttonFirstVidLabel: string; buttonSecondVidLabel: string; buttonThirdVidLabel: string; - } -} + }; +}; const VideoPlayer = (props: Props) => { + const [ref, entry] = useIntersectionObserver({ + threshold: 0.75, + rootMargin: "0px", + }); + const [position, setPosition] = useState(0); const theme = useMediaQuery("(prefers-color-scheme: dark)") ? "dark" @@ -37,6 +43,7 @@ const VideoPlayer = (props: Props) => { }, [isMobile]); useEffect(() => { + if (!entry?.isIntersecting) return; const interval = setInterval(() => { setPosition((prevPosition) => { if (!isMobile ? prevPosition === 8 : prevPosition === 2) { @@ -48,106 +55,110 @@ const VideoPlayer = (props: Props) => { }, duration); return () => clearInterval(interval); - }, [position, duration, isMobile]); + }, [position, duration, isMobile, entry?.isIntersecting]); return ( -
-
- setPosition(0)} - active={!isMobile ? position <= 2 : position === 0} - duration={!isMobile ? duration * 3 : duration} - > - {props.textContent.buttonCollab} - - setPosition(3)} - active={!isMobile ? position > 2 && position <= 5 : position === 1} - duration={!isMobile ? duration * 3 : duration} - > - {props.textContent.buttonModerate} - - setPosition(6)} - active={!isMobile ? position > 5 && position <= 8 : position === 2} - duration={!isMobile ? duration * 3 : duration} - > - {props.textContent.buttonCustomize} - -
-
- {!isMobile && ( - - - {`${props.textContent.screenshotAlt} - - )} -
-
- - {isMobile && ( -
+
); -} +}; export default VideoPlayer; diff --git a/src/views/Choices/Choices.astro b/src/views/Choices/Choices.astro index ce30e00..a5134b6 100644 --- a/src/views/Choices/Choices.astro +++ b/src/views/Choices/Choices.astro @@ -3,13 +3,12 @@ import VideoPlayer from "../../components/VideoPlayer"; import getTranslatedContent from "../../utils/directus"; import "./Choices.scss"; -const {lang} = Astro.params; +const { lang } = Astro.params; const content = await getTranslatedContent("Choices_Section", lang!); ---

{content.header}

{content.text}

- +
- diff --git a/src/views/Feedback/Feedback.astro b/src/views/Feedback/Feedback.astro index e267a5c..bfc5756 100644 --- a/src/views/Feedback/Feedback.astro +++ b/src/views/Feedback/Feedback.astro @@ -1,10 +1,10 @@ --- import FeedbackCarousel from "./FeedbackCarousel.tsx"; -import getTranslatedContent, {getContent} from "../../utils/directus"; +import getTranslatedContent, { getContent } from "../../utils/directus"; -const {lang} = Astro.params; +const { lang } = Astro.params; const content = await getTranslatedContent("Feedback_Section", lang!); -const testimonials = await getContent("testimonials") as FeedbackItem[]; +const testimonials = (await getContent("testimonials")) as FeedbackItem[]; export type FeedbackItem = { name: string; @@ -16,8 +16,8 @@ export type FeedbackItem = { ---