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:
parent
330a069bcd
commit
ae3fea9c82
@ -66,6 +66,7 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
|
||||
const [currentTime, setCurrentTime] = useState(0);
|
||||
const [duration, setDuration] = useState(0);
|
||||
const [volume, setVolume] = useState(1);
|
||||
const [hoverTime, setHoverTime] = useState(-1);
|
||||
|
||||
useEffect(() => {
|
||||
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 newVolume = parseFloat(e.target.value);
|
||||
if (videoRef.current) {
|
||||
@ -475,14 +485,26 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
|
||||
{/* Progress Bar */}
|
||||
<div className="mb-3">
|
||||
<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}
|
||||
onMouseMove={handleProgressHover}
|
||||
onMouseLeave={() => setHoverTime(-1)}
|
||||
data-testid="progress-bar"
|
||||
>
|
||||
<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}%` }}
|
||||
/>
|
||||
|
||||
{/* 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>
|
||||
|
||||
@ -526,6 +548,73 @@ export default function VideoModal({ video, isOpen, onClose }: VideoModalProps)
|
||||
{formatTime(currentTime)} / {formatTime(duration)}
|
||||
</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 */}
|
||||
<Button
|
||||
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>
|
||||
|
||||
{/* Video info - only show when not playing or when controls are visible */}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user