Card bulk operations, remove expand/collapse, graph color picker fix
- Bulk selection mode: Ctrl+Click or toggle button to enter, Escape to exit - Shift+Click for range select, bottom toolbar with SVG icon action buttons - All CardSections wired with bulk actions: Delete everywhere, Start/Stop for targets, Enable/Disable for automations - Remove expand/collapse all buttons (no collapsible sections remain) - Fix graph node color picker overlay persisting after outside click - Add Icons section to frontend.md conventions - Add trash2, listChecks, circleOff icons to icon system - Backend: processing loop performance improvements (monotonic timestamps, deque-based FPS tracking) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -595,7 +595,13 @@ class WledTargetProcessor(TargetProcessor):
|
||||
|
||||
fps_samples: collections.deque = collections.deque(maxlen=10)
|
||||
_fps_sum = 0.0
|
||||
send_timestamps: collections.deque = collections.deque(maxlen=target_fps + 10)
|
||||
send_timestamps: collections.deque = collections.deque(maxlen=self._target_fps + 10)
|
||||
|
||||
def _fps_current_from_timestamps():
|
||||
"""Count timestamps within the last second."""
|
||||
cutoff = time.perf_counter() - 1.0
|
||||
return sum(1 for ts in send_timestamps if ts > cutoff)
|
||||
|
||||
last_send_time = 0.0
|
||||
_last_preview_broadcast = 0.0
|
||||
prev_frame_time_stamp = time.perf_counter()
|
||||
@@ -839,7 +845,7 @@ class WledTargetProcessor(TargetProcessor):
|
||||
send_timestamps.append(now)
|
||||
self._metrics.frames_keepalive += 1
|
||||
self._metrics.frames_skipped += 1
|
||||
self._metrics.fps_current = len(send_timestamps)
|
||||
self._metrics.fps_current = _fps_current_from_timestamps()
|
||||
await asyncio.sleep(SKIP_REPOLL)
|
||||
continue
|
||||
|
||||
@@ -864,7 +870,7 @@ class WledTargetProcessor(TargetProcessor):
|
||||
await self._broadcast_led_preview(send_colors, cur_brightness)
|
||||
_last_preview_broadcast = now
|
||||
self._metrics.frames_skipped += 1
|
||||
self._metrics.fps_current = len(send_timestamps)
|
||||
self._metrics.fps_current = _fps_current_from_timestamps()
|
||||
is_animated = stream.is_animated
|
||||
repoll = SKIP_REPOLL if is_animated else frame_time
|
||||
await asyncio.sleep(repoll)
|
||||
@@ -923,7 +929,7 @@ class WledTargetProcessor(TargetProcessor):
|
||||
processing_time = now - loop_start
|
||||
self._metrics.fps_potential = 1.0 / processing_time if processing_time > 0 else 0
|
||||
|
||||
self._metrics.fps_current = len(send_timestamps)
|
||||
self._metrics.fps_current = _fps_current_from_timestamps()
|
||||
|
||||
except Exception as e:
|
||||
self._metrics.errors_count += 1
|
||||
|
||||
Reference in New Issue
Block a user