/** Parent mode: reachable only via `?parentMode=1`, never from the child-facing UI. * * This hides the settings, it does not protect them - there is no login, and the * endpoints behind it are as open as the rest of the API. That matches the device's * threat model (a box on a home network) and is stated in the README rather than * implied. */ import { useEffect, useState } from "react"; import { api } from "../api/client"; import type { Settings } from "../api/types"; const FIELDS: Array<[keyof Settings, string, string, number, number, number]> = [ ["min_volume", "Minimale Lautstärke", "Untergrenze am Gerät (0-200)", 0, 200, 1], ["max_volume", "Maximale Lautstärke", "Was 100 % in der Kinder-Ansicht bedeutet", 0, 200, 1], ["initial_volume", "Start-Lautstärke", "Beim Einschalten", 0, 200, 1], ["volume_increment", "Schritt am Drehknopf", "Pro Rasterung", 1, 100, 1], ["button_leds_brightness", "Tastenbeleuchtung", "0 bis 1", 0, 1, 0.05], ]; export function ParentPanel({ onClose }: { onClose: () => void }) { const [settings, setSettings] = useState(null); const [status, setStatus] = useState(null); const [busy, setBusy] = useState(false); useEffect(() => { api .settings() .then(setSettings) .catch((cause: unknown) => setStatus(String(cause))); }, []); const save = async () => { if (!settings) return; setBusy(true); setStatus(null); try { setSettings(await api.saveSettings(settings)); setStatus("Gespeichert."); } catch { // The backend rejects an inverted range or an out-of-band start volume. setStatus("Nicht gespeichert — bitte die Werte prüfen (min ≤ Start ≤ max)."); } finally { setBusy(false); } }; const rescan = async () => { setStatus("Bibliothek wird eingelesen …"); await api.refreshLibrary(); setStatus("Einlesen gestartet. Neue Titel erscheinen gleich von selbst."); }; return (
🔧 Eltern-Einstellungen
{settings === null ? (
Wird geladen …
) : (
{FIELDS.map(([key, label, hint, min, max, step]) => ( ))}
Speichern schreibt in die config.yml auf dem Gerät. Die neue Obergrenze gilt sofort, ohne Neustart.
)} {status && (
{status}
)}
); }