/** * Immersive (system-bar-free) full-screen video, Android only. * * TRACES: UR-066 | DR-157 * * `requestFullscreen()` is the only fullscreen control the web layer has, and in * an Android WebView it does not touch the Activity window — it expands the * element inside a viewport that already spans the whole screen (MainActivity * calls `enableEdgeToEdge()`, and SDK 36 makes that mandatory). So the status and * navigation bars stayed painted over full-screen video, and "fullscreen" * changed nothing visible. * * Hiding them needs `WindowInsetsControllerCompat` on the Activity, so it goes * through the `AndroidImmersive` @JavascriptInterface installed by MainActivity. * Elsewhere (desktop, the Linux WebKitGTK webview) the real `requestFullscreen()` * already does the right thing and these calls are no-ops. */ interface AndroidImmersiveBridge { enter(): void; exit(): void; isSupported(): boolean; } declare global { interface Window { AndroidImmersive?: AndroidImmersiveBridge; } } function bridge(): AndroidImmersiveBridge | undefined { if (typeof window === "undefined") return undefined; return window.AndroidImmersive; } /** Whether native immersive mode exists on this platform. */ export function isImmersiveSupported(): boolean { try { return bridge()?.isSupported() ?? false; } catch (err) { console.warn("[Immersive] isSupported check failed:", err); return false; } } /** Hide the system bars. No-op where unsupported. */ export function enterImmersive(): void { try { bridge()?.enter(); } catch (err) { console.error("[Immersive] Failed to hide the system bars:", err); } } /** * Restore the system bars. No-op where unsupported. * * Call this on leaving fullscreen *and* on player teardown — the bars belong to * the Activity, not the player, so a player destroyed while immersive would * leave every screen behind it without a status or navigation bar. */ export function exitImmersive(): void { try { bridge()?.exit(); } catch (err) { console.error("[Immersive] Failed to restore the system bars:", err); } }