Fixed qr-scanner (needs to be deployed (https))
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import { Controller } from "@hotwired/stimulus";
|
import { Controller } from "@hotwired/stimulus";
|
||||||
import QrScanner from "qr-scanner"; // Importiert das saubere, einzelne Modul
|
|
||||||
|
|
||||||
export default class extends Controller {
|
export default class extends Controller {
|
||||||
static targets = ["input", "preview", "modal"];
|
static targets = ["input", "preview", "modal"];
|
||||||
@@ -8,50 +7,37 @@ export default class extends Controller {
|
|||||||
this.qrScanner = null;
|
this.qrScanner = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Öffnet das Modal und startet den Kamera-Stream
|
|
||||||
startCamera(event) {
|
startCamera(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
// 1. Modal anzeigen
|
|
||||||
this.modalTarget.classList.remove("hidden");
|
this.modalTarget.classList.remove("hidden");
|
||||||
|
|
||||||
// 2. Ein HTML5 <video> Element holen oder erstellen (wird für den Stream gebraucht)
|
const videoElement = this.previewTarget;
|
||||||
const videoElement = this.previewTarget.querySelector("video") || this.createVideoElement();
|
|
||||||
|
|
||||||
// 3. Scanner initialisieren
|
// Greift fehlerfrei auf die Klasse aus dem public-Ordner zu
|
||||||
this.qrScanner = new QrScanner(
|
this.qrScanner = new window.QrScanner(
|
||||||
videoElement,
|
videoElement,
|
||||||
(result) => {
|
(result) => { this.handleScanSuccess(result.data); },
|
||||||
// SUCCESS: Code erkannt!
|
|
||||||
this.handleScanSuccess(result.data);
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
onDecodeError: (error) => { /* Loop-Fehler während der Suche ignorieren */ },
|
onDecodeError: (error) => { /* Fehler ignorieren */ },
|
||||||
highlightScanRegion: true, // Zeichnet einen schicken gelben/grünen Scan-Rahmen ins Bild
|
highlightScanRegion: true,
|
||||||
highlightCodeOutline: true,
|
highlightCodeOutline: true,
|
||||||
maxScansPerSecond: 10
|
maxScansPerSecond: 10
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 4. Kamera starten
|
|
||||||
this.qrScanner.start().catch((err) => {
|
this.qrScanner.start().catch((err) => {
|
||||||
alert("Kamera-Zugriff verweigert, blockiert oder unverschlüsselte Verbindung!");
|
|
||||||
console.error("Kamera-Fehler:", err);
|
console.error("Kamera-Fehler:", err);
|
||||||
|
alert("Kamera konnte nicht gestartet werden.");
|
||||||
this.modalTarget.classList.add("hidden");
|
this.modalTarget.classList.add("hidden");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verarbeitet die gescannte ID und startet das search-form
|
|
||||||
handleScanSuccess(decodedText) {
|
handleScanSuccess(decodedText) {
|
||||||
this.inputTarget.value = decodedText;
|
this.inputTarget.value = decodedText;
|
||||||
|
|
||||||
// Simuliert das Tippen für deinen Live-Filter
|
|
||||||
this.inputTarget.dispatchEvent(new Event("input", { bubbles: true }));
|
this.inputTarget.dispatchEvent(new Event("input", { bubbles: true }));
|
||||||
|
|
||||||
this.stopCamera();
|
this.stopCamera();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Beendet den Stream sauber und schließt das Fenster
|
|
||||||
stopCamera() {
|
stopCamera() {
|
||||||
if (this.qrScanner) {
|
if (this.qrScanner) {
|
||||||
this.qrScanner.stop();
|
this.qrScanner.stop();
|
||||||
@@ -61,17 +47,6 @@ export default class extends Controller {
|
|||||||
this.modalTarget.classList.add("hidden");
|
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() {
|
disconnect() {
|
||||||
this.stopCamera();
|
this.stopCamera();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,9 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- DAS VORSCHAUFENSTER FÜR DIE KAMERA IN DEINER _search_bar.html.erb -->
|
<!-- DAS VORSCHAUFENSTER FÜR DIE KAMERA IN DEINER _search_bar.html.erb -->
|
||||||
<div data-scanner-target="preview" class="w-full aspect-square rounded-xl overflow-hidden border border-gray-200 bg-gray-50 flex items-center justify-center">
|
<!-- KORREKTUR: Das Video-Tag steht jetzt fest im HTML und dient direkt als Target -->
|
||||||
<!-- Das <video>-Tag wird von Stimulus hier automatisch injiziert -->
|
<div class="w-full aspect-square rounded-xl overflow-hidden border border-gray-200 bg-black flex items-center justify-center">
|
||||||
|
<video data-scanner-target="preview" class="w-full h-full object-cover rounded-xl" playsinline muted></video>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xs text-gray-500 text-center">Halte den QR-Code des Geräts ruhig in den Scan-Rahmen.</p>
|
<p class="text-xs text-gray-500 text-center">Halte den QR-Code des Geräts ruhig in den Scan-Rahmen.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
||||||
<link rel="apple-touch-icon" href="/icon.png">
|
<link rel="apple-touch-icon" href="/icon.png">
|
||||||
|
|
||||||
|
<!-- Lädt die lokale Legacy-Datei direkt aus dem public-Ordner ohne Rails-Asset-Pipeline -->
|
||||||
|
<script src="/qr-scanner.js" data-turbo-track="reload"></script>
|
||||||
|
|
||||||
<%# Includes all stylesheet files in app/assets/stylesheets %>
|
<%# Includes all stylesheet files in app/assets/stylesheets %>
|
||||||
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
|
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
|
||||||
<%= javascript_importmap_tags %>
|
<%= javascript_importmap_tags %>
|
||||||
|
|||||||
@@ -5,4 +5,3 @@ pin "@hotwired/turbo-rails", to: "turbo.min.js"
|
|||||||
pin "@hotwired/stimulus", to: "stimulus.min.js"
|
pin "@hotwired/stimulus", to: "stimulus.min.js"
|
||||||
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
|
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
|
||||||
pin_all_from "app/javascript/controllers", under: "controllers"
|
pin_all_from "app/javascript/controllers", under: "controllers"
|
||||||
pin "qr-scanner" # @1.4.2
|
|
||||||
|
|||||||
57
public/qr-scanner.js
Normal file
57
public/qr-scanner.js
Normal file
File diff suppressed because one or more lines are too long
4
vendor/javascript/qr-scanner.js
vendored
4
vendor/javascript/qr-scanner.js
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user