1// Shared camera stream across page navigations. 2// Strategy: browser can't truly persist a MediaStream across hard navigations, 3// but we persist the USER'S INTENT in sessionStorage and auto-reacquire on 4// page load. Within a single page, the stream is cached on window so multiple 5// modules (s.js, index.js) share one. 6 7const KEY = "18.cam.on"; 8const WINDOW_KEY = "__1800_cam_stream__"; 9 10export function wantsCamera() { 11 return sessionStorage.getItem(KEY) === "1"; 12} 13export function setWantsCamera(on) { 14 if (on) sessionStorage.setItem(KEY, "1"); 15 else sessionStorage.removeItem(KEY); 16} 17export function sharedStream() { 18 return window[WINDOW_KEY] || null; 19} 20 21export async function acquireCamera(constraints = {}) { 22 let s = sharedStream(); 23 if (s && s.active) { setWantsCamera(true); return s; } 24 s = await navigator.mediaDevices.getUserMedia({ 25 video: constraints.video ?? { width: 320, height: 240, frameRate: 15 }, 26 audio: constraints.audio ?? { echoCancellation: true, noiseSuppression: true }, 27 }); 28 window[WINDOW_KEY] = s; 29 setWantsCamera(true); 30 return s; 31} 32 33export function releaseCamera() { 34 const s = sharedStream(); 35 if (s) { 36 try { s.getTracks().forEach(t => t.stop()); } catch {} 37 window[WINDOW_KEY] = null; 38 } 39 setWantsCamera(false); 40}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.