Files
alexei.dolgolyov 304fa24389 Comprehensive WebUI review: 41 UX/feature/CSS improvements
Safety & Correctness:
- Add confirmation dialogs to Stop All, turnOffDevice
- i18n confirm dialog (title, yes, no buttons)
- Fix duplicate tutorial-overlay ID
- Define missing CSS variables (--radius, --text-primary, --hover-bg, --input-bg)
- Fix toast z-index conflict with confirm dialog (2500 → 3000)

UX Consistency:
- Add backdrop-close to test modals
- Add device clone feature (only entity without it)
- Add sync clocks to command palette
- Replace 20+ hardcoded accent colors with CSS vars/color-mix()
- Remove dead .badge duplicate from components.css
- Make calibration elements keyboard-accessible (div → button)
- Add aria-labels to color picker swatches
- Fix pattern canvas mobile horizontal scroll
- Fix graph editor mobile bottom clipping

Polish:
- Add empty-state messages to all CardSection instances
- Convert 21 px font-sizes to rem
- Add scroll-behavior: smooth with reduced-motion override
- Add @media print styles
- Add :focus-visible to 4 missing interactive elements
- Fix settings modal close label (Cancel → Close)
- Fix api-key submit button i18n

New Features:
- Command palette actions: start/stop targets, activate scenes, enable/disable
- Bulk start/stop API endpoints (POST /output-targets/bulk/start|stop)
- OS notification history viewer modal
- Scene "used by" automation reference count on cards
- Clock elapsed time display on Streams tab cards
- Device "last seen" relative timestamp on cards
- Audio device refresh button in edit modal
- Composite layer drag-to-reorder
- MQTT settings panel (broker config with JSON persistence)
- WebSocket log viewer with level filtering and ring buffer
- Runtime log-level adjustment (GET/PUT endpoints + settings UI)
- Animated value source waveform canvas preview
- Gradient custom preset save/delete (localStorage)
- API key read-only display in settings
- Backup metadata (file size, auto/manual badges)
- Server restart button with confirm + overlay
- Partial config export/import per entity type
- Progressive disclosure in target editor (Advanced section)

CSS Architecture:
- Define radius scale tokens (--radius-sm/md/lg/pill)
- Scope .cs-filter selectors to remove 7 !important overrides
- Consolidate duplicate toggle switch (filter-list → settings-toggle)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 18:46:38 +03:00

8.5 KiB
Raw Permalink Blame History

Pending Features & Issues

Priority: P1 quick win · P2 moderate · P3 large effort

Processing Pipeline

  • P3 Transition effects — Crossfade, wipe, or dissolve between sources/profiles instead of instant cut
    • Complexity: large — requires a new transition layer concept in ProcessorManager; must blend two live streams simultaneously during switch, coordinating start/stop timing
    • Impact: medium — polishes profile switching UX but ambient lighting rarely switches sources frequently

Output Targets

  • P2 Art-Net / sACN (E1.31) — Stage/theatrical lighting protocols, DMX controllers
    • Complexity: medium — UDP-based protocols with well-documented specs; similar architecture to DDP client; needs DMX universe/channel mapping UI
    • Impact: medium — opens stage/theatrical use case, niche but differentiating

Capture Engines

  • P3 SCRCPY capture engine — Implement SCRCPY-based screen capture for Android devices
    • Complexity: large — external dependency on scrcpy binary; need to manage subprocess lifecycle, parse video stream (ffmpeg/AV pipe), handle device connect/disconnect
    • Impact: medium — enables phone screen mirroring to ambient lighting; appeals to mobile gaming use case

Code Health

  • P1 "Start All" targets button — "Stop All" exists but "Start All" is missing
  • P2 Manual backup trigger endpointPOST /system/auto-backup/trigger (~5 lines)
  • P2 Scene snapshot should capture device brightnesssoftware_brightness not saved/restored
  • P2 Distinguish "crashed" vs "stopped" in dashboardmetrics.last_error is already populated
  • P3 CSS source import/export — share individual sources without full config backup

Backend Review Fixes (2026-03-14)

Performance

  • P1 PIL blocking in async handlers → asyncio.to_thread
  • P2 subprocess.run blocking event loop → asyncio.create_subprocess_exec
  • P3 Audio enum blocking async → asyncio.to_thread
  • P4 Display enum blocking async → asyncio.to_thread
  • P5 colorsys scalar loop in hot path → vectorize numpy
  • P6 MappedStream per-frame allocation → double-buffer
  • P7 Audio/effect per-frame temp allocs → pre-allocate
  • P8 Blocking httpx.get in stream init → documented (callers use to_thread)
  • P9 No-cache middleware runs on all requests → scope to static
  • P10 Sync file I/O in async handlers (stores) → documented as accepted risk (< 5ms)
  • P11 frame_time float division every loop iter → cache field
  • P12 _check_name_unique O(N) + no lock → add threading.Lock
  • P13 Imports inside 1-Hz metrics loop → move to module level

