Improve video player controls for better user interaction

Implement temporary visibility for video player navigation controls, making them appear on hover or click and fade out after a short period of inactivity.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 2eb1084e-b728-4449-9231-f1665924c8d5
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/2eb1084e-b728-4449-9231-f1665924c8d5/1Ar8Azc
This commit is contained in:
sebastjanartic 2025-08-28 21:01:07 +00:00
parent 297a1e1a1e
commit f5a1a2d391

View File

@ -53,6 +53,8 @@ function formatDate(date: Date | string): string {
export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos = [], onVideoChange }: BunnyVideoModalProps) { export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos = [], onVideoChange }: BunnyVideoModalProps) {
const [showShareMenu, setShowShareMenu] = useState(false); const [showShareMenu, setShowShareMenu] = useState(false);
const [showNavigation, setShowNavigation] = useState(true);
const [navigationTimeout, setNavigationTimeout] = useState<NodeJS.Timeout | null>(null);
// Navigation functions // Navigation functions
const getCurrentVideoIndex = () => { const getCurrentVideoIndex = () => {
@ -74,9 +76,26 @@ export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos
const newVideo = videos[newIndex]; const newVideo = videos[newIndex];
if (newVideo) { if (newVideo) {
onVideoChange(newVideo); onVideoChange(newVideo);
showNavigationTemporarily();
} }
}; };
const showNavigationTemporarily = () => {
setShowNavigation(true);
// Počisti prejšnji timeout
if (navigationTimeout) {
clearTimeout(navigationTimeout);
}
// Sakrij navigacijo po 4 sekundah
const timeout = setTimeout(() => {
setShowNavigation(false);
}, 4000);
setNavigationTimeout(timeout);
};
useEffect(() => { useEffect(() => {
const handleEscape = (e: KeyboardEvent) => { const handleEscape = (e: KeyboardEvent) => {
@ -88,6 +107,9 @@ export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos
if (isOpen) { if (isOpen) {
document.addEventListener("keydown", handleEscape); document.addEventListener("keydown", handleEscape);
document.body.style.overflow = "hidden"; document.body.style.overflow = "hidden";
// Prikaži kontrole ob odprtju modala
showNavigationTemporarily();
} else { } else {
document.body.style.overflow = ""; document.body.style.overflow = "";
} }
@ -95,9 +117,22 @@ export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos
return () => { return () => {
document.removeEventListener("keydown", handleEscape); document.removeEventListener("keydown", handleEscape);
document.body.style.overflow = ""; document.body.style.overflow = "";
// Počisti timeout ob zaprtju
if (navigationTimeout) {
clearTimeout(navigationTimeout);
setNavigationTimeout(null);
}
}; };
}, [isOpen, onClose]); }, [isOpen, onClose]);
// Prikaži kontrole ob menjavi videa
useEffect(() => {
if (isOpen && video) {
showNavigationTemporarily();
}
}, [video?.id, isOpen]);
const handleVideoPlay = async () => { const handleVideoPlay = async () => {
if (video) { if (video) {
try { try {
@ -258,7 +293,11 @@ export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos
<div className="flex-1 flex flex-col lg:flex-row gap-4 min-h-0"> <div className="flex-1 flex flex-col lg:flex-row gap-4 min-h-0">
{/* Main video player */} {/* Main video player */}
<div className="flex-1"> <div className="flex-1">
<div className="relative w-full aspect-video bg-black rounded-lg overflow-hidden"> <div
className="relative w-full aspect-video bg-black rounded-lg overflow-hidden"
onMouseEnter={showNavigationTemporarily}
onClick={showNavigationTemporarily}
>
{video.videoUrlIframe ? ( {video.videoUrlIframe ? (
<iframe <iframe
src={video.videoUrlIframe} src={video.videoUrlIframe}
@ -275,12 +314,14 @@ export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos
</div> </div>
)} )}
{/* Navigation buttons - always visible */} {/* Navigation buttons - fade in/out */}
{videos.length > 1 && ( {videos.length > 1 && (
<> <>
<Button <Button
onClick={() => navigateToVideo('prev')} onClick={() => navigateToVideo('prev')}
className="absolute left-4 top-1/2 transform -translate-y-1/2 bg-black bg-opacity-60 hover:bg-opacity-80 text-white border-none p-2 rounded-full z-20" className={`absolute left-4 top-1/2 transform -translate-y-1/2 bg-black bg-opacity-60 hover:bg-opacity-80 text-white border-none p-2 rounded-full z-20 transition-opacity duration-1000 ${
showNavigation ? 'opacity-100' : 'opacity-0 pointer-events-none'
}`}
size="sm" size="sm"
data-testid="button-prev-video" data-testid="button-prev-video"
> >
@ -288,7 +329,9 @@ export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos
</Button> </Button>
<Button <Button
onClick={() => navigateToVideo('next')} onClick={() => navigateToVideo('next')}
className="absolute right-4 top-1/2 transform -translate-y-1/2 bg-black bg-opacity-60 hover:bg-opacity-80 text-white border-none p-2 rounded-full z-20" className={`absolute right-4 top-1/2 transform -translate-y-1/2 bg-black bg-opacity-60 hover:bg-opacity-80 text-white border-none p-2 rounded-full z-20 transition-opacity duration-1000 ${
showNavigation ? 'opacity-100' : 'opacity-0 pointer-events-none'
}`}
size="sm" size="sm"
data-testid="button-next-video" data-testid="button-next-video"
> >