// Native-video compositing state. // // TRACES: UR-003, UR-004 | DR-150, DR-152 // // Two separate concerns live here, deliberately: // // 1. `experimentalNativeVideo` — the user-facing opt-in flag. Rust already // decides *which backend this platform has* (`useHtml5Element` from // `player_play_item`); this flag only *suppresses* that decision so a // half-working spike cannot ship as a regression. It never turns native on // where Rust says HTML5. // // 2. `nativeVideoActive` — whether a native surface is on screen right now. // Setting it toggles `data-native-video` on , which is what the CSS in // app.css keys off to clear the app's opaque backgrounds so the SurfaceView // behind the WebView is visible. It is deliberately NOT derived from the // flag: the backgrounds must come back the moment the player unmounts. // // Frontend-only preference, stored in localStorage per the `jellytau-view-mode` // precedent in library.ts — no Rust settings command backs this. import { writable } from "svelte/store"; const STORAGE_KEY = "jellytau-experimental-native-video"; /** The attribute app.css keys its transparency rules off. */ const NATIVE_VIDEO_ATTR = "data-native-video"; /** * Whether the native path is on, defaulting to **on** when the user has never * chosen. * * This default has moved three times, so the history is the documentation: * * - **off** while the path was a spike (DR-150). * - **on** for picture-in-picture (DR-161), which shipped as *audio with no * picture* — ExoPlayer decoded correctly into a live SurfaceView while the * page stayed opaque over it. * - **off** again (DR-172), which named the compositing as the suspect but did * not find it. * - **on** now, because the four defects behind that symptom were found and * each is fixed and verified on a device: the app shell painted over the * surface through a CSS rule targeting an attribute nothing set (DR-185); the * poster card had no way to lift on a path with no `