+
App-Onboarding (QR-Code)
+
+ RVS-Credentials als QR-Code — App scannt, keine manuelle Eingabe.
+ Enthaelt Host, Port, TLS-Flag und Token.
+
+
+
+
+ QR-Code wird geladen...
+
+
+
Achtung
+ Dieser QR enthaelt den RVS-Token im Klartext — zeige ihn niemandem,
+ speichere keine Screenshots davon in unsicheren Cloud-Diensten.
+
+
+
+
+
+
Highlight-Trigger
@@ -1441,6 +1465,48 @@
send({ action: 'send_voice_config', defaultVoice, highlightVoice, ttsEnabled, speedRamona, speedThorsten, ttsEngine, xttsVoice, whisperModel });
}
+ // ── App-Onboarding QR-Code ────────────────────
+ let qrLibReady = false;
+ function ensureQRLib() {
+ return new Promise((resolve) => {
+ if (qrLibReady || window.qrcode) { qrLibReady = true; resolve(); return; }
+ const s = document.createElement('script');
+ s.src = 'https://cdn.jsdelivr.net/npm/qrcode-generator@1.4.4/qrcode.min.js';
+ s.onload = () => { qrLibReady = true; resolve(); };
+ s.onerror = () => resolve(); // silent fail
+ document.head.appendChild(s);
+ });
+ }
+
+ async function loadOnboardingQR() {
+ const box = document.getElementById('onboarding-qr');
+ box.textContent = 'Lade...';
+ try {
+ await ensureQRLib();
+ if (!window.qrcode) throw new Error('QR-Library nicht geladen');
+ const resp = await fetch('/api/onboarding');
+ const cfg = await resp.json();
+ if (!cfg.rvsHost || !cfg.rvsToken) {
+ box.innerHTML = '
RVS nicht konfiguriert (ENV Variablen fehlen)
';
+ return;
+ }
+ // Format kompatibel mit android/src/components/QRScanner.tsx parseQRData()
+ const payload = JSON.stringify({
+ host: cfg.rvsHost,
+ port: Number(cfg.rvsPort) || 443,
+ tls: cfg.rvsTLS !== false,
+ token: cfg.rvsToken,
+ });
+ const qr = window.qrcode(0, 'M');
+ qr.addData(payload);
+ qr.make();
+ box.innerHTML = qr.createImgTag(6, 4);
+ box.querySelector('img').style.cssText = 'background:#fff;padding:8px;border-radius:4px;display:block;';
+ } catch (e) {
+ box.innerHTML = `
Fehler: ${e.message}
`;
+ }
+ }
+
// ── Highlight-Trigger ────────────────────────
function loadHighlightTriggers() {
send({ action: 'get_triggers' });
@@ -1921,10 +1987,11 @@
document.querySelectorAll('.main-nav-btn').forEach(b => {
if (b.textContent.trim().toLowerCase().includes(tab === 'main' ? 'main' : 'einstellung')) b.classList.add('active');
});
- // Einstellungen: Config + Trigger laden
+ // Einstellungen: Config + Trigger + QR laden
if (tab === 'settings') {
loadHighlightTriggers();
send({ action: 'get_voice_config' });
+ loadOnboardingQR();
}
}
diff --git a/diagnostic/server.js b/diagnostic/server.js
index c9ab61b..57ae6c8 100644
--- a/diagnostic/server.js
+++ b/diagnostic/server.js
@@ -1169,6 +1169,15 @@ const server = http.createServer((req, res) => {
} else if (req.url === "/api/session") {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ sessionKey: activeSessionKey }));
+ } else if (req.url === "/api/onboarding") {
+ // RVS-Credentials fuer QR-Code App-Onboarding
+ res.writeHead(200, { "Content-Type": "application/json" });
+ res.end(JSON.stringify({
+ rvsHost: RVS_HOST,
+ rvsPort: RVS_PORT,
+ rvsTLS: RVS_TLS === "true" || RVS_TLS === true,
+ rvsToken: RVS_TOKEN,
+ }));
} else if (req.url === "/api/cancel" && req.method === "POST") {
log("warn", "server", "HTTP /api/cancel — Cancel-Request (von Bridge)");
pendingMessageTime = 0;