Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | 2x 1932x 245x 1932x 359x 359x 136x 1x 1932x 245x 5x | // SPDX-License-Identifier: GPL-3.0-only
// Copyright (C) 2026 Max Boksem. See NOTICE for additional terms under GPLv3 section 7.
import { useEffect, type RefObject } from "react";
import { hasOpenFocusTrap, onFocusLostOnClose } from "./useFocusTrap";
/**
* Gives the player keyboard focus when it opens and again each time a stream
* loads, so its keys work without a click first. Focus already inside the
* player, such as on the resume prompt, stays put. So does focus on a confirm
* opened from the controls, which renders outside the player. When the last
* dialog closes and can't hand focus back, the player takes focus too. That
* happens when the element that had focus as the dialog opened is gone or
* can't take focus, as when the next episode replaced the button that opened
* it, or when nothing had focus.
*/
export const usePlayerFocus = (
containerRef: RefObject<HTMLElement | null>,
currentUrl: string | null
): void => {
useEffect(() => {
containerRef.current?.focus();
}, [containerRef]);
useEffect(() => {
const container = containerRef.current;
if (!currentUrl || !container) return;
if (container.contains(document.activeElement) || hasOpenFocusTrap()) return;
container.focus();
}, [containerRef, currentUrl]);
useEffect(
() =>
onFocusLostOnClose(() => {
containerRef.current?.focus();
}),
[containerRef]
);
};
|