Code Quality

  • Q1 DeviceStore not using BaseJsonStore
  • Q2 ColorStripStore 275-line god methods → factory dispatch
  • Q3 Layer violation: core imports from routes → extract to utility
  • Q4 20+ field-by-field update in Device/routes → dataclass + generic update
  • Q5 WebSocket auth copy-pasted 9x → extract helper
  • Q6 set_device_brightness bypasses store → use update_device
  • Q7 DI via 16+ module globals → registry pattern
  • Q8 _css_to_response 30+ getattr → polymorphic to_response
  • Q9 Private attribute access across modules → expose as properties
  • Q10 ColorStripSource.to_dict() emits ~25 nulls → per-subclass override
  • Q11 DeviceStore.get_device returns None vs raises → raise ValueError
  • Q12 list_all_tags fragile method-name probing → use get_all()
  • Q13 Route create/update pass 30 individual fields → **kwargs

UX

  • P1 Collapse dashboard running target stats — Show only FPS chart by default; uptime, errors, and pipeline timings in an expandable section collapsed by default
  • P1 Daylight brightness value source — New value source type that reports a 0255 brightness level based on daylight cycle time (real-time or simulated), reusing the daylight LUT logic
  • P1 Tags input: move under name, remove hint/title — Move the tags chip input directly below the name field in all entity editor modals; remove the hint toggle and section title for a cleaner layout

WebUI Review (2026-03-16)

Critical (Safety & Correctness)

  • P1 "Stop All" buttons need confirmation — dashboard, LED targets, KC targets
  • P1 turnOffDevice() needs confirmation
  • P1 Confirm dialog i18n — added data-i18n to title/buttons
  • P1 Duplicate id="tutorial-overlay" — renamed to calibration-tutorial-overlay
  • P1 Define missing CSS variables — --radius, --text-primary, --hover-bg, --input-bg
  • P1 Toast z-index conflict — toast now 3000

UX Consistency

  • P1 Test modals backdrop-close — added setupBackdropClose
  • P1 Devices clone — added cloneDevice with full field prefill
  • P1 Sync clocks in command palette — added to _responseKeys + _buildItems
  • P2 Hardcoded accent colors — 20+ replacements using color-mix() and CSS vars
  • P2 Duplicate .badge definition — removed dead code from components.css
  • P2 Calibration elements keyboard-accessible — changed div to button
  • P2 Color-picker swatch aria-labels — added aria-label with hex value
  • P2 Pattern canvas mobile scroll — added min-width: 0 override in mobile.css
  • P2 Graph editor mobile bottom clipping — adjusted height in mobile.css

Low Priority Polish

  • P3 Empty-state illustrations/onboarding — CardSection emptyKey with per-entity messages
  • P3 api-key-modal submit title i18n
  • P3 Settings modal close labeled "Cancel" → "Close"
  • P3 Inconsistent px vs rem font sizes — 21 conversions across streams/modal/cards CSS
  • P3 scroll-behavior: smooth — added with reduced-motion override
  • P3 Reduce !important usage — scoped .cs-filter selectors
  • P3 @media print styles — theme reset + hide nav
  • P3 :focus-visible on interactive elements — added 4 missing selectors
  • P3 iOS Safari modal scroll-position jump — already implemented in ui.js lockBody/unlockBody

New Features

  • P1 Command palette actions — start/stop targets, activate scenes, enable/disable automations
  • P1 Bulk start/stop API — POST /output-targets/bulk/start and /bulk/stop
  • P1 OS notification history viewer — modal with app name, timestamp, fired/filtered badges
  • P1 Scene "used by" reference count — badge on card with automation count
  • P1 Clock elapsed time on cards — shows formatted elapsed time
  • P1 Device "last seen" timestamp — relative time with full ISO in title
  • P2 Audio device refresh in modal — refresh button next to device dropdown
  • P2 Composite layer reorder — drag handles with pointer-based reorder
  • P2 MQTT settings panel — config form with enabled/host/port/auth/topic, JSON persistence
  • P2 Log viewer — WebSocket broadcaster with ring buffer, level-filtered UI in settings
  • P2 Animated value source waveform preview — canvas drawing of sine/triangle/sawtooth/square
  • P2 Gradient custom preset save — localStorage-backed custom presets with save/delete
  • P2 API key management UI — read-only display of key labels with masked values
  • P2 Backup metadata — file size, auto/manual badge
  • P2 Server restart button — in settings with confirm dialog + restart overlay
  • P2 Partial config export/import — per-store export/import with merge option
  • P3 Audio spectrum visualizer — already fully implemented
  • P3 Hue bridge pairing flow — requires physical Hue bridge hardware
  • P3 Runtime log-level adjustment — GET/PUT endpoints + settings dropdown
  • P3 Progressive disclosure in target editor — advanced section collapsed by default

CSS Architecture

  • P1 Define missing CSS variables — --radius, --text-primary, --hover-bg, --input-bg
  • P2 Define radius scale — --radius-sm/md/lg/pill tokens, migrated key selectors
  • P2 Scope generic input selector — .cs-filter boosted specificity, 7 !important removed
  • P2 Consolidate duplicate toggle switch — filter-list uses settings-toggle
  • P2 Replace hardcoded accent colors — 20+ values → CSS vars with color-mix()