fix(player): reclaim keyboard focus when fullscreen ends
UAT found a dead end: F -> YouTube's fullscreen button -> Esc left the player maximised with no way back, and a further F produced a second, control-less fullscreen with the wheel driving YouTube's own volume box. Measured cause: reaching YouTube's control bar means clicking INTO the player, which moves keyboard focus into the cross-origin iframe — and it stays there. Our window-level shortcuts then never fire (document.activeElement === IFRAME), so F went to YouTube instead of toggling our maximise. Fix: on fullscreenchange, when fullscreen ends, focus the modal card again. Verified in real Chrome, step by step: - F -> maximised, no browser lock, focus on our card - YouTube's own FS button -> real fullscreen (innerHeight 889 -> 1024) - leaving fullscreen -> focus back on our card (was: still the iframe) - F -> back to the normal modal view (was: a second fullscreen with no controls)
This commit is contained in:
@@ -555,9 +555,8 @@ export default function PlayerModal({
|
|||||||
return () => el.removeEventListener("wheel", onWheel);
|
return () => el.removeEventListener("wheel", onWheel);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Track whether the fullscreen element is ours — the player iframe (see fullscreenTarget) or,
|
// Track the browser's fullscreen state. WE never request it any more (F maximises via CSS), so
|
||||||
// before the player exists, the stage. Covers F, our button, YouTube's own button and the
|
// this is YouTube's own fullscreen — entered from its control bar, left by its button or Esc.
|
||||||
// browser's Esc exit alike, since all of them land on one of those two elements.
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onChange = () => {
|
const onChange = () => {
|
||||||
const fsEl = document.fullscreenElement;
|
const fsEl = document.fullscreenElement;
|
||||||
@@ -567,6 +566,12 @@ export default function PlayerModal({
|
|||||||
const ours = !!fsEl && (fsEl === stageRef.current || fsEl === frame);
|
const ours = !!fsEl && (fsEl === stageRef.current || fsEl === frame);
|
||||||
isFullscreenRef.current = ours; // read by the once-bound keydown handler
|
isFullscreenRef.current = ours; // read by the once-bound keydown handler
|
||||||
setIsFullscreen(ours); // drives the overlay's pointer-events
|
setIsFullscreen(ours); // drives the overlay's pointer-events
|
||||||
|
// LEAVING fullscreen is where the user got stranded: to reach YouTube's fullscreen button
|
||||||
|
// they had to click INTO the player, which moves keyboard focus into the cross-origin iframe
|
||||||
|
// — and it stays there afterwards. Our window-level shortcuts then never fire (F went to
|
||||||
|
// YouTube instead, giving a second, control-less fullscreen), so the maximised view had no
|
||||||
|
// way out. Taking focus back here restores F/Space/arrows the moment fullscreen ends.
|
||||||
|
if (!fsEl) focusModal();
|
||||||
};
|
};
|
||||||
document.addEventListener("fullscreenchange", onChange);
|
document.addEventListener("fullscreenchange", onChange);
|
||||||
return () => document.removeEventListener("fullscreenchange", onChange);
|
return () => document.removeEventListener("fullscreenchange", onChange);
|
||||||
|
|||||||
Reference in New Issue
Block a user