diff --git a/client/src/components/bunny-video-modal.tsx b/client/src/components/bunny-video-modal.tsx index f244b47..a3b17bf 100644 --- a/client/src/components/bunny-video-modal.tsx +++ b/client/src/components/bunny-video-modal.tsx @@ -14,6 +14,8 @@ interface BunnyVideoModalProps { isOpen: boolean; onClose: () => void; onEdit?: () => void; + videos?: Video[]; + onVideoChange?: (video: Video) => void; } function formatDuration(seconds: number): string { @@ -49,8 +51,11 @@ function formatDate(date: Date | string): string { return `Pred ${Math.floor(diffDays / 30)} mesec${Math.floor(diffDays / 30) > 1 ? 'i' : 'em'}`; } -export default function BunnyVideoModal({ video, isOpen, onClose, onEdit }: BunnyVideoModalProps) { +export default function BunnyVideoModal({ video, isOpen, onClose, onEdit, videos = [], onVideoChange }: BunnyVideoModalProps) { const [showShareMenu, setShowShareMenu] = useState(false); + const [isDragging, setIsDragging] = useState(false); + const [dragStart, setDragStart] = useState({ x: 0, y: 0 }); + const [dragOffset, setDragOffset] = useState(0); useEffect(() => { const handleEscape = (e: KeyboardEvent) => { @@ -137,6 +142,100 @@ export default function BunnyVideoModal({ video, isOpen, onClose, onEdit }: Bunn setShowShareMenu(false); }; + // Navigation functions + const getCurrentVideoIndex = () => { + if (!video || !videos.length) return -1; + return videos.findIndex(v => v.id === video.id); + }; + + const navigateToVideo = (direction: 'next' | 'prev') => { + const currentIndex = getCurrentVideoIndex(); + if (currentIndex === -1) return; + + let newIndex; + if (direction === 'next') { + newIndex = currentIndex + 1 >= videos.length ? 0 : currentIndex + 1; + } else { + newIndex = currentIndex - 1 < 0 ? videos.length - 1 : currentIndex - 1; + } + + const newVideo = videos[newIndex]; + if (newVideo && onVideoChange) { + onVideoChange(newVideo); + } + }; + + // Touch and mouse drag handlers + const handleDragStart = (clientX: number, clientY: number) => { + setIsDragging(true); + setDragStart({ x: clientX, y: clientY }); + setDragOffset(0); + }; + + const handleDragMove = (clientX: number, clientY: number) => { + if (!isDragging) return; + + const deltaX = clientX - dragStart.x; + const deltaY = Math.abs(clientY - dragStart.y); + + // Only allow horizontal drag if it's more horizontal than vertical + if (deltaY < Math.abs(deltaX)) { + setDragOffset(deltaX); + } + }; + + const handleDragEnd = () => { + if (!isDragging) return; + + const threshold = 100; // minimum drag distance to trigger navigation + + if (Math.abs(dragOffset) > threshold && videos.length > 1) { + if (dragOffset > 0) { + navigateToVideo('prev'); // drag right = previous video + } else { + navigateToVideo('next'); // drag left = next video + } + } + + setIsDragging(false); + setDragOffset(0); + }; + + // Mouse events + const handleMouseDown = (e: React.MouseEvent) => { + if (e.target === e.currentTarget) return; // only on video area + handleDragStart(e.clientX, e.clientY); + }; + + const handleMouseMove = (e: React.MouseEvent) => { + handleDragMove(e.clientX, e.clientY); + }; + + const handleMouseUp = () => { + handleDragEnd(); + }; + + // Touch events + const handleTouchStart = (e: React.TouchEvent) => { + if (e.touches.length !== 1) return; + const touch = e.touches[0]; + handleDragStart(touch.clientX, touch.clientY); + e.preventDefault(); + }; + + const handleTouchMove = (e: React.TouchEvent) => { + if (e.touches.length !== 1) return; + if (!isDragging) return; + const touch = e.touches[0]; + handleDragMove(touch.clientX, touch.clientY); + e.preventDefault(); + }; + + const handleTouchEnd = (e: React.TouchEvent) => { + handleDragEnd(); + e.preventDefault(); + }; + if (!isOpen || !video) return null; return ( @@ -231,7 +330,17 @@ export default function BunnyVideoModal({ video, isOpen, onClose, onEdit }: Bunn