This commit is contained in:
alan 2026-08-05 01:20:32 +02:00 committed by GitHub
commit 4c306b5833
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 114 additions and 8 deletions

View file

@ -5107,9 +5107,10 @@ const HLSPlayer = forwardRef<HLSPlayerRef, HLSPlayerProps>(({
}
}, [activeTranslatedSubtitleId]);
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) {
@ -5124,7 +5125,7 @@ const HLSPlayer = forwardRef<HLSPlayerRef, HLSPlayerProps>(({
}
}, 5000);
}
};
}, [isPlaying, showCastMenu, showForwardAnimation, showRewindAnimation, showLeftTapAnimation, showRightTapAnimation]);
const togglePlay = () => {
@ -6569,6 +6570,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;
@ -10403,7 +10438,6 @@ const HLSPlayer = forwardRef<HLSPlayerRef, HLSPlayerProps>(({
};
const shouldHideCursor =
!isTouchDevice &&
!isCasting &&
isFullscreen &&
isPlaying &&
@ -10422,7 +10456,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)}
onClickCapture={handlePlayerControlInteractionCapture}
onChangeCapture={handlePlayerControlInteractionCapture}

View file

@ -1644,11 +1644,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();
@ -1917,6 +1952,7 @@ const LiveTVPlayer: React.FC<LiveTVPlayerProps> = ({
exit={{ opacity: 0 }}
className={`fixed inset-0 z-[12000] flex items-center justify-center bg-black ${shouldHideCursor ? 'cursor-none' : ''}`}
ref={containerRef}
onPointerMove={isEmbedStream ? undefined : handleMouseMove}
onMouseMove={isEmbedStream ? undefined : handleMouseMove}
onClick={isEmbedStream ? undefined : handleMouseMove}
onMouseLeave={isEmbedStream ? undefined : (() => {

View file

@ -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}
>