feat(3b): Einstellungen vereinfacht — wichtige sichtbar, „Erweitert" einklappbar

Statt 7 technischer Gruppen jetzt 3: „Sprache & Stimme" und
„Antwortverhalten" (die alltagsrelevanten Schalter) immer sichtbar;
alle technischen Regler (STT/LLM-Provider, OpenRouter-Modelle, Temperatur,
top_p, Tokens, Systemprompt, Normalisierung …) unter „Erweitert", das
standardmäßig eingeklappt ist. app.js v=47.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-06-25 04:54:56 +02:00
commit d296bad9f2
2 changed files with 28 additions and 13 deletions

View file

@ -1724,13 +1724,12 @@ const FIELD_META = {
};
const FIELD_GROUPS = [
{ label: "Provider & Sprache", keys: ["default_stt_provider","default_llm_provider","default_tts_provider","default_language"] },
{ label: "OpenRouter-Modelle & Stimmen", keys: ["openrouter_llm_model","openrouter_tts_model","openrouter_tts_voice"] },
{ label: "Piper TTS", keys: ["piper_voice"] },
{ label: "Lokales LLM", keys: ["local_llm_system_prompt","local_llm_temperature","local_llm_top_p","local_llm_max_tokens"] },
{ label: "TTS-Verarbeitung", keys: ["tts_normalize_level","audio_stream_default"] },
{ label: "Gedächtnis", keys: ["memory_extraction_enabled","memory_extraction_every_n_turns"] },
{ label: "Limits", keys: ["daily_request_limit"] },
{ label: "Sprache & Stimme", keys: ["default_language","default_tts_provider","openrouter_tts_voice","piper_voice"] },
{ label: "Antwortverhalten", keys: ["memory_extraction_enabled","audio_stream_default","daily_request_limit"] },
{ label: "Erweitert", advanced: true, keys: [
"default_stt_provider","default_llm_provider","openrouter_llm_model","openrouter_tts_model",
"tts_normalize_level","local_llm_system_prompt","local_llm_temperature","local_llm_top_p",
"local_llm_max_tokens","memory_extraction_every_n_turns" ] },
];
let _settingsData = [];
@ -1748,15 +1747,31 @@ async function loadSettings() {
if (!items.length) return;
const section = document.createElement("div");
section.className = "bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 overflow-hidden";
const header = document.createElement("div");
header.className = "px-4 py-2.5 border-b border-slate-100 dark:border-slate-700 bg-slate-50/80 dark:bg-slate-800/60";
header.innerHTML = `<h4 class="text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide">${escHtml(group.label)}</h4>`;
section.appendChild(header);
const body = document.createElement("div");
items.forEach((item, idx) => {
const row = buildSettingRow(item);
if (idx > 0) row.classList.add("border-t", "border-slate-100", "dark:border-slate-700/60");
section.appendChild(row);
body.appendChild(row);
});
const header = document.createElement(group.advanced ? "button" : "div");
header.className = "w-full text-left px-4 py-2.5 border-b border-slate-100 dark:border-slate-700 bg-slate-50/80 dark:bg-slate-800/60 flex items-center gap-2";
if (group.advanced) {
body.classList.add("hidden");
header.innerHTML = `<span class="adv-arrow text-slate-400">▶</span>` +
`<h4 class="text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide flex-1">${escHtml(group.label)}</h4>` +
`<span class="text-xs text-slate-400">technische Optionen</span>`;
header.addEventListener("click", () => {
const open = !body.classList.contains("hidden");
body.classList.toggle("hidden", open);
header.querySelector(".adv-arrow").textContent = open ? "▶" : "▼";
});
} else {
header.innerHTML = `<h4 class="text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide">${escHtml(group.label)}</h4>`;
}
section.appendChild(header);
section.appendChild(body);
container.appendChild(section);
});
}

View file

@ -365,6 +365,6 @@
<div id="status" class="w-full max-w-3xl mx-auto mt-1 min-h-[1rem] text-xs text-slate-500 dark:text-slate-400"></div>
</footer>
<script src="/app.js?v=46"></script>
<script src="/app.js?v=47"></script>
</body>
</html>