diff --git a/components/player/DesktopVideoPlayer.tsx b/components/player/DesktopVideoPlayer.tsx index b01a59a..90eddf2 100644 --- a/components/player/DesktopVideoPlayer.tsx +++ b/components/player/DesktopVideoPlayer.tsx @@ -42,9 +42,32 @@ export function DesktopVideoPlayer({ const { fullscreenType: settingsFullscreenType } = usePlayerSettings(); const isIOS = useIsIOS(); + // State to track if device is in landscape mode + const [isLandscape, setIsLandscape] = React.useState(true); + + React.useEffect(() => { + const checkOrientation = () => { + // Check if width > height + if (typeof window !== 'undefined') { + setIsLandscape(window.innerWidth > window.innerHeight); + } + }; + + checkOrientation(); + window.addEventListener('resize', checkOrientation); + window.addEventListener('orientationchange', checkOrientation); + return () => { + window.removeEventListener('resize', checkOrientation); + window.removeEventListener('orientationchange', checkOrientation); + }; + }, []); + // Force windowed fullscreen on iOS to avoid native player hijacking const fullscreenType = isIOS ? 'window' : settingsFullscreenType; + // Check if we need to force landscape (iOS + Fullscreen + Portrait) + const shouldForceLandscape = data.isFullscreen && fullscreenType === 'window' && isIOS && !isLandscape; + // Initialize HLS Player useHlsPlayer({ videoRef: refs.videoRef, @@ -84,7 +107,8 @@ export function DesktopVideoPlayer({ refs, data, actions, - fullscreenType + fullscreenType, + isForceLandscape: shouldForceLandscape }); // Auto-skip intro/outro and auto-next episode @@ -119,29 +143,6 @@ export function DesktopVideoPlayer({ handleVideoError, } = logic; - // State to track if device is in landscape mode - const [isLandscape, setIsLandscape] = React.useState(true); - - React.useEffect(() => { - const checkOrientation = () => { - // Check if width > height - if (typeof window !== 'undefined') { - setIsLandscape(window.innerWidth > window.innerHeight); - } - }; - - checkOrientation(); - window.addEventListener('resize', checkOrientation); - window.addEventListener('orientationchange', checkOrientation); - return () => { - window.removeEventListener('resize', checkOrientation); - window.removeEventListener('orientationchange', checkOrientation); - }; - }, []); - - // Check if we need to force landscape (iOS + Fullscreen + Portrait) - const shouldForceLandscape = data.isFullscreen && fullscreenType === 'window' && isIOS && !isLandscape; - return (
(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 [isFullscreen, setIsFullscreen] = React.useState(false); 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 (showSpeedMenu && 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 = 250; // approximate height of speed menu + const actualMenuHeight = menuRef.current?.offsetHeight || estimatedMenuHeight; + + // Determine if we should open upward + const openUpward = spaceBelow < Math.min(actualMenuHeight, 200) && 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.right - containerRect.left, + maxHeight: `${maxHeight}px`, + openUpward: true + }); + } else { setMenuPosition({ top: buttonRect.bottom - containerRect.top + 10, - left: buttonRect.right - containerRect.left + left: buttonRect.right - containerRect.left, + maxHeight: `${maxHeight}px`, + openUpward: false }); } - }, [showSpeedMenu, containerRef]); + }, [containerRef]); // Auto-close menu on scroll React.useEffect(() => { @@ -60,28 +98,33 @@ export function DesktopSpeedMenu({ return () => window.removeEventListener('scroll', handleScroll); }, [showSpeedMenu, onToggleSpeedMenu]); - const handleToggle = () => { - if (!showSpeedMenu && buttonRef.current && containerRef.current) { - const buttonRect = buttonRef.current.getBoundingClientRect(); - const containerRect = containerRef.current.getBoundingClientRect(); + // 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); + return () => clearTimeout(timer); + } + }, [showSpeedMenu, calculateMenuPosition]); - setMenuPosition({ - top: buttonRect.bottom - containerRect.top + 10, - left: buttonRect.right - containerRect.left - }); + const handleToggle = () => { + if (!showSpeedMenu) { + calculateMenuPosition(); } onToggleSpeedMenu(); }; - const MenuContent = (
void; isDraggingProgressRef: React.MutableRefObject; + isRotated?: boolean; } export function useProgressControls({ @@ -13,19 +14,34 @@ export function useProgressControls({ progressBarRef, duration, setCurrentTime, - isDraggingProgressRef + isDraggingProgressRef, + isRotated = false }: UseProgressControlsProps) { const lastDragTimeRef = useRef(0); + const getEventPos = useCallback((e: any, rect: DOMRect) => { + // Handle both mouse and touch events + const clientX = e.clientX || (e.touches && e.touches[0]?.clientX) || 0; + const clientY = e.clientY || (e.touches && e.touches[0]?.clientY) || 0; + + if (isRotated) { + // When rotated 90deg, visual left->right is physical top->bottom + // The bounding rect height is the visual width of the bar + return Math.max(0, Math.min(1, (clientY - rect.top) / rect.height)); + } else { + return Math.max(0, Math.min(1, (clientX - rect.left) / rect.width)); + } + }, [isRotated]); + const handleProgressClick = useCallback((e: any) => { if (!videoRef.current || !progressBarRef.current) return; const rect = progressBarRef.current.getBoundingClientRect(); - const pos = (e.clientX - rect.left) / rect.width; + const pos = getEventPos(e, rect); const newTime = pos * duration; videoRef.current.currentTime = newTime; lastDragTimeRef.current = newTime; // Update ref to prevent snap-back on mouseup setCurrentTime(newTime); - }, [videoRef, progressBarRef, duration, setCurrentTime]); + }, [videoRef, progressBarRef, duration, setCurrentTime, getEventPos]); const handleProgressMouseDown = useCallback((e: any) => { e.preventDefault(); @@ -34,29 +50,17 @@ export function useProgressControls({ }, [isDraggingProgressRef, handleProgressClick]); const handleProgressTouchStart = useCallback((e: any) => { - // e.preventDefault(); // Do not prevent default immediately to allow scrolling if needed, or check logic - // But for a slider, we usually want to capture the drag. e.preventDefault(); isDraggingProgressRef.current = true; - - // Calculate new time immediately on touch start - if (!videoRef.current || !progressBarRef.current) return; - const rect = progressBarRef.current.getBoundingClientRect(); - const touch = e.touches[0]; - const pos = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width)); - const newTime = pos * duration; - - videoRef.current.currentTime = newTime; - lastDragTimeRef.current = newTime; - setCurrentTime(newTime); - }, [videoRef, progressBarRef, duration, setCurrentTime, isDraggingProgressRef]); + handleProgressClick(e); + }, [isDraggingProgressRef, handleProgressClick]); useEffect(() => { const handleProgressMouseMove = (e: MouseEvent) => { if (!isDraggingProgressRef.current || !progressBarRef.current || !videoRef.current) return; e.preventDefault(); const rect = progressBarRef.current.getBoundingClientRect(); - const pos = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width)); + const pos = getEventPos(e, rect); const newTime = pos * duration; lastDragTimeRef.current = newTime; setCurrentTime(newTime); @@ -73,11 +77,10 @@ export function useProgressControls({ const handleProgressTouchMove = (e: TouchEvent) => { if (!isDraggingProgressRef.current || !progressBarRef.current || !videoRef.current) return; - // e.preventDefault(); // Prevent scrolling while dragging progress + if (e.cancelable) e.preventDefault(); const rect = progressBarRef.current.getBoundingClientRect(); - const touch = e.touches[0]; - const pos = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width)); + const pos = getEventPos(e, rect); const newTime = pos * duration; lastDragTimeRef.current = newTime; setCurrentTime(newTime); diff --git a/components/player/hooks/useDesktopPlayerLogic.ts b/components/player/hooks/useDesktopPlayerLogic.ts index 1d7a47a..fa74ab7 100644 --- a/components/player/hooks/useDesktopPlayerLogic.ts +++ b/components/player/hooks/useDesktopPlayerLogic.ts @@ -23,6 +23,7 @@ interface UseDesktopPlayerLogicProps { data: DesktopPlayerState['data']; actions: DesktopPlayerState['actions']; fullscreenType?: 'native' | 'window'; + isForceLandscape?: boolean; } export function useDesktopPlayerLogic({ @@ -34,7 +35,8 @@ export function useDesktopPlayerLogic({ refs, data, actions, - fullscreenType = 'native' + fullscreenType = 'native', + isForceLandscape = false }: UseDesktopPlayerLogicProps) { const { videoRef, containerRef, progressBarRef, volumeBarRef, @@ -104,7 +106,8 @@ export function useDesktopPlayerLogic({ const progressControls = useProgressControls({ videoRef, progressBarRef, duration, - setCurrentTime, isDraggingProgressRef + setCurrentTime, isDraggingProgressRef, + isRotated: isForceLandscape }); const skipControls = useSkipControls({ diff --git a/package-lock.json b/package-lock.json index 78878c9..942b84f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,10 +14,10 @@ "@vercel/analytics": "^1.6.1", "hls.js": "^1.6.15", "lucide-react": "^0.563.0", - "next": "16.1.4", - "react": "19.2.3", - "react-dom": "19.2.3", - "zustand": "^5.0.10" + "next": "16.1.6", + "react": "19.2.4", + "react-dom": "19.2.4", + "zustand": "^5.0.11" }, "devDependencies": { "@cloudflare/next-on-pages": "^1.13.16", @@ -26,7 +26,7 @@ "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", - "eslint-config-next": "16.1.4", + "eslint-config-next": "16.1.6", "postcss": "^8.5.6", "tailwindcss": "^4", "typescript": "^5" @@ -1306,15 +1306,15 @@ } }, "node_modules/@next/env": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.4.tgz", - "integrity": "sha512-gkrXnZyxPUy0Gg6SrPQPccbNVLSP3vmW8LU5dwEttEEC1RwDivk8w4O+sZIjFvPrSICXyhQDCG+y3VmjlJf+9A==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.6.tgz", + "integrity": "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.1.4.tgz", - "integrity": "sha512-38WMjGP8y+1MN4bcZFs+GTcBe0iem5GGTzFE5GWW/dWdRKde7LOXH3lQT2QuoquVWyfl2S0fQRchGmeacGZ4Wg==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.1.6.tgz", + "integrity": "sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1322,9 +1322,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.4.tgz", - "integrity": "sha512-T8atLKuvk13XQUdVLCv1ZzMPgLPW0+DWWbHSQXs0/3TjPrKNxTmUIhOEaoEyl3Z82k8h/gEtqyuoZGv6+Ugawg==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.6.tgz", + "integrity": "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==", "cpu": [ "arm64" ], @@ -1338,9 +1338,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.4.tgz", - "integrity": "sha512-AKC/qVjUGUQDSPI6gESTx0xOnOPQ5gttogNS3o6bA83yiaSZJek0Am5yXy82F1KcZCx3DdOwdGPZpQCluonuxg==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz", + "integrity": "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==", "cpu": [ "x64" ], @@ -1354,9 +1354,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.4.tgz", - "integrity": "sha512-POQ65+pnYOkZNdngWfMEt7r53bzWiKkVNbjpmCt1Zb3V6lxJNXSsjwRuTQ8P/kguxDC8LRkqaL3vvsFrce4dMQ==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz", + "integrity": "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==", "cpu": [ "arm64" ], @@ -1370,9 +1370,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.4.tgz", - "integrity": "sha512-3Wm0zGYVCs6qDFAiSSDL+Z+r46EdtCv/2l+UlIdMbAq9hPJBvGu/rZOeuvCaIUjbArkmXac8HnTyQPJFzFWA0Q==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz", + "integrity": "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==", "cpu": [ "arm64" ], @@ -1386,9 +1386,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.4.tgz", - "integrity": "sha512-lWAYAezFinaJiD5Gv8HDidtsZdT3CDaCeqoPoJjeB57OqzvMajpIhlZFce5sCAH6VuX4mdkxCRqecCJFwfm2nQ==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz", + "integrity": "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==", "cpu": [ "x64" ], @@ -1402,9 +1402,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.4.tgz", - "integrity": "sha512-fHaIpT7x4gA6VQbdEpYUXRGyge/YbRrkG6DXM60XiBqDM2g2NcrsQaIuj375egnGFkJow4RHacgBOEsHfGbiUw==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz", + "integrity": "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==", "cpu": [ "x64" ], @@ -1418,9 +1418,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.4.tgz", - "integrity": "sha512-MCrXxrTSE7jPN1NyXJr39E+aNFBrQZtO154LoCz7n99FuKqJDekgxipoodLNWdQP7/DZ5tKMc/efybx1l159hw==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz", + "integrity": "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==", "cpu": [ "arm64" ], @@ -1434,9 +1434,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.4.tgz", - "integrity": "sha512-JSVlm9MDhmTXw/sO2PE/MRj+G6XOSMZB+BcZ0a7d6KwVFZVpkHcb2okyoYFBaco6LeiL53BBklRlOrDDbOeE5w==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz", + "integrity": "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==", "cpu": [ "x64" ], @@ -3863,13 +3863,13 @@ } }, "node_modules/eslint-config-next": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.1.4.tgz", - "integrity": "sha512-iCrrNolUPpn/ythx0HcyNRfUBgTkaNBXByisKUbusPGCl8DMkDXXAu7exlSTSLGTIsH9lFE/c4s/3Qiyv2qwdA==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.1.6.tgz", + "integrity": "sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA==", "dev": true, "license": "MIT", "dependencies": { - "@next/eslint-plugin-next": "16.1.4", + "@next/eslint-plugin-next": "16.1.6", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", @@ -5906,12 +5906,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/next/-/next-16.1.4.tgz", - "integrity": "sha512-gKSecROqisnV7Buen5BfjmXAm7Xlpx9o2ueVQRo5DxQcjC8d330dOM1xiGWc2k3Dcnz0In3VybyRPOsudwgiqQ==", + "version": "16.1.6", + "resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz", + "integrity": "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==", "license": "MIT", "dependencies": { - "@next/env": "16.1.4", + "@next/env": "16.1.6", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.8.3", "caniuse-lite": "^1.0.30001579", @@ -5925,14 +5925,14 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.1.4", - "@next/swc-darwin-x64": "16.1.4", - "@next/swc-linux-arm64-gnu": "16.1.4", - "@next/swc-linux-arm64-musl": "16.1.4", - "@next/swc-linux-x64-gnu": "16.1.4", - "@next/swc-linux-x64-musl": "16.1.4", - "@next/swc-win32-arm64-msvc": "16.1.4", - "@next/swc-win32-x64-msvc": "16.1.4", + "@next/swc-darwin-arm64": "16.1.6", + "@next/swc-darwin-x64": "16.1.6", + "@next/swc-linux-arm64-gnu": "16.1.6", + "@next/swc-linux-arm64-musl": "16.1.6", + "@next/swc-linux-x64-gnu": "16.1.6", + "@next/swc-linux-x64-musl": "16.1.6", + "@next/swc-win32-arm64-msvc": "16.1.6", + "@next/swc-win32-x64-msvc": "16.1.6", "sharp": "^0.34.4" }, "peerDependencies": { @@ -6371,24 +6371,24 @@ "license": "MIT" }, "node_modules/react": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", - "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.3" + "react": "^19.2.4" } }, "node_modules/react-is": { @@ -7639,9 +7639,9 @@ } }, "node_modules/zustand": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.10.tgz", - "integrity": "sha512-U1AiltS1O9hSy3rul+Ub82ut2fqIAefiSuwECWt6jlMVUGejvf+5omLcRBSzqbRagSM3hQZbtzdeRc6QVScXTg==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.11.tgz", + "integrity": "sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg==", "license": "MIT", "engines": { "node": ">=12.20.0" diff --git a/package.json b/package.json index 2c3dbd7..c0d9a94 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kvideo", - "version": "4.0.6", + "version": "4.0.7", "private": true, "scripts": { "dev": "next dev",