Fixed qr-scanner (needs to be deployed (https))
Some checks failed
CI / scan_ruby (push) Has been cancelled
CI / scan_js (push) Has been cancelled
CI / lint (push) Has been cancelled
CI / test (push) Has been cancelled
CI / system-test (push) Has been cancelled

This commit is contained in:
2026-05-27 01:56:45 +02:00
parent b66f59eedc
commit a0e7272b6f
6 changed files with 70 additions and 39 deletions

View File

@@ -1,5 +1,4 @@
import { Controller } from "@hotwired/stimulus";
import QrScanner from "qr-scanner"; // Importiert das saubere, einzelne Modul
export default class extends Controller {
static targets = ["input", "preview", "modal"];
@@ -8,50 +7,37 @@ export default class extends Controller {
this.qrScanner = null;
}
// Öffnet das Modal und startet den Kamera-Stream
startCamera(event) {
event.preventDefault();
// 1. Modal anzeigen
this.modalTarget.classList.remove("hidden");
// 2. Ein HTML5 <video> Element holen oder erstellen (wird für den Stream gebraucht)
const videoElement = this.previewTarget.querySelector("video") || this.createVideoElement();
const videoElement = this.previewTarget;
// 3. Scanner initialisieren
this.qrScanner = new QrScanner(
// Greift fehlerfrei auf die Klasse aus dem public-Ordner zu
this.qrScanner = new window.QrScanner(
videoElement,
(result) => {
// SUCCESS: Code erkannt!
this.handleScanSuccess(result.data);
},
(result) => { this.handleScanSuccess(result.data); },
{
onDecodeError: (error) => { /* Loop-Fehler während der Suche ignorieren */ },
highlightScanRegion: true, // Zeichnet einen schicken gelben/grünen Scan-Rahmen ins Bild
onDecodeError: (error) => { /* Fehler ignorieren */ },
highlightScanRegion: true,
highlightCodeOutline: true,
maxScansPerSecond: 10
}
);
// 4. Kamera starten
this.qrScanner.start().catch((err) => {
alert("Kamera-Zugriff verweigert, blockiert oder unverschlüsselte Verbindung!");
console.error("Kamera-Fehler:", err);
alert("Kamera konnte nicht gestartet werden.");
this.modalTarget.classList.add("hidden");
});
}
// Verarbeitet die gescannte ID und startet das search-form
handleScanSuccess(decodedText) {
this.inputTarget.value = decodedText;
// Simuliert das Tippen für deinen Live-Filter
this.inputTarget.dispatchEvent(new Event("input", { bubbles: true }));
this.stopCamera();
}
// Beendet den Stream sauber und schließt das Fenster
stopCamera() {
if (this.qrScanner) {
this.qrScanner.stop();
@@ -61,17 +47,6 @@ export default class extends Controller {
this.modalTarget.classList.add("hidden");
}
// Hilfsmethode: Erstellt das Video-Tag im Vorschau-Fenster
createVideoElement() {
const video = document.createElement("video");
video.autoplay = true;
video.muted = true;
video.playsInline = true;
video.className = "w-full h-full object-cover rounded-xl";
this.previewTarget.appendChild(video);
return video;
}
disconnect() {
this.stopCamera();
}