Fix: Allow scanner to attempt camera access without HTTPS

In test environments without HTTPS, the camera may still work
depending on browser settings. Now shows warning instead of
blocking completely.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-02-17 11:22:23 +01:00
parent 74b452b82e
commit 6bb3927ca3

View file

@ -27,6 +27,7 @@
let currentProduct = null; let currentProduct = null;
let selectedSupplier = null; let selectedSupplier = null;
let allSuppliers = []; let allSuppliers = [];
let quaggaInitialized = false;
// DOM Elements (will be set on init) // DOM Elements (will be set on init)
let elements = {}; let elements = {};
@ -48,10 +49,54 @@
return; return;
} }
// Check for camera support
checkCameraSupport();
bindEvents(); bindEvents();
loadAllSuppliers(); loadAllSuppliers();
} }
// Check camera support and show appropriate messages
function checkCameraSupport() {
// Check HTTPS (required for camera access except on localhost)
// Note: In test environments without HTTPS, camera may not work but we still allow trying
const isSecure = location.protocol === 'https:' || location.hostname === 'localhost' || location.hostname === '127.0.0.1';
if (!isSecure) {
// Show warning but don't disable - some browsers/configs may still work
console.warn('HandyBarcodeScanner: HTTPS empfohlen für Kamerazugriff');
}
// Check if getUserMedia is supported
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
showCameraError('Kamera wird von diesem Browser nicht unterstützt');
elements.startBtn.disabled = true;
elements.startBtn.classList.add('butActionRefused');
elements.startBtn.classList.remove('butAction');
return;
}
// Check if Quagga is loaded
if (typeof Quagga === 'undefined') {
showCameraError('Scanner-Bibliothek nicht geladen');
elements.startBtn.disabled = true;
elements.startBtn.classList.add('butActionRefused');
elements.startBtn.classList.remove('butAction');
return;
}
// All checks passed - enable button
elements.startBtn.disabled = false;
}
function showCameraError(message) {
const errorDiv = document.createElement('div');
errorDiv.className = 'error-message';
errorDiv.style.cssText = 'position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #fff; text-align: center; padding: 20px;';
errorDiv.innerHTML = '<div style="font-size: 40px; margin-bottom: 10px;">⚠️</div><div>' + message + '</div>';
elements.videoContainer.appendChild(errorDiv);
}
// Event Bindings // Event Bindings
function bindEvents() { function bindEvents() {
elements.startBtn.addEventListener('click', startScanner); elements.startBtn.addEventListener('click', startScanner);
@ -73,6 +118,7 @@
// Scanner Functions // Scanner Functions
function startScanner() { function startScanner() {
if (isScanning) return; if (isScanning) return;
if (elements.startBtn.disabled) return;
// Check if Quagga is available // Check if Quagga is available
if (typeof Quagga === 'undefined') { if (typeof Quagga === 'undefined') {
@ -80,6 +126,10 @@
return; return;
} }
// Disable button while initializing
elements.startBtn.disabled = true;
elements.startBtn.textContent = 'Initialisiere...';
Quagga.init({ Quagga.init({
inputStream: { inputStream: {
name: "Live", name: "Live",
@ -87,8 +137,8 @@
target: elements.videoContainer, target: elements.videoContainer,
constraints: { constraints: {
facingMode: "environment", facingMode: "environment",
width: { ideal: 1280 }, width: { min: 640, ideal: 1280, max: 1920 },
height: { ideal: 720 } height: { min: 480, ideal: 720, max: 1080 }
} }
}, },
decoder: { decoder: {
@ -104,25 +154,48 @@
}, function(err) { }, function(err) {
if (err) { if (err) {
console.error('Quagga init error:', err); console.error('Quagga init error:', err);
showToast(CONFIG.lang.cameraError, 'error'); elements.startBtn.disabled = false;
elements.startBtn.textContent = CONFIG.lang.startScan || 'Scan starten';
// Show specific error message
let errorMsg = CONFIG.lang.cameraError || 'Kamerafehler';
if (err.name === 'NotAllowedError') {
errorMsg = 'Kamerazugriff verweigert. Bitte Berechtigung erteilen.';
} else if (err.name === 'NotFoundError') {
errorMsg = 'Keine Kamera gefunden.';
} else if (err.name === 'NotReadableError') {
errorMsg = 'Kamera wird bereits verwendet.';
}
showToast(errorMsg, 'error');
return; return;
} }
// Success - start scanning
Quagga.start(); Quagga.start();
quaggaInitialized = true;
isScanning = true; isScanning = true;
elements.startBtn.classList.add('hidden'); elements.startBtn.classList.add('hidden');
elements.stopBtn.classList.remove('hidden'); elements.stopBtn.classList.remove('hidden');
elements.videoContainer.classList.add('scanning'); elements.videoContainer.classList.add('scanning');
});
// Register detection handler
Quagga.onDetected(onBarcodeDetected); Quagga.onDetected(onBarcodeDetected);
});
} }
function stopScanner() { function stopScanner() {
if (!isScanning) return; if (!isScanning) return;
if (quaggaInitialized) {
Quagga.offDetected(onBarcodeDetected);
Quagga.stop(); Quagga.stop();
}
isScanning = false; isScanning = false;
quaggaInitialized = false;
elements.startBtn.classList.remove('hidden'); elements.startBtn.classList.remove('hidden');
elements.startBtn.disabled = false;
elements.startBtn.textContent = CONFIG.lang.startScan || 'Scan starten';
elements.stopBtn.classList.add('hidden'); elements.stopBtn.classList.add('hidden');
elements.videoContainer.classList.remove('scanning'); elements.videoContainer.classList.remove('scanning');
} }