Major optimizations to reduce UI lag with large queues (5000+ items):
1. ItemRow extracted to its own memoized component (renderer)
Previously every package re-render mapped all its items inline,
producing N×M re-renders per state update. Now each item-row only
re-renders when ITS specific data changes, with custom equality on
the visible fields (status, progress, speed, fullStatus, etc.).
Also adds stable useCallback handlers per item.
2. PackageCard stats consolidated into single useMemo (renderer)
Replaces 5 separate filter()/some() + 2 reduce() calls (O(7N)) with
one O(N) pass collecting all aggregates (done/failed/cancelled/
extracted/extracting/activeProgress/extractingProgress).
3. selectedIds memo comparator fixed (renderer)
Custom equality now checks if selection state changed for items in
THIS package only. Previously any selection anywhere broke memo on
all 200+ visible PackageCards.
4. Scheduler single-pass queue presence (main)
New getQueuePresence() returns hasImmediate + hasDelayed in one
iteration. Replaces hasQueuedItems() + hasDelayedQueuedItems() that
each scanned packages independently. Saves one full O(n) iteration
per scheduler tick.
No functional changes. All 565 tests green.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>