diff --git a/shared/locales/de/website-home.json b/shared/locales/de/website-home.json index 8588a3b65..233b14845 100644 --- a/shared/locales/de/website-home.json +++ b/shared/locales/de/website-home.json @@ -20,6 +20,7 @@ } ] }, + "video-subtitle": "/assets/video/subtitle-video-testimonials.de_DE.vtt", "section-2": { "title-1": "Die Menschen in den ärmsten Regionen Sierra Leones kennen den Weg aus der Armut. ", "title-2": [ diff --git a/shared/locales/en/website-home.json b/shared/locales/en/website-home.json index 978a50e15..6e8fdf5b5 100644 --- a/shared/locales/en/website-home.json +++ b/shared/locales/en/website-home.json @@ -20,6 +20,7 @@ } ] }, + "video-subtitle": "/assets/video/subtitle-video-testimonials.en_US.vtt", "section-2": { "title-1": "Those that live in Sierra Leone’s poorest communities know what it takes to rise out of poverty.", "title-2": [ diff --git a/shared/locales/fr/website-home.json b/shared/locales/fr/website-home.json index 5db651c88..da847dafd 100644 --- a/shared/locales/fr/website-home.json +++ b/shared/locales/fr/website-home.json @@ -20,6 +20,7 @@ } ] }, + "video-subtitle": "/assets/video/subtitle-video-testimonials.fr_FR.vtt", "section-2": { "title-1": "Dans les communautés les plus pauvres de Sierra Leone, les gens savent très bien ce qu’il faut faire pour sortir de la pauvreté.", "title-2": [ diff --git a/shared/locales/it/website-home.json b/shared/locales/it/website-home.json index f883c1fc8..30733c662 100644 --- a/shared/locales/it/website-home.json +++ b/shared/locales/it/website-home.json @@ -20,6 +20,7 @@ } ] }, + "video-subtitle": "/assets/video/subtitle-video-testimonials.it_IT.vtt", "section-2": { "title-1": "Le persone che vivono nelle comunità più povere della Sierra Leone sanno di cosa hanno bisogno per uscire dalla povertà.", "title-2": [ diff --git a/website/src/app/[lang]/[region]/(website)/(home)/(components)/mux-video.tsx b/website/src/app/[lang]/[region]/(website)/(home)/(components)/mux-video.tsx index 325348501..67fdbf247 100644 --- a/website/src/app/[lang]/[region]/(website)/(home)/(components)/mux-video.tsx +++ b/website/src/app/[lang]/[region]/(website)/(home)/(components)/mux-video.tsx @@ -1,24 +1,45 @@ 'use client'; +import { DefaultParams } from '@/app/[lang]/[region]'; import { useGlobalStateProvider } from '@/components/providers/global-state-provider'; import { PauseIcon, PlayIcon, SpeakerWaveIcon, SpeakerXMarkIcon } from '@heroicons/react/24/solid'; import MuxVideo from '@mux/mux-video-react'; import { Button } from '@socialincome/ui'; import classNames from 'classnames'; +import Image from 'next/image'; import { useEffect, useRef, useState } from 'react'; import { useEventListener, useIntersectionObserver } from 'usehooks-ts'; export const OVERLAY_FADE_OUT_DELAY = 4000; +type HeroVideoSubtitles = { + translations: { + subtitles: string; + }; +} & DefaultParams; + +const MuxVideoComponent = ({ lang, translations }: HeroVideoSubtitles) => { + const [error, setError] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const handleError = (e: Event) => { + setError(new Error('Failed to load video')); + setIsLoading(false); + }; -const MuxVideoComponent = () => { + useEffect(() => { + const video = videoElementRef.current; + if (video) { + video.addEventListener('error', handleError); + return () => video.removeEventListener('error', handleError); + } + }, []); const videoElementRef = useRef(null); + const posterRef = useRef(null); const [muted, setMuted] = useState(true); const [playing, setPlaying] = useState(false); const [showCaptions, setShowCaptions] = useState(true); const [showControls, setShowControls] = useState(true); const { entry, isIntersecting, ref } = useIntersectionObserver({ initialIsIntersecting: true, threshold: 0.5 }); const { setBackgroundColor } = useGlobalStateProvider(); - useEffect(() => { if (!entry) return; if (!isIntersecting && entry.boundingClientRect.top < 0) { @@ -34,8 +55,18 @@ const MuxVideoComponent = () => { }, [entry, isIntersecting]); useEffect(() => { - if (playing) { - videoElementRef.current?.play(); + const video = videoElementRef.current; + if (playing && video) { + // Hide poster when video is ready + const handleCanPlay = () => { + if (posterRef.current) { + posterRef.current.style.opacity = '0'; + posterRef.current.style.transition = 'opacity 0.5s ease'; + } + }; + video.addEventListener('canplay', handleCanPlay); + video.play(); + return () => video.removeEventListener('canplay', handleCanPlay); } else { videoElementRef.current?.pause(); } @@ -67,32 +98,34 @@ const MuxVideoComponent = () => { return ( <> +
+ Video Poster +
setPlaying(true)} // Ensure smooth start > - + + video::cue { + background-color: rgba(0, 0, 0, 0.8); + color: white; + font-family: Arial, sans-serif; + font-size: 24px; + opacity: ${showCaptions ? 1 : 0}; + } + `} {/* Transparent element used to track whether navbar should be transparent or not */}
@@ -131,5 +164,4 @@ const MuxVideoComponent = () => { ); }; - export default MuxVideoComponent; diff --git a/website/src/app/[lang]/[region]/(website)/(home)/(sections)/hero-video.tsx b/website/src/app/[lang]/[region]/(website)/(home)/(sections)/hero-video.tsx index 1a6bb0021..ef4815115 100644 --- a/website/src/app/[lang]/[region]/(website)/(home)/(sections)/hero-video.tsx +++ b/website/src/app/[lang]/[region]/(website)/(home)/(sections)/hero-video.tsx @@ -12,7 +12,13 @@ export async function HeroVideo({ lang, region }: DefaultParams) { return (
- + ('video-subtitle'), + }} + lang={lang} + region={region} + />