feat: color picker, unified UI styling, filament mismatch detection, Spoolman slot assignment
All checks were successful
Nightly Build / build (push) Successful in 4m27s

- Slot color editor: Pickr HSV color picker (offline, served from lib/),
  recent swatches (up to 16, localStorage), copy color from other slot
- Unified axes control panel: XY+Z merged, shared step size + custom mm input
- Language selector moved from header to Settings → Appearance
- Filament mismatch detection blocks Upload-and-Print on material mismatch,
  slot mapper opens automatically
- Spoolman spool-per-slot assignment in AMS status tab and Filaments settings
- Fix: Spoolman sync rate label — 0=end of print, not disabled (Issue #76)
- Fix: lib/ assets served by bridge static handler for offline use
- UI: global unified select + input styling, set-row labels match modal-field
This commit is contained in:
2026-06-30 11:13:34 +02:00
parent 771599be0c
commit 74fc2ddab0
13 changed files with 209 additions and 23 deletions

View File

@ -142,6 +142,11 @@ _KX_UI_ASSETS: dict[str, str] = {
"style.css": "text/css",
"app.js": "application/javascript",
}
# Dateien aus lib/ werden anhand der Extension ausgeliefert (kein Whitelist-Eintrag nötig)
_KX_UI_LIB_TYPES: dict[str, str] = {
".js": "application/javascript",
".css": "text/css",
}
_KX_UI_TRANSLATION_RE = re.compile(r"^translations/([a-z]{2}(?:-[a-z]{2})?)\.json$")
# Ring-Buffer für Browser-Log-Stream (letzte 200 Einträge)
@ -3576,6 +3581,12 @@ class KobraXBridge:
if ctype is not None:
path = os.path.join(_WEB_BASE, "web", "themes", self._ui_theme, name)
elif name.startswith("lib/"):
ext = os.path.splitext(name)[1].lower()
ctype = _KX_UI_LIB_TYPES.get(ext)
if not ctype:
raise web.HTTPNotFound()
path = os.path.join(_WEB_BASE, "web", "themes", self._ui_theme, name)
else:
m = _KX_UI_TRANSLATION_RE.match(name)
if not m: