mirror of
https://github.com/movixcorp/MovixOpenSource.git
synced 2026-08-07 07:38:53 +00:00
fix: resolve player controls not waking up on mousemove in Firefox Wayland
This commit is contained in:
parent
4d742373b5
commit
4c6619a02f
3 changed files with 114 additions and 8 deletions
|
|
@ -4120,9 +4120,10 @@ const HLSPlayer = forwardRef<HLSPlayerRef, HLSPlayerProps>(({
|
|||
setTranslationLang(null);
|
||||
}, []);
|
||||
|
||||
const handleMouseMove = () => {
|
||||
// Do not show controls via mousemove on touch devices or while a touch gesture is active
|
||||
if (isTouchDevice || touchActiveRef.current) return;
|
||||
const handleMouseMove = useCallback((e?: Event | React.MouseEvent | PointerEvent) => {
|
||||
// Ignore touch drag events (touch taps/toggles are handled separately)
|
||||
if (touchActiveRef.current) return;
|
||||
if (e && 'pointerType' in e && (e as PointerEvent).pointerType === 'touch') return;
|
||||
|
||||
setShowControls(true);
|
||||
if (controlsTimeoutRef.current) {
|
||||
|
|
@ -4137,7 +4138,7 @@ const HLSPlayer = forwardRef<HLSPlayerRef, HLSPlayerProps>(({
|
|||
}
|
||||
}, 5000);
|
||||
}
|
||||
};
|
||||
}, [isPlaying, showCastMenu, showForwardAnimation, showRewindAnimation, showLeftTapAnimation, showRightTapAnimation]);
|
||||
|
||||
|
||||
const togglePlay = () => {
|
||||
|
|
@ -5330,6 +5331,40 @@ const HLSPlayer = forwardRef<HLSPlayerRef, HLSPlayerProps>(({
|
|||
};
|
||||
}, [isCastDragging, castDuration, handleCastProgressDragMove, handleCastProgressDragEnd]);
|
||||
|
||||
// Native listener binding for pointer & mouse movement to ensure controls wake up
|
||||
// across all platforms (including Firefox on Linux Wayland)
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
if (!container) return;
|
||||
|
||||
const onUserPointerActivity = (e: Event) => {
|
||||
handleMouseMove(e);
|
||||
};
|
||||
|
||||
const events = ['pointermove', 'mousemove', 'pointerenter', 'mouseenter'];
|
||||
|
||||
events.forEach(eventName => {
|
||||
container.addEventListener(eventName, onUserPointerActivity, { passive: true });
|
||||
});
|
||||
|
||||
const handleDocumentPointerMove = (e: Event) => {
|
||||
if (document.fullscreenElement || container.contains(e.target as Node)) {
|
||||
onUserPointerActivity(e);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('pointermove', handleDocumentPointerMove, { passive: true });
|
||||
document.addEventListener('mousemove', handleDocumentPointerMove, { passive: true });
|
||||
|
||||
return () => {
|
||||
events.forEach(eventName => {
|
||||
container.removeEventListener(eventName, onUserPointerActivity);
|
||||
});
|
||||
document.removeEventListener('pointermove', handleDocumentPointerMove);
|
||||
document.removeEventListener('mousemove', handleDocumentPointerMove);
|
||||
};
|
||||
}, [handleMouseMove]);
|
||||
|
||||
// Add event listener for PIP changes initiated outside our button
|
||||
useEffect(() => {
|
||||
const video = videoRef.current;
|
||||
|
|
@ -9046,7 +9081,6 @@ const HLSPlayer = forwardRef<HLSPlayerRef, HLSPlayerProps>(({
|
|||
};
|
||||
|
||||
const shouldHideCursor =
|
||||
!isTouchDevice &&
|
||||
!isCasting &&
|
||||
isFullscreen &&
|
||||
isPlaying &&
|
||||
|
|
@ -9065,7 +9099,8 @@ const HLSPlayer = forwardRef<HLSPlayerRef, HLSPlayerProps>(({
|
|||
<div
|
||||
ref={containerRef}
|
||||
className={`relative group w-full h-full bg-black rounded-xl overflow-hidden ${isLoading ? 'aspect-[16/9]' : ''} video-container ${className} ${isFullscreenAnimating ? 'fullscreen-animating' : ''} select-none ${shouldHideCursor || isLocked ? 'cursor-none' : ''}`}
|
||||
onMouseMove={!isTouchDevice ? handleMouseMove : undefined}
|
||||
onPointerMove={handleMouseMove}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={() => isPlaying && !showCastMenu && setShowControls(false)}
|
||||
onClick={handleVideoClick}
|
||||
onTouchStart={handleZoomTouchStart}
|
||||
|
|
|
|||
|
|
@ -1619,11 +1619,46 @@ const LiveTVPlayer: React.FC<LiveTVPlayerProps> = ({
|
|||
};
|
||||
}, [clearControlsTimeout, hideControlsTimeout, isFullscreen, isPlaying, isUserPaused, showControls, showSettings]);
|
||||
|
||||
const handleMouseMove = useCallback(() => {
|
||||
const handleMouseMove = useCallback((e?: Event | React.MouseEvent | PointerEvent) => {
|
||||
if (e && 'pointerType' in e && (e as PointerEvent).pointerType === 'touch') return;
|
||||
setShowControls(true);
|
||||
hideControlsTimeout();
|
||||
}, [hideControlsTimeout]);
|
||||
|
||||
// Native listener binding for pointer & mouse movement in LiveTVPlayer
|
||||
useEffect(() => {
|
||||
if (isEmbedStream) return;
|
||||
const container = containerRef.current;
|
||||
if (!container) return;
|
||||
|
||||
const onUserPointerActivity = (e: Event) => {
|
||||
handleMouseMove(e);
|
||||
};
|
||||
|
||||
const events = ['pointermove', 'mousemove', 'pointerenter', 'mouseenter'];
|
||||
|
||||
events.forEach(eventName => {
|
||||
container.addEventListener(eventName, onUserPointerActivity, { passive: true });
|
||||
});
|
||||
|
||||
const handleDocumentPointerMove = (e: Event) => {
|
||||
if (document.fullscreenElement || container.contains(e.target as Node)) {
|
||||
onUserPointerActivity(e);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('pointermove', handleDocumentPointerMove, { passive: true });
|
||||
document.addEventListener('mousemove', handleDocumentPointerMove, { passive: true });
|
||||
|
||||
return () => {
|
||||
events.forEach(eventName => {
|
||||
container.removeEventListener(eventName, onUserPointerActivity);
|
||||
});
|
||||
document.removeEventListener('pointermove', handleDocumentPointerMove);
|
||||
document.removeEventListener('mousemove', handleDocumentPointerMove);
|
||||
};
|
||||
}, [isEmbedStream, handleMouseMove]);
|
||||
|
||||
// Tap on video area to toggle play/pause (essential for mobile)
|
||||
const handleVideoClick = useCallback((e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
|
|
@ -1876,6 +1911,7 @@ const LiveTVPlayer: React.FC<LiveTVPlayerProps> = ({
|
|||
exit={{ opacity: 0 }}
|
||||
className={`fixed inset-0 z-[12000] flex items-center justify-center ${isEmbedStream ? 'bg-black/80 p-4 backdrop-blur-md sm:p-6' : 'bg-black'} ${shouldHideCursor ? 'cursor-none' : ''}`}
|
||||
ref={containerRef}
|
||||
onPointerMove={isEmbedStream ? undefined : handleMouseMove}
|
||||
onMouseMove={isEmbedStream ? undefined : handleMouseMove}
|
||||
onClick={isEmbedStream ? undefined : handleMouseMove}
|
||||
onMouseLeave={isEmbedStream ? undefined : (() => {
|
||||
|
|
|
|||
|
|
@ -480,10 +480,44 @@ const FranceTVPlayer: React.FC = () => {
|
|||
}, 5000);
|
||||
}, [isPlaying, showSettings]);
|
||||
|
||||
const handleMouseMove = useCallback(() => {
|
||||
const handleMouseMove = useCallback((e?: Event | React.MouseEvent | PointerEvent) => {
|
||||
if (e && 'pointerType' in e && (e as PointerEvent).pointerType === 'touch') return;
|
||||
resetControlsTimeout();
|
||||
}, [resetControlsTimeout]);
|
||||
|
||||
// Native listener binding for pointer & mouse movement in FranceTVPlayer
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
if (!container) return;
|
||||
|
||||
const onUserPointerActivity = (e: Event) => {
|
||||
handleMouseMove(e);
|
||||
};
|
||||
|
||||
const events = ['pointermove', 'mousemove', 'pointerenter', 'mouseenter'];
|
||||
|
||||
events.forEach(eventName => {
|
||||
container.addEventListener(eventName, onUserPointerActivity, { passive: true });
|
||||
});
|
||||
|
||||
const handleDocumentPointerMove = (e: Event) => {
|
||||
if (document.fullscreenElement || container.contains(e.target as Node)) {
|
||||
onUserPointerActivity(e);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('pointermove', handleDocumentPointerMove, { passive: true });
|
||||
document.addEventListener('mousemove', handleDocumentPointerMove, { passive: true });
|
||||
|
||||
return () => {
|
||||
events.forEach(eventName => {
|
||||
container.removeEventListener(eventName, onUserPointerActivity);
|
||||
});
|
||||
document.removeEventListener('pointermove', handleDocumentPointerMove);
|
||||
document.removeEventListener('mousemove', handleDocumentPointerMove);
|
||||
};
|
||||
}, [handleMouseMove]);
|
||||
|
||||
const handleMouseLeave = useCallback(() => {
|
||||
if (isPlaying) {
|
||||
if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);
|
||||
|
|
@ -759,6 +793,7 @@ const FranceTVPlayer: React.FC = () => {
|
|||
ref={containerRef}
|
||||
style={{ minHeight: 'calc(var(--vh, 1vh) * 100)', overflow: 'hidden' }}
|
||||
className="w-full bg-black text-white overflow-hidden fixed inset-0 z-40"
|
||||
onPointerMove={handleMouseMove}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
|
|
|
|||
Loading…
Reference in a new issue