From a93f96c967301745f8bc5a537ad30ce119256054 Mon Sep 17 00:00:00 2001 From: kuekhaoyang Date: Tue, 13 Jan 2026 16:11:25 +0800 Subject: [PATCH] Fix Progress bar can't drag --- components/player/desktop/DesktopControls.tsx | 3 ++ .../player/desktop/DesktopControlsWrapper.tsx | 2 + .../player/desktop/DesktopProgressBar.tsx | 5 +- .../hooks/desktop/useProgressControls.ts | 50 ++++++++++++++++++- .../player/hooks/useDesktopPlayerLogic.ts | 1 + package-lock.json | 4 +- package.json | 2 +- 7 files changed, 61 insertions(+), 6 deletions(-) diff --git a/components/player/desktop/DesktopControls.tsx b/components/player/desktop/DesktopControls.tsx index fbc853e..7d894d6 100644 --- a/components/player/desktop/DesktopControls.tsx +++ b/components/player/desktop/DesktopControls.tsx @@ -30,6 +30,7 @@ interface DesktopControlsProps { onShowCastMenu: () => void; onProgressClick: (e: React.MouseEvent) => void; onProgressMouseDown: (e: React.MouseEvent) => void; + onProgressTouchStart: (e: React.TouchEvent) => void; formatTime: (seconds: number) => string; } @@ -41,6 +42,7 @@ export function DesktopControls(props: DesktopControlsProps) { progressBarRef, onProgressClick, onProgressMouseDown, + onProgressTouchStart, formatTime, } = props; @@ -57,6 +59,7 @@ export function DesktopControls(props: DesktopControlsProps) { duration={duration} onProgressClick={onProgressClick} onProgressMouseDown={onProgressMouseDown} + onProgressTouchStart={onProgressTouchStart} /> {/* Controls Bar */} diff --git a/components/player/desktop/DesktopControlsWrapper.tsx b/components/player/desktop/DesktopControlsWrapper.tsx index 875ad30..0a9deb9 100644 --- a/components/player/desktop/DesktopControlsWrapper.tsx +++ b/components/player/desktop/DesktopControlsWrapper.tsx @@ -37,6 +37,7 @@ export function DesktopControlsWrapper({ src, data, actions, logic, refs }: Desk showCastMenu, handleProgressClick, handleProgressMouseDown, + handleProgressTouchStart, formatTime, } = logic; @@ -73,6 +74,7 @@ export function DesktopControlsWrapper({ src, data, actions, logic, refs }: Desk onShowCastMenu={showCastMenu} onProgressClick={handleProgressClick} onProgressMouseDown={handleProgressMouseDown} + onProgressTouchStart={handleProgressTouchStart} formatTime={formatTime} /> ); diff --git a/components/player/desktop/DesktopProgressBar.tsx b/components/player/desktop/DesktopProgressBar.tsx index d3805e6..59b7a2d 100644 --- a/components/player/desktop/DesktopProgressBar.tsx +++ b/components/player/desktop/DesktopProgressBar.tsx @@ -7,6 +7,7 @@ interface DesktopProgressBarProps { duration: number; onProgressClick: (e: React.MouseEvent) => void; onProgressMouseDown: (e: React.MouseEvent) => void; + onProgressTouchStart: (e: React.TouchEvent) => void; } export function DesktopProgressBar({ @@ -14,7 +15,8 @@ export function DesktopProgressBar({ currentTime, duration, onProgressClick, - onProgressMouseDown + onProgressMouseDown, + onProgressTouchStart }: DesktopProgressBarProps) { return (
@@ -23,6 +25,7 @@ export function DesktopProgressBar({ className="slider-track cursor-pointer" onClick={onProgressClick} onMouseDown={onProgressMouseDown} + onTouchStart={onProgressTouchStart} style={{ pointerEvents: 'auto' }} >
{ + // 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]); + useEffect(() => { const handleProgressMouseMove = (e: MouseEvent) => { if (!isDraggingProgressRef.current || !progressBarRef.current || !videoRef.current) return; @@ -53,19 +71,47 @@ export function useProgressControls({ } }; + const handleProgressTouchMove = (e: TouchEvent) => { + if (!isDraggingProgressRef.current || !progressBarRef.current || !videoRef.current) return; + // e.preventDefault(); // Prevent scrolling while dragging progress + + 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; + lastDragTimeRef.current = newTime; + setCurrentTime(newTime); + }; + + const handleTouchEnd = () => { + if (isDraggingProgressRef.current) { + isDraggingProgressRef.current = false; + if (videoRef.current) { + videoRef.current.currentTime = lastDragTimeRef.current; + } + } + }; + document.addEventListener('mousemove', handleProgressMouseMove); document.addEventListener('mouseup', handleMouseUp); + document.addEventListener('touchmove', handleProgressTouchMove, { passive: false }); + document.addEventListener('touchend', handleTouchEnd); + document.addEventListener('touchcancel', handleTouchEnd); return () => { document.removeEventListener('mousemove', handleProgressMouseMove); document.removeEventListener('mouseup', handleMouseUp); + document.removeEventListener('touchmove', handleProgressTouchMove); + document.removeEventListener('touchend', handleTouchEnd); + document.removeEventListener('touchcancel', handleTouchEnd); }; }, [duration, isDraggingProgressRef, progressBarRef, videoRef, setCurrentTime]); const progressActions = useMemo(() => ({ handleProgressClick, - handleProgressMouseDown - }), [handleProgressClick, handleProgressMouseDown]); + handleProgressMouseDown, + handleProgressTouchStart + }), [handleProgressClick, handleProgressMouseDown, handleProgressTouchStart]); return progressActions; } diff --git a/components/player/hooks/useDesktopPlayerLogic.ts b/components/player/hooks/useDesktopPlayerLogic.ts index 03753d4..e8c7bc9 100644 --- a/components/player/hooks/useDesktopPlayerLogic.ts +++ b/components/player/hooks/useDesktopPlayerLogic.ts @@ -156,6 +156,7 @@ export function useDesktopPlayerLogic({ handleVideoError: playbackControls.handleVideoError, handleProgressClick: progressControls.handleProgressClick, handleProgressMouseDown: progressControls.handleProgressMouseDown, + handleProgressTouchStart: progressControls.handleProgressTouchStart, toggleMute: volumeControls.toggleMute, showVolumeBarTemporarily: volumeControls.showVolumeBarTemporarily, handleVolumeChange: volumeControls.handleVolumeChange, diff --git a/package-lock.json b/package-lock.json index b155a3b..4543bc5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "kvideo", - "version": "3.9.4", + "version": "3.9.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kvideo", - "version": "3.9.4", + "version": "3.9.5", "dependencies": { "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", diff --git a/package.json b/package.json index a1189d0..dcccdc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kvideo", - "version": "3.9.4", + "version": "3.9.5", "private": true, "scripts": { "dev": "next dev",