Add OpenRGB per-zone LED control with separate/combined modes and zone preview

- Zone picker UI in device add/settings modals with per-zone checkbox selection
- Combined mode: pixels distributed sequentially across zones
- Separate mode: full effect resampled independently to each zone via linear interpolation
- Per-zone LED preview in target cards: one canvas strip per zone with hover overlay labels
- Zone badges on device cards enriched with actual LED counts from OpenRGB API
- Fix stale led_count by using device_led_count discovered at connect time

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 20:35:51 +03:00
parent aafcf83896
commit 52ee4bdeb6
19 changed files with 769 additions and 55 deletions

View File

@@ -32,6 +32,7 @@ class Device:
auto_shutdown: bool = False,
send_latency_ms: int = 0,
rgbw: bool = False,
zone_mode: str = "combined",
created_at: Optional[datetime] = None,
updated_at: Optional[datetime] = None,
):
@@ -46,6 +47,7 @@ class Device:
self.auto_shutdown = auto_shutdown
self.send_latency_ms = send_latency_ms
self.rgbw = rgbw
self.zone_mode = zone_mode
self.created_at = created_at or datetime.utcnow()
self.updated_at = updated_at or datetime.utcnow()
@@ -71,6 +73,8 @@ class Device:
d["send_latency_ms"] = self.send_latency_ms
if self.rgbw:
d["rgbw"] = True
if self.zone_mode != "combined":
d["zone_mode"] = self.zone_mode
return d
@classmethod
@@ -88,6 +92,7 @@ class Device:
auto_shutdown=data.get("auto_shutdown", False),
send_latency_ms=data.get("send_latency_ms", 0),
rgbw=data.get("rgbw", False),
zone_mode=data.get("zone_mode", "combined"),
created_at=datetime.fromisoformat(data.get("created_at", datetime.utcnow().isoformat())),
updated_at=datetime.fromisoformat(data.get("updated_at", datetime.utcnow().isoformat())),
)
@@ -175,6 +180,7 @@ class DeviceStore:
auto_shutdown: bool = False,
send_latency_ms: int = 0,
rgbw: bool = False,
zone_mode: str = "combined",
) -> Device:
"""Create a new device."""
device_id = f"device_{uuid.uuid4().hex[:8]}"
@@ -193,6 +199,7 @@ class DeviceStore:
auto_shutdown=auto_shutdown,
send_latency_ms=send_latency_ms,
rgbw=rgbw,
zone_mode=zone_mode,
)
self._devices[device_id] = device
@@ -220,6 +227,7 @@ class DeviceStore:
auto_shutdown: Optional[bool] = None,
send_latency_ms: Optional[int] = None,
rgbw: Optional[bool] = None,
zone_mode: Optional[str] = None,
) -> Device:
"""Update device."""
device = self._devices.get(device_id)
@@ -242,6 +250,8 @@ class DeviceStore:
device.send_latency_ms = send_latency_ms
if rgbw is not None:
device.rgbw = rgbw
if zone_mode is not None:
device.zone_mode = zone_mode
device.updated_at = datetime.utcnow()
self.save()