diff --git a/components/player/DesktopVideoPlayer.tsx b/components/player/DesktopVideoPlayer.tsx index 90eddf2..fdf4dd7 100644 --- a/components/player/DesktopVideoPlayer.tsx +++ b/components/player/DesktopVideoPlayer.tsx @@ -183,6 +183,7 @@ export function DesktopVideoPlayer({ data={data} actions={actions} showControls={data.showControls} + isRotated={shouldForceLandscape} onTogglePlay={togglePlay} onSkipForward={logic.skipForward} onSkipBackward={logic.skipBackward} diff --git a/components/player/desktop/DesktopMoreMenu.tsx b/components/player/desktop/DesktopMoreMenu.tsx index aa5cddf..1b45ab5 100644 --- a/components/player/desktop/DesktopMoreMenu.tsx +++ b/components/player/desktop/DesktopMoreMenu.tsx @@ -15,6 +15,7 @@ interface DesktopMoreMenuProps { onMouseLeave: () => void; onCopyLink: (type?: 'original' | 'proxy') => void; containerRef: React.RefObject; + isRotated?: boolean; } export function DesktopMoreMenu({ @@ -24,7 +25,8 @@ export function DesktopMoreMenu({ onMouseEnter, onMouseLeave, onCopyLink, - containerRef + containerRef, + isRotated = false }: DesktopMoreMenuProps) { const { autoNextEpisode, @@ -119,6 +121,18 @@ export function DesktopMoreMenu({ } }, [containerRef]); + // When rotated, use direct viewport positioning + const calculateRotatedPosition = React.useCallback(() => { + if (!buttonRef.current) return; + const buttonRect = buttonRef.current.getBoundingClientRect(); + setMenuPosition({ + top: buttonRect.bottom + 10, + left: buttonRect.left, + maxHeight: `${window.innerHeight * 0.6}px`, + openUpward: false + }); + }, []); + // Auto-close menu on scroll React.useEffect(() => { if (!showMoreMenu) return; @@ -131,19 +145,31 @@ export function DesktopMoreMenu({ return () => window.removeEventListener('scroll', handleScroll); }, [showMoreMenu, onToggleMoreMenu]); - // Recalculate position when menu opens React.useEffect(() => { if (showMoreMenu) { - calculateMenuPosition(); - // Recalculate after a small delay to get actual menu height - const timer = setTimeout(calculateMenuPosition, 50); + if (isRotated) { + calculateRotatedPosition(); + } else { + calculateMenuPosition(); + } + const timer = setTimeout(() => { + if (isRotated) { + calculateRotatedPosition(); + } else { + calculateMenuPosition(); + } + }, 50); return () => clearTimeout(timer); } - }, [showMoreMenu, calculateMenuPosition]); + }, [showMoreMenu, calculateMenuPosition, calculateRotatedPosition, isRotated]); const handleToggle = () => { if (!showMoreMenu) { - calculateMenuPosition(); + if (isRotated) { + calculateRotatedPosition(); + } else { + calculateMenuPosition(); + } } onToggleMoreMenu(); }; @@ -151,16 +177,17 @@ export function DesktopMoreMenu({ const MenuContent = (
e.stopPropagation()} + onTouchStart={(e) => e.stopPropagation()} > {/* Copy Link Options */} {isProxied ? ( @@ -393,7 +420,7 @@ export function DesktopMoreMenu({ {/* More Menu Dropdown (Portal) */} - {showMoreMenu && typeof document !== 'undefined' && createPortal(MenuContent, containerRef.current || document.body)} + {showMoreMenu && typeof document !== 'undefined' && createPortal(MenuContent, isRotated ? document.body : (containerRef.current || document.body))}
); } diff --git a/components/player/desktop/DesktopOverlay.tsx b/components/player/desktop/DesktopOverlay.tsx index 1d98fdc..4626b3f 100644 --- a/components/player/desktop/DesktopOverlay.tsx +++ b/components/player/desktop/DesktopOverlay.tsx @@ -35,6 +35,7 @@ interface DesktopOverlayProps { onSpeedMenuMouseEnter: () => void; onSpeedMenuMouseLeave: () => void; containerRef: React.RefObject; + isRotated?: boolean; } export function DesktopOverlay({ @@ -67,6 +68,7 @@ export function DesktopOverlay({ onSpeedMenuMouseEnter, onSpeedMenuMouseLeave, containerRef, + isRotated = false, }: DesktopOverlayProps) { // Show navigation buttons when controls are visible or when paused (controls usually show when paused anyway) const showNavButtons = showControls || !isPlaying; @@ -83,6 +85,7 @@ export function DesktopOverlay({ onMouseLeave={onMoreMenuMouseLeave} onCopyLink={onCopyLink} containerRef={containerRef} + isRotated={isRotated} /> @@ -97,6 +100,7 @@ export function DesktopOverlay({ onMouseEnter={onSpeedMenuMouseEnter} onMouseLeave={onSpeedMenuMouseLeave} containerRef={containerRef} + isRotated={isRotated} /> diff --git a/components/player/desktop/DesktopOverlayWrapper.tsx b/components/player/desktop/DesktopOverlayWrapper.tsx index c7e7a29..82ccde1 100644 --- a/components/player/desktop/DesktopOverlayWrapper.tsx +++ b/components/player/desktop/DesktopOverlayWrapper.tsx @@ -6,6 +6,7 @@ interface DesktopOverlayWrapperProps { data: ReturnType['data']; actions: ReturnType['actions']; showControls: boolean; + isRotated?: boolean; onTogglePlay: () => void; onSkipForward: () => void; onSkipBackward: () => void; @@ -31,6 +32,7 @@ export function DesktopOverlayWrapper({ data, actions, showControls, + isRotated = false, onTogglePlay, onSkipForward, onSkipBackward, @@ -94,6 +96,7 @@ export function DesktopOverlayWrapper({ onSpeedMenuMouseEnter={onSpeedMenuMouseEnter} onSpeedMenuMouseLeave={onSpeedMenuMouseLeave} containerRef={containerRef} + isRotated={isRotated} /> ); } diff --git a/components/player/desktop/DesktopSpeedMenu.tsx b/components/player/desktop/DesktopSpeedMenu.tsx index 7de89a1..1badfaa 100644 --- a/components/player/desktop/DesktopSpeedMenu.tsx +++ b/components/player/desktop/DesktopSpeedMenu.tsx @@ -10,6 +10,7 @@ interface DesktopSpeedMenuProps { onMouseEnter: () => void; onMouseLeave: () => void; containerRef: React.RefObject; + isRotated?: boolean; } export function DesktopSpeedMenu({ @@ -20,7 +21,8 @@ export function DesktopSpeedMenu({ onToggleSpeedMenu, onMouseEnter, onMouseLeave, - containerRef + containerRef, + isRotated = false }: DesktopSpeedMenuProps) { const buttonRef = React.useRef(null); const menuRef = React.useRef(null); @@ -86,6 +88,18 @@ export function DesktopSpeedMenu({ } }, [containerRef]); + // When rotated, use direct viewport positioning + const calculateRotatedPosition = React.useCallback(() => { + if (!buttonRef.current) return; + const buttonRect = buttonRef.current.getBoundingClientRect(); + setMenuPosition({ + top: buttonRect.bottom + 10, + left: buttonRect.right, + maxHeight: `${window.innerHeight * 0.6}px`, + openUpward: false + }); + }, []); + // Auto-close menu on scroll React.useEffect(() => { if (!showSpeedMenu) return; @@ -98,19 +112,31 @@ export function DesktopSpeedMenu({ return () => window.removeEventListener('scroll', handleScroll); }, [showSpeedMenu, onToggleSpeedMenu]); - // Recalculate position when menu opens React.useEffect(() => { if (showSpeedMenu) { - calculateMenuPosition(); - // Recalculate after a small delay to get actual menu height - const timer = setTimeout(calculateMenuPosition, 50); + if (isRotated) { + calculateRotatedPosition(); + } else { + calculateMenuPosition(); + } + const timer = setTimeout(() => { + if (isRotated) { + calculateRotatedPosition(); + } else { + calculateMenuPosition(); + } + }, 50); return () => clearTimeout(timer); } - }, [showSpeedMenu, calculateMenuPosition]); + }, [showSpeedMenu, calculateMenuPosition, calculateRotatedPosition, isRotated]); const handleToggle = () => { if (!showSpeedMenu) { - calculateMenuPosition(); + if (isRotated) { + calculateRotatedPosition(); + } else { + calculateMenuPosition(); + } } onToggleSpeedMenu(); }; @@ -118,16 +144,18 @@ export function DesktopSpeedMenu({ const MenuContent = (
e.stopPropagation()} + onTouchStart={(e) => e.stopPropagation()} > {speeds.map((speed) => (
); }