Add running target indicator to command palette

Fetch /picture-targets/batch/states alongside entity data and show a
small green glowing dot next to targets that are currently processing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 23:49:26 +03:00
parent 32a54b7d3c
commit cb779e10d3
2 changed files with 23 additions and 8 deletions

View File

@@ -489,6 +489,15 @@ h2 {
color: var(--text-secondary);
}
.cp-running {
width: 6px;
height: 6px;
border-radius: 50%;
background: #4caf50;
flex-shrink: 0;
box-shadow: 0 0 4px #4caf50;
}
.cp-loading,
.cp-empty {
padding: 24px 16px;

View File

@@ -31,7 +31,7 @@ function _mapEntities(data, mapFn) {
return [];
}
function _buildItems(results) {
function _buildItems(results, states = {}) {
const [devices, targets, css, automations, capTempl, ppTempl, patTempl, audioSrc, valSrc, streams, scenePresets] = results;
const items = [];
@@ -41,15 +41,16 @@ function _buildItems(results) {
}));
_mapEntities(targets, tgt => {
const running = !!states[tgt.id]?.processing;
if (tgt.target_type === 'key_colors') {
items.push({
name: tgt.name, detail: 'key_colors', group: 'kc_targets', icon: getTargetTypeIcon('key_colors'),
nav: ['targets', 'key_colors', 'kc-targets', 'data-kc-target-id', tgt.id],
nav: ['targets', 'key_colors', 'kc-targets', 'data-kc-target-id', tgt.id], running,
});
} else {
items.push({
name: tgt.name, detail: tgt.target_type, group: 'targets', icon: ICON_TARGET,
nav: ['targets', 'led', 'led-targets', 'data-target-id', tgt.id],
nav: ['targets', 'led', 'led-targets', 'data-target-id', tgt.id], running,
});
}
});
@@ -124,14 +125,18 @@ const _responseKeys = [
];
async function _fetchAllEntities() {
const results = await Promise.all(
_responseKeys.map(([ep, key]) =>
const [statesData, ...results] = await Promise.all([
fetchWithAuth('/picture-targets/batch/states', { retry: false, timeout: 5000 })
.then(r => r.ok ? r.json() : {})
.then(data => data.states || {})
.catch(() => ({})),
..._responseKeys.map(([ep, key]) =>
fetchWithAuth(ep, { retry: false, timeout: 5000 })
.then(r => r.ok ? r.json() : {})
.then(data => data[key] || [])
.catch(() => []))
);
return _buildItems(results);
.catch(() => [])),
]);
return _buildItems(results, statesData);
}
// ─── Group ordering ───
@@ -197,6 +202,7 @@ function _render() {
html += `<div class="cp-result${active}" data-cp-idx="${idx}"${colorStyle}>` +
`<span class="cp-icon">${item.icon}</span>` +
`<span class="cp-name">${_escHtml(item.name)}</span>` +
(item.running ? '<span class="cp-running"></span>' : '') +
(item.detail ? `<span class="cp-detail">${_escHtml(item.detail)}</span>` : '') +
`</div>`;
idx++;