This repository has been archived on 2026-06-15. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MediaLore/src/components/mixed/VideoPlayerModal.tsx
2026-04-05 14:01:32 -04:00

120 lines
4.2 KiB
TypeScript

'use client'
import { useEffect, useRef, useState } from 'react'
import TagSelector from '@/components/tags/TagSelector'
interface Props {
url: string
name: string
onClose: () => void
mediaKey?: string
onTagsChanged?: () => void
}
export default function VideoPlayerModal({ url, name, onClose, mediaKey, onTagsChanged }: Props) {
const overlayRef = useRef<HTMLDivElement>(null)
const [showTags, setShowTags] = useState(
() => !!mediaKey && typeof window !== 'undefined' && window.innerWidth >= 1280
)
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])
const handleOverlayClick = (e: React.MouseEvent) => {
if (e.target === overlayRef.current) onClose()
}
return (
<div
ref={overlayRef}
className="fixed inset-0 z-50 flex flex-col items-center justify-center p-4 gap-3"
style={{ backgroundColor: 'rgba(0,0,0,0.9)' }}
onClick={handleOverlayClick}
>
{/* Toolbar */}
<div className={`flex items-center justify-between w-full ${showTags ? '' : 'max-w-4xl'}`}>
<span className="text-sm truncate max-w-[80%]" style={{ color: 'var(--text-secondary)' }}>
{name}
</span>
<div className="flex items-center gap-2 flex-shrink-0">
{mediaKey && (
<button
onClick={(e) => { e.stopPropagation(); setShowTags((v) => !v) }}
className="w-8 h-8 rounded-full flex items-center justify-center text-sm transition-colors"
style={{
backgroundColor: showTags ? 'var(--accent)' : 'var(--surface)',
color: showTags ? '#fff' : 'var(--text-primary)',
}}
onMouseEnter={(e) => {
if (!showTags) (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--surface-hover)'
}}
onMouseLeave={(e) => {
if (!showTags) (e.currentTarget as HTMLElement).style.backgroundColor = 'var(--surface)'
}}
aria-label={showTags ? 'Hide tags' : 'Show tags'}
title="Tags"
>
🏷
</button>
)}
<button
onClick={onClose}
className="w-8 h-8 rounded-full flex items-center justify-center text-sm flex-shrink-0 transition-colors"
style={{ backgroundColor: 'var(--surface)', color: 'var(--text-primary)' }}
onMouseEnter={(e) => ((e.currentTarget as HTMLElement).style.backgroundColor = 'var(--surface-hover)')}
onMouseLeave={(e) => ((e.currentTarget as HTMLElement).style.backgroundColor = 'var(--surface)')}
aria-label="Close"
>
</button>
</div>
</div>
{showTags ? (
<div className="flex gap-4 w-full flex-1 min-h-0 items-start">
{/* Video */}
<div className="flex-1 min-w-0 flex items-center justify-center">
<video
src={url}
controls
autoPlay
className="w-full max-h-full rounded-lg"
style={{ backgroundColor: '#000' }}
onClick={(e) => e.stopPropagation()}
/>
</div>
{/* Tag panel */}
<div
className="w-80 flex-shrink-0 rounded-xl overflow-y-auto max-h-[80vh] p-4"
style={{ backgroundColor: 'var(--surface)', border: '1px solid var(--border)' }}
onClick={(e) => e.stopPropagation()}
>
<p className="text-xs font-semibold uppercase tracking-wider mb-3" style={{ color: 'var(--text-secondary)' }}>
Tags
</p>
<TagSelector mediaKey={mediaKey!} onTagsChanged={onTagsChanged} />
</div>
</div>
) : (
<video
src={url}
controls
autoPlay
className="w-full max-w-4xl max-h-[80vh] rounded-lg"
style={{ backgroundColor: '#000' }}
onClick={(e) => e.stopPropagation()}
/>
)}
</div>
)
}