Last active
August 7, 2024 13:44
-
-
Save jonoroboto/48ffaa6d1b35a6c58d8e250bd633d33f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use client'; | |
import { Loader2, PlayIcon } from 'lucide-react'; | |
import dynamic from 'next/dynamic'; | |
import { FC, useState } from 'react'; | |
import { preload } from 'react-dom'; | |
import { getMuxVideoProps } from '~/lib/helper'; | |
import { MuxVideo, Video as VideoType } from '~/sanity.types'; | |
type VideoPlay = { | |
poster: string; | |
vidUrl: string; | |
loop?: boolean; | |
muted?: boolean; | |
control?: boolean; | |
}; | |
const VideoAutoPlay = ({ control, loop, muted, poster, vidUrl }: VideoPlay) => { | |
const HlsVideo = dynamic( | |
() => import('./hls-video').then((mod) => mod.HlsVideo), | |
{ | |
loading: () => { | |
return ( | |
<div className="relative size-full"> | |
{/* eslint-disable-next-line @next/next/no-img-element */} | |
<img | |
src={poster} | |
width={1600} | |
height={900} | |
alt="a" | |
className="mx-auto size-full " | |
/> | |
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 transform "> | |
<Loader2 className="animate-spin" size={112} strokeWidth={0.5} /> | |
</div> | |
</div> | |
); | |
}, | |
}, | |
); | |
return ( | |
<HlsVideo | |
autoPlay | |
poster={poster} | |
vidUrl={vidUrl} | |
loop={control ? loop : undefined} | |
muted={control ? muted : undefined} | |
controls={control} | |
width={1600} | |
height={900} | |
className="mx-auto size-full" | |
/> | |
); | |
}; | |
const VideoWithOutAutoPlay = ( | |
props: VideoPlay & { loading?: 'lazy' | 'eager' }, | |
) => { | |
const { poster, loading } = props; | |
const [play, setPlay] = useState(false); | |
return ( | |
<div className=" size-full"> | |
{play ? ( | |
<div className="relative size-full "> | |
<div className="my-4"> | |
<VideoAutoPlay {...props} /> | |
</div> | |
</div> | |
) : ( | |
<div className="relative size-full"> | |
{/* eslint-disable-next-line @next/next/no-img-element */} | |
<img | |
src={poster} | |
width={1600} | |
height={900} | |
// priority={loading === 'eager'} | |
loading={loading === 'lazy' ? 'lazy' : 'eager'} | |
alt="a" | |
className="mx-auto size-full " | |
/> | |
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 transform "> | |
<button | |
className="grid place-items-center rounded-full bg-black p-8 hover:bg-hotpink-400" | |
onClick={() => setPlay(true)} | |
> | |
<PlayIcon className="h-8 w-8 fill-white text-white" /> | |
<span className="sr-only">Play</span> | |
</button> | |
</div> | |
</div> | |
)} | |
</div> | |
); | |
}; | |
export type VideoProps = VideoType & { | |
videoEmbed: NonNullable<VideoType['videoEmbed']> & { | |
video: MuxVideo & { | |
asset: { | |
playbackId: string; | |
}; | |
}; | |
}; | |
}; | |
export const Video: FC<VideoProps & { loading?: 'lazy' | 'eager' }> = ({ | |
videoEmbed, | |
loading = 'eager', | |
}) => { | |
const { video, autoPlay, control, loop, muted } = videoEmbed ?? {}; | |
const { poster, vidUrl } = getMuxVideoProps(video?.asset?.playbackId); | |
preload(vidUrl, { | |
as: 'video', | |
fetchPriority: 'high', | |
}); | |
preload(poster, { | |
as: 'image', | |
fetchPriority: 'high', | |
}); | |
const videoProps = { poster, loading, vidUrl, loop, muted, control }; | |
return ( | |
<div className="mx-auto flex max-w-7xl "> | |
{/* <div className="mx-auto size-full"> */} | |
{control && autoPlay ? ( | |
<VideoAutoPlay {...videoProps} /> | |
) : ( | |
<VideoWithOutAutoPlay {...videoProps} loading={loading} /> | |
)} | |
{/* </div> */} | |
</div> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment