Skip to content

Instantly share code, notes, and snippets.

@jonoroboto
Last active August 7, 2024 13:44
Show Gist options
  • Save jonoroboto/48ffaa6d1b35a6c58d8e250bd633d33f to your computer and use it in GitHub Desktop.
Save jonoroboto/48ffaa6d1b35a6c58d8e250bd633d33f to your computer and use it in GitHub Desktop.
'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