From 7ebba4e755e848e294456e1667ae79eaa07b69d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dieter=20Schl=C3=BCter?= Date: Thu, 18 Jun 2026 10:20:24 +0200 Subject: [PATCH] feat(web): Tailwind-Redesign-UI + Doku (Nachtrag zu 3470c0e) Eigentliche UI-Dateien: neues Tailwind-Layout (index.html), Theme-Umschalter + Bubble-Stile + Mic-Status (app.js); README-Abschnitt aktualisiert. Co-Authored-By: Claude Opus 4.8 --- README.md | 8 +++-- app/web/app.js | 35 +++++++++++++++--- app/web/index.html | 88 +++++++++++++++++++++++++++++----------------- 3 files changed, 91 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index bff10b8..9ec3f55 100644 --- a/README.md +++ b/README.md @@ -392,9 +392,11 @@ PORT=8003 docker compose up # mit Docker ## Web-UI & Remote-Zugang -Das Gateway liefert unter `/` eine minimale **Web-Oberfläche** aus (`app/web/`, vanilla, -kein Build): Text-Eingabe + **Mikrofon-Button** (Aufnahme im Browser → `/ws/voice` → -Antwort wird vorgelesen) und links ein Menü mit Identität/Logout/Admin. +Das Gateway liefert unter `/` eine **Web-Oberfläche** aus (`app/web/`, Tailwind via CDN, +kein Build): responsives, modernes Layout mit **Tag-/Nacht-Umschalter** (folgt automatisch +dem System), Text-Eingabe + **Mikrofon-Button** (Aufnahme im Browser → `/ws/voice` → Antwort +wird vorgelesen), **Stimmen-Auswahl** (piper/chatterbox/cloud) sowie Identität/Logout und +(für Admins) eine Nutzerliste. ### Zugriff aus dem lokalen Netz (LAN) diff --git a/app/web/app.js b/app/web/app.js index 8416444..1f25420 100644 --- a/app/web/app.js +++ b/app/web/app.js @@ -39,7 +39,7 @@ function loadMe() { logout.classList.remove("hidden"); } if (me.is_admin) { - $("#admin").classList.remove("hidden"); + $("#admin-toggle").classList.remove("hidden"); } return me; } catch (e) { @@ -83,9 +83,16 @@ function scrollToBottom() { requestAnimationFrame(() => { messagesEl.scrollTop = messagesEl.scrollHeight; }); } +const BUBBLE = { + user: "ml-auto max-w-[80%] rounded-2xl rounded-br-sm bg-blue-600 px-4 py-2 text-white whitespace-pre-wrap", + assistant: "mr-auto max-w-[80%] rounded-2xl rounded-bl-sm border border-slate-200 bg-white px-4 py-2 whitespace-pre-wrap dark:border-slate-700 dark:bg-slate-800", + system: "mx-auto max-w-[90%] rounded-lg bg-amber-100 px-3 py-1.5 text-xs text-amber-800 dark:bg-amber-900/40 dark:text-amber-200", + emergency: "mx-auto max-w-[90%] rounded-lg bg-red-100 px-3 py-1.5 text-sm font-semibold text-red-800 dark:bg-red-900/40 dark:text-red-200", +}; + function addMessage(role, text) { const div = document.createElement("div"); - div.className = "msg " + role; + div.className = BUBBLE[role] || BUBBLE.assistant; div.textContent = text; messagesEl.appendChild(div); scrollToBottom(); @@ -211,13 +218,15 @@ async function startRecording() { sendVoice(bytes); }; mediaRecorder.start(); - micBtn.classList.add("recording"); + micBtn.classList.remove("bg-emerald-600"); + micBtn.classList.add("bg-red-600", "animate-pulse"); statusEl.textContent = "Aufnahme … (zum Stoppen erneut tippen)"; } function stopRecording() { if (mediaRecorder && mediaRecorder.state !== "inactive") mediaRecorder.stop(); - micBtn.classList.remove("recording"); + micBtn.classList.remove("bg-red-600", "animate-pulse"); + micBtn.classList.add("bg-emerald-600"); } async function sendVoice(bytes) { @@ -239,6 +248,24 @@ micBtn.addEventListener("click", () => { }); $("#reload-users").addEventListener("click", loadUsers); +$("#admin-toggle").addEventListener("click", () => $("#admin").classList.toggle("hidden")); + +// Tag/Nacht: Umschalter (manuell) + automatisch dem System folgen, solange nichts gewählt. +const themeBtn = $("#theme-toggle"); +const setThemeIcon = () => + (themeBtn.textContent = document.documentElement.classList.contains("dark") ? "☀️" : "🌙"); +themeBtn.addEventListener("click", () => { + const dark = document.documentElement.classList.toggle("dark"); + localStorage.setItem("theme", dark ? "dark" : "light"); + setThemeIcon(); +}); +matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => { + if (!localStorage.getItem("theme")) { + document.documentElement.classList.toggle("dark", e.matches); + setThemeIcon(); + } +}); +setThemeIcon(); // Wenn die Bildschirmtastatur die sichtbare Hoehe aendert (iOS), unten bleiben. if (window.visualViewport) { diff --git a/app/web/index.html b/app/web/index.html index 316c7eb..e5c31a8 100644 --- a/app/web/index.html +++ b/app/web/index.html @@ -1,43 +1,65 @@ - + - + Voice Assistant - + + + - -
- + -
-
+
+

Voice Assistant

+ + + +
-
- - - -
-
-
+
+ lade … +
- + + + +
+ +
+
+ + + +
+
+
+ +