73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { useEffect, useRef } from "react";
|
|
|
|
interface VideoPlayerModalProps {
|
|
videoId: string;
|
|
title: string;
|
|
onClose: () => void;
|
|
localVideoPath?: string | null;
|
|
}
|
|
|
|
export default function VideoPlayerModal({ videoId, title, onClose, localVideoPath }: VideoPlayerModalProps) {
|
|
const videoRef = useRef<HTMLVideoElement>(null);
|
|
|
|
useEffect(() => {
|
|
const handleKey = (e: KeyboardEvent) => {
|
|
if (e.key === "Escape") onClose();
|
|
};
|
|
document.addEventListener("keydown", handleKey);
|
|
document.body.style.overflow = "hidden";
|
|
return () => {
|
|
document.removeEventListener("keydown", handleKey);
|
|
document.body.style.overflow = "";
|
|
};
|
|
}, [onClose]);
|
|
|
|
useEffect(() => {
|
|
if (videoRef.current && localVideoPath) {
|
|
videoRef.current.play().catch(() => {});
|
|
}
|
|
}, [localVideoPath]);
|
|
|
|
return (
|
|
<div
|
|
className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm"
|
|
onClick={onClose}
|
|
>
|
|
<div
|
|
className="bg-slate-900 rounded-xl overflow-hidden w-full max-w-4xl mx-4 shadow-2xl"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-center justify-between px-4 py-3 border-b border-slate-700">
|
|
<h2 className="text-white font-semibold truncate pr-4">{title}</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-slate-400 hover:text-white transition-colors flex-shrink-0"
|
|
>
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<div className="aspect-video bg-black">
|
|
{localVideoPath ? (
|
|
<video
|
|
ref={videoRef}
|
|
src={localVideoPath}
|
|
controls
|
|
className="w-full h-full"
|
|
autoPlay
|
|
/>
|
|
) : (
|
|
<iframe
|
|
src={`https://www.youtube.com/embed/${videoId}?autoplay=1&rel=0`}
|
|
title={title}
|
|
className="w-full h-full"
|
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; fullscreen"
|
|
allowFullScreen
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |