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 [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 */}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user