Pre-warm camera stream on page load if permission already granted

Uses Permissions API (non-prompting) to check camera state on load.
If state === 'granted', silently starts the stream so Scan Label opens
instantly with no browser prompt on subsequent page visits. Falls back
gracefully when Permissions API is unavailable or permission is 'prompt'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-03 18:48:37 -04:00
parent 4b65572f6f
commit 97cf6dcbf0
@@ -56,6 +56,10 @@
if (shutterBtn) shutterBtn.addEventListener('click', captureFrame);
window.addEventListener('beforeunload', releaseCamera);
// If the user has already granted camera permission, silently pre-warm the stream
// so the next Scan Label click opens instantly without any browser prompt.
preWarmCamera();
// ── Open / close ──────────────────────────────────────────────────────
async function openScanner() {
@@ -184,6 +188,24 @@
rafId = requestAnimationFrame(tick);
}
// ── Camera pre-warm ───────────────────────────────────────────────────
// Check camera permission state without prompting. If already granted, start the stream
// silently on page load so Scan Label opens instantly with no browser prompt on this visit.
// The idle timer ensures the camera releases if the user never actually scans anything.
async function preWarmCamera() {
try {
if (!navigator.permissions) return;
const perm = await navigator.permissions.query({ name: 'camera' });
if (perm.state !== 'granted') return;
stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: 'environment', width: { ideal: 1280 }, height: { ideal: 720 } }
});
// Start idle timer — release if user never opens the scanner
idleTimer = setTimeout(releaseCamera, IDLE_RELEASE_MS);
} catch { /* permission denied or getUserMedia failed — ignore */ }
}
function loadJsQR() {
return new Promise((resolve, reject) => {
if (window.jsQR) { resolve(); return; }