diff --git a/app/layout.tsx b/app/layout.tsx index c3da363..d8ed1e0 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -77,6 +77,19 @@ export default function RootLayout({ }>) { return ( + + {/* PWA Manifest */} + + {/* Apple PWA Support */} + + + + + {/* Theme Color (for browser address bar) */} + + {/* Mobile viewport */} + + (null); - const [menuPosition, setMenuPosition] = React.useState({ top: 0, left: 0 }); + const menuRef = React.useRef(null); + const [menuPosition, setMenuPosition] = React.useState({ top: 0, left: 0, maxHeight: 'none', openUpward: false }); const [isAdFilterOpen, setAdFilterOpen] = React.useState(false); const AD_FILTER_LABELS: Record = { @@ -62,23 +63,61 @@ export function DesktopMoreMenu({ React.useEffect(() => { const updateFullscreen = () => { - setIsFullscreen(!!document.fullscreenElement); + // Check both native fullscreen and window fullscreen (CSS-based) + const nativeFullscreen = !!document.fullscreenElement; + const windowFullscreen = containerRef.current?.closest('.is-web-fullscreen') !== null; + setIsFullscreen(nativeFullscreen || windowFullscreen); }; document.addEventListener('fullscreenchange', updateFullscreen); + // Also check periodically for window fullscreen changes (CSS class based) + const interval = setInterval(updateFullscreen, 500); updateFullscreen(); - return () => document.removeEventListener('fullscreenchange', updateFullscreen); - }, []); + return () => { + document.removeEventListener('fullscreenchange', updateFullscreen); + clearInterval(interval); + }; + }, [containerRef]); - React.useEffect(() => { - if (showMoreMenu && buttonRef.current && containerRef.current) { - const buttonRect = buttonRef.current.getBoundingClientRect(); - const containerRect = containerRef.current.getBoundingClientRect(); + // Calculate menu position with available space awareness + const calculateMenuPosition = React.useCallback(() => { + if (!buttonRef.current || !containerRef.current) return; + + const buttonRect = buttonRef.current.getBoundingClientRect(); + const containerRect = containerRef.current.getBoundingClientRect(); + const viewportHeight = window.innerHeight; + + // Space available below and above the button + const spaceBelow = viewportHeight - buttonRect.bottom - 20; // 20px margin + const spaceAbove = buttonRect.top - containerRect.top - 20; + + // Estimate menu height (or use actual if already rendered) + const estimatedMenuHeight = 450; // approximate height of menu + const actualMenuHeight = menuRef.current?.offsetHeight || estimatedMenuHeight; + + // Determine if we should open upward + const openUpward = spaceBelow < Math.min(actualMenuHeight, 300) && spaceAbove > spaceBelow; + + // Calculate max-height based on available space + const maxHeight = openUpward + ? Math.min(spaceAbove, actualMenuHeight) + : Math.min(spaceBelow, viewportHeight * 0.7); + + if (openUpward) { + setMenuPosition({ + top: buttonRect.top - containerRect.top - 10, // Position above button + left: buttonRect.left - containerRect.left, + maxHeight: `${maxHeight}px`, + openUpward: true + }); + } else { setMenuPosition({ top: buttonRect.bottom - containerRect.top + 10, - left: buttonRect.left - containerRect.left + left: buttonRect.left - containerRect.left, + maxHeight: `${maxHeight}px`, + openUpward: false }); } - }, [showMoreMenu, containerRef]); + }, [containerRef]); // Auto-close menu on scroll React.useEffect(() => { @@ -92,25 +131,32 @@ 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); + return () => clearTimeout(timer); + } + }, [showMoreMenu, calculateMenuPosition]); + const handleToggle = () => { - if (!showMoreMenu && buttonRef.current && containerRef.current) { - const buttonRect = buttonRef.current.getBoundingClientRect(); - const containerRect = containerRef.current.getBoundingClientRect(); - setMenuPosition({ - top: buttonRect.bottom - containerRect.top + 10, - left: buttonRect.left - containerRect.left - }); + if (!showMoreMenu) { + calculateMenuPosition(); } onToggleMoreMenu(); }; const MenuContent = (