/** * When the player's control bar may auto-hide. * * TRACES: UR-003, UR-066 | DR-189 | UT-188 * * The bar's hide timer used to be armed from exactly one place — the container's * `onmousemove`. A touchscreen never fires `mousemove`, so on Android the timer * was never set and the bar stayed on screen for the whole film. It went * unnoticed while the video itself was invisible: with nothing to obscure, a * permanent control bar looks like the UI, not like a defect. * * The decision is separated from the timer so it can be tested without a clock * or a DOM: it is a rule about state, and the parts that were wrong here were * the conditions, not the `setTimeout`. */ /** Everything that decides whether the bar may disappear right now. */ export interface ControlsHideContext { /** Hiding controls over a paused player strands the user with no affordance. */ isPlaying: boolean; /** A seek in flight is exactly when the position readout is worth watching. */ isSeeking: boolean; /** True while any of the track / subtitle / quality menus is open. */ menuOpen: boolean; } /** * Whether the control bar may hide now. * * Requires playback to be running: a paused player keeps its controls, which is * both the convention and the only way back for a user who paused by tapping. * A menu open over the bar pins it too — the menus are anchored to the bar, so * hiding it would take the open menu with it, mid-interaction. */ export function shouldHideControls(ctx: ControlsHideContext): boolean { if (!ctx.isPlaying) return false; if (ctx.isSeeking) return false; if (ctx.menuOpen) return false; return true; }