feat: comprehensive React SPA replacing Jinja2 UI

- New dark UI with 7 tabs: Rig, FX Chain, Models, IRs, Presets, Settings, Record
- All screens wired to live API endpoints
- Real-time state via WebSocket + polling fallback
- Models screen: list/load/unload/upload NAM files + Tone3000 search/install
- IRs screen: list/load/unload/upload IR files + Tone3000 search/install
- Presets screen: browse banks, activate, save, delete
- Settings screen: WiFi scan/connect/hotspot, Bluetooth/MIDI, 4CM routing
- Rig screen: live state, volume, bypass, tuner, signal chain
- FX Chain screen: block params, per-block bypass
- Serves at / instead of /ui
- Built with Vite, ~71KB gzipped
This commit is contained in:
2026-06-12 15:30:03 -04:00
parent 35d2dc0893
commit 32690c293e
18 changed files with 4342 additions and 2 deletions
+9 -2
View File
@@ -168,8 +168,15 @@ class WebServer:
# ── HTML pages ──────────────────────────────────────────────
@app.get("/", response_class=HTMLResponse)
async def dashboard(request: Request):
"""Main dashboard — current preset, bypass, tuner, volume."""
async def root(request: Request):
"""Serve the React SPA (or legacy dashboard as fallback)."""
# If we have a React build, serve it at /
if UI_DIST_DIR and UI_DIST_DIR.is_dir():
index_html = UI_DIST_DIR / "index.html"
if index_html.exists():
content = index_html.read_text()
return HTMLResponse(content)
# Fallback: legacy dashboard
state = self._gather_state()
ctx = {"request": request}
ctx.update(state)