Enhance video player with progress sharing and time display

Update the video player to show the current playback progress with a hover-over time tooltip, a blue progress bar, and a share button with social media links.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: d7424866-83d1-4486-a212-ac12b4c7becf
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/d7424866-83d1-4486-a212-ac12b4c7becf/J2c5fwX
This commit is contained in:
sebastjanartic 2025-08-07 11:00:07 +00:00
parent 330a069bcd
commit ae3fea9c82

View File

@ -66,6 +66,7 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
const [currentTime, setCurrentTime] = useState(0); const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(0); const [duration, setDuration] = useState(0);
const [volume, setVolume] = useState(1); const [volume, setVolume] = useState(1);
const [hoverTime, setHoverTime] = useState(-1);
useEffect(() => { useEffect(() => {
const handleEscape = (e: KeyboardEvent) => { const handleEscape = (e: KeyboardEvent) => {
@ -364,6 +365,15 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
} }
}; };
const handleProgressHover = (e: React.MouseEvent<HTMLDivElement>) => {
if (duration > 0) {
const rect = e.currentTarget.getBoundingClientRect();
const hoverX = e.clientX - rect.left;
const time = (hoverX / rect.width) * duration;
setHoverTime(Math.max(0, Math.min(duration, time)));
}
};
const handleVolumeChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleVolumeChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newVolume = parseFloat(e.target.value); const newVolume = parseFloat(e.target.value);
if (videoRef.current) { if (videoRef.current) {
@ -475,14 +485,26 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
{/* Progress Bar */} {/* Progress Bar */}
<div className="mb-3"> <div className="mb-3">
<div <div
className="w-full h-2 bg-white/20 rounded-full cursor-pointer hover:h-3 transition-all duration-200" className="w-full h-2 bg-white/20 rounded-full cursor-pointer hover:h-3 transition-all duration-200 relative"
onClick={handleProgressClick} onClick={handleProgressClick}
onMouseMove={handleProgressHover}
onMouseLeave={() => setHoverTime(-1)}
data-testid="progress-bar" data-testid="progress-bar"
> >
<div <div
className="h-full bg-bunny-blue rounded-full transition-all duration-200" className="h-full bg-blue-500 rounded-full transition-all duration-200"
style={{ width: `${duration > 0 ? (currentTime / duration) * 100 : 0}%` }} style={{ width: `${duration > 0 ? (currentTime / duration) * 100 : 0}%` }}
/> />
{/* Time tooltip on hover */}
{hoverTime >= 0 && (
<div
className="absolute -top-8 bg-black/80 text-white text-xs px-2 py-1 rounded pointer-events-none"
style={{ left: `${(hoverTime / duration) * 100}%`, transform: 'translateX(-50%)' }}
>
{formatTime(hoverTime)}
</div>
)}
</div> </div>
</div> </div>
@ -526,6 +548,73 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
{formatTime(currentTime)} / {formatTime(duration)} {formatTime(currentTime)} / {formatTime(duration)}
</div> </div>
{/* Share Button */}
<div className="relative">
<Button
onClick={() => setShowShareMenu(!showShareMenu)}
variant="ghost"
size="icon"
className="text-white hover:text-bunny-blue transition-colors"
data-testid="button-share"
>
<Share2 className="w-5 h-5" />
</Button>
{/* Share Menu */}
{showShareMenu && (
<div className="absolute bottom-12 right-0 bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 z-50 min-w-[200px]">
<div className="flex flex-col gap-2">
<div className="pb-2 border-b border-gray-200 dark:border-gray-600">
<span className="text-sm font-medium text-gray-900 dark:text-gray-100">Share Video</span>
</div>
<div
onClick={() => {
window.open(`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(getShareUrl())}`, '_blank', 'width=600,height=400');
setShowShareMenu(false);
}}
className="flex items-center gap-2 p-2 w-full hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer"
>
<FacebookIcon size={20} round />
<span className="text-sm text-gray-900 dark:text-gray-100">Facebook</span>
</div>
<div
onClick={() => {
window.open(`https://twitter.com/intent/tweet?url=${encodeURIComponent(getShareUrl())}&text=${encodeURIComponent(`Watch "${video.title}" on g4.video`)}`, '_blank', 'width=600,height=400');
setShowShareMenu(false);
}}
className="flex items-center gap-2 p-2 w-full hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer"
>
<TwitterIcon size={20} round />
<span className="text-sm text-gray-900 dark:text-gray-100">Twitter</span>
</div>
<div
onClick={() => {
window.open(`https://wa.me/?text=${encodeURIComponent(`Watch "${video.title}" on g4.video: ${getShareUrl()}`)}`, '_blank');
setShowShareMenu(false);
}}
className="flex items-center gap-2 p-2 w-full hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer"
>
<WhatsappIcon size={20} round />
<span className="text-sm text-gray-900 dark:text-gray-100">WhatsApp</span>
</div>
<button
onClick={copyToClipboard}
className="flex items-center gap-2 p-2 w-full hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer text-left"
>
<div className="w-5 h-5 bg-gray-500 rounded-full flex items-center justify-center">
<span className="text-white text-xs">📋</span>
</div>
<span className="text-sm text-gray-900 dark:text-gray-100">Copy Link</span>
</button>
</div>
</div>
)}
</div>
{/* Fullscreen Button */} {/* Fullscreen Button */}
<Button <Button
onClick={toggleFullscreen} onClick={toggleFullscreen}
@ -548,87 +637,7 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
/> />
)} )}
{/* Video Controls - only show on hover */}
{showControls && (
<div className="absolute top-4 right-4 flex gap-2 transition-opacity duration-300">
{/* Share Button */}
<div className="relative">
<Button
onClick={() => setShowShareMenu(!showShareMenu)}
variant="secondary"
size="sm"
className="bg-black/50 hover:bg-black/70 border-white/20"
data-testid="button-share"
>
<Share2 className="w-4 h-4 text-white" />
</Button>
{/* Share Menu - moved to bottom */}
{showShareMenu && (
<div className="absolute top-12 right-0 bg-white dark:bg-gray-800 rounded-lg shadow-lg p-4 z-50 min-w-[200px]">
<div className="flex flex-col gap-2">
<div className="pb-2 border-b border-gray-200 dark:border-gray-600">
<span className="text-sm font-medium text-gray-900 dark:text-gray-100">Share Video</span>
{videoThumbnail && (
<div className="mt-2">
<img
src={videoThumbnail}
alt="Video preview"
className="w-full h-20 object-cover rounded border"
/>
<span className="text-xs text-gray-600 dark:text-gray-400 mt-1 block">Preview image for sharing</span>
</div>
)}
</div>
<div
onClick={() => {
console.log('Facebook share clicked:', getShareUrl());
window.open(`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(getShareUrl())}`, '_blank', 'width=600,height=400');
}}
className="flex items-center gap-2 p-2 w-full hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer"
>
<FacebookIcon size={20} round />
<span className="text-sm text-gray-900 dark:text-gray-100">Facebook</span>
</div>
<div
onClick={() => {
console.log('Twitter share clicked:', getShareUrl());
window.open(`https://twitter.com/intent/tweet?url=${encodeURIComponent(getShareUrl())}&text=${encodeURIComponent(`Watch "${video.title}" on g4.video`)}`, '_blank', 'width=600,height=400');
}}
className="flex items-center gap-2 p-2 w-full hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer"
>
<TwitterIcon size={20} round />
<span className="text-sm text-gray-900 dark:text-gray-100">Twitter</span>
</div>
<div
onClick={() => {
console.log('WhatsApp share clicked:', getShareUrl());
window.open(`https://wa.me/?text=${encodeURIComponent(`Watch "${video.title}" on g4.video: ${getShareUrl()}`)}`, '_blank');
}}
className="flex items-center gap-2 p-2 w-full hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer"
>
<WhatsappIcon size={20} round />
<span className="text-sm text-gray-900 dark:text-gray-100">WhatsApp</span>
</div>
<button
onClick={copyToClipboard}
className="flex items-center gap-2 p-2 w-full hover:bg-gray-100 dark:hover:bg-gray-700 rounded cursor-pointer text-left"
>
<div className="w-5 h-5 bg-gray-500 rounded-full flex items-center justify-center">
<span className="text-white text-xs">📋</span>
</div>
<span className="text-sm text-gray-900 dark:text-gray-100">Copy Link</span>
</button>
</div>
</div>
)}
</div>
</div>
)}
</div> </div>
{/* Video info - only show when not playing or when controls are visible */} {/* Video info - only show when not playing or when controls are visible */}