Live KC test WS, sync clock fix, device card perf, camera icons, tab indicator

Key Colors test:
- New WS endpoint for live KC target test streaming (replaces REST polling)
- Auto-connect on lightbox open, auto-disconnect on close
- Uses same FPS/preview_width as CSS source test (no separate controls)
- Removed FPS selector, start/stop toggle, and updateAutoRefreshButton

Device cards:
- Fix full re-render on every poll caused by relative "Last seen" time in HTML
- Last seen label now patched in-place via data attribute (like FPS metrics)
- Remove overlay visualization button from LED target cards

Sync clocks:
- Fix card not updating start/stop icon: invalidate cache before reload

Other:
- Tab indicator respects bg-anim toggle (hidden when dynamic background off)
- Camera backend icon grid uses SVG icons instead of emoji
- Frontend context rule: no emoji in IconSelect items

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 02:03:07 +03:00
parent bcba5f33fc
commit 00c9ad3a86
16 changed files with 430 additions and 85 deletions

View File

@@ -16,7 +16,7 @@ import { API_BASE, getHeaders, fetchWithAuth, escapeHtml, isOpenrgbDevice } from
import { t } from '../core/i18n.js';
import { showToast, showConfirm, formatUptime, formatCompact, setTabRefreshing, desktopFocus } from '../core/ui.js';
import { Modal } from '../core/modal.js';
import { createDeviceCard, attachDeviceListeners, fetchDeviceBrightness, enrichOpenrgbZoneBadges, _computeMaxFps, getZoneCountCache } from './devices.js';
import { createDeviceCard, attachDeviceListeners, fetchDeviceBrightness, enrichOpenrgbZoneBadges, _computeMaxFps, getZoneCountCache, formatRelativeTime } from './devices.js';
import { _splitOpenrgbZone } from './device-discovery.js';
import { createKCTargetCard, patchKCTargetMetrics, connectKCWebSocket, disconnectKCWebSocket } from './kc-targets.js';
import {
@@ -727,6 +727,17 @@ export async function loadTargetsTab() {
}
});
// Patch "Last seen" labels in-place (avoids full card re-render on relative time changes)
for (const device of devicesWithState) {
const el = container.querySelector(`[data-last-seen="${device.id}"]`);
if (el) {
const ts = device.state?.device_last_checked;
const label = ts ? formatRelativeTime(ts) : null;
el.textContent = label ? `\u23F1 ${t('device.last_seen.label')}: ${label}` : '';
if (ts) el.title = ts;
}
}
// Manage KC WebSockets: connect for processing, disconnect for stopped
const processingKCIds = new Set();
kcTargets.forEach(target => {
@@ -1021,15 +1032,7 @@ export function createTargetCard(target, deviceMap, colorStripSourceMap, valueSo
<button class="btn btn-icon btn-secondary" onclick="showTargetEditor('${target.id}')" title="${t('common.edit')}">
${ICON_EDIT}
</button>
${overlayAvailable ? (state.overlay_active ? `
<button class="btn btn-icon btn-warning" onclick="stopTargetOverlay('${target.id}')" title="${t('overlay.button.hide')}">
${ICON_OVERLAY}
</button>
` : `
<button class="btn btn-icon btn-secondary" onclick="startTargetOverlay('${target.id}')" title="${t('overlay.button.show')}">
${ICON_OVERLAY}
</button>
`) : ''}`,
`,
});
}