Unify value source icons across dropdowns and card badges
Extract getValueSourceIcon() into value-sources.js and use it for brightness source dropdowns and card badges in both LED and KC targets. Icons now match value source cards: 📊 static, 🔄 animated, 🎵 audio, 🕐 adaptive_time, 🌤️ adaptive_scene. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import { API_BASE, getHeaders, fetchWithAuth, escapeHtml } from '../core/api.js'
|
|||||||
import { t } from '../core/i18n.js';
|
import { t } from '../core/i18n.js';
|
||||||
import { lockBody, showToast, showConfirm, formatUptime } from '../core/ui.js';
|
import { lockBody, showToast, showConfirm, formatUptime } from '../core/ui.js';
|
||||||
import { Modal } from '../core/modal.js';
|
import { Modal } from '../core/modal.js';
|
||||||
|
import { getValueSourceIcon } from './value-sources.js';
|
||||||
|
|
||||||
class KCEditorModal extends Modal {
|
class KCEditorModal extends Modal {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -81,7 +82,7 @@ export function createKCTargetCard(target, sourceMap, patternTemplateMap, valueS
|
|||||||
<span class="stream-card-prop" title="${t('kc.pattern_template')}">📄 ${escapeHtml(patternName)}</span>
|
<span class="stream-card-prop" title="${t('kc.pattern_template')}">📄 ${escapeHtml(patternName)}</span>
|
||||||
<span class="stream-card-prop">▭ ${rectCount} rect${rectCount !== 1 ? 's' : ''}</span>
|
<span class="stream-card-prop">▭ ${rectCount} rect${rectCount !== 1 ? 's' : ''}</span>
|
||||||
<span class="stream-card-prop" title="${t('kc.fps')}">⚡ ${kcSettings.fps ?? 10}</span>
|
<span class="stream-card-prop" title="${t('kc.fps')}">⚡ ${kcSettings.fps ?? 10}</span>
|
||||||
${bvs ? `<span class="stream-card-prop stream-card-prop-full" title="${t('targets.brightness_vs')}">🔆 ${escapeHtml(bvs.name)}</span>` : ''}
|
${bvs ? `<span class="stream-card-prop stream-card-prop-full" title="${t('targets.brightness_vs')}">${getValueSourceIcon(bvs.source_type)} ${escapeHtml(bvs.name)}</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<div class="brightness-control" data-kc-brightness-wrap="${target.id}">
|
<div class="brightness-control" data-kc-brightness-wrap="${target.id}">
|
||||||
<input type="range" class="brightness-slider" min="0" max="255"
|
<input type="range" class="brightness-slider" min="0" max="255"
|
||||||
@@ -363,9 +364,10 @@ function _populateKCBrightnessVsDropdown(selectedId = '') {
|
|||||||
// Keep the first "None" option, remove the rest
|
// Keep the first "None" option, remove the rest
|
||||||
while (sel.options.length > 1) sel.remove(1);
|
while (sel.options.length > 1) sel.remove(1);
|
||||||
_cachedValueSources.forEach(vs => {
|
_cachedValueSources.forEach(vs => {
|
||||||
|
const icon = getValueSourceIcon(vs.source_type);
|
||||||
const opt = document.createElement('option');
|
const opt = document.createElement('option');
|
||||||
opt.value = vs.id;
|
opt.value = vs.id;
|
||||||
opt.textContent = `🔢 ${vs.name}`;
|
opt.textContent = `${icon} ${vs.name}`;
|
||||||
sel.appendChild(opt);
|
sel.appendChild(opt);
|
||||||
});
|
});
|
||||||
sel.value = selectedId || '';
|
sel.value = selectedId || '';
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { Modal } from '../core/modal.js';
|
|||||||
import { createDeviceCard, attachDeviceListeners, fetchDeviceBrightness, _computeMaxFps } from './devices.js';
|
import { createDeviceCard, attachDeviceListeners, fetchDeviceBrightness, _computeMaxFps } from './devices.js';
|
||||||
import { createKCTargetCard, connectKCWebSocket, disconnectKCWebSocket } from './kc-targets.js';
|
import { createKCTargetCard, connectKCWebSocket, disconnectKCWebSocket } from './kc-targets.js';
|
||||||
import { createColorStripCard } from './color-strips.js';
|
import { createColorStripCard } from './color-strips.js';
|
||||||
|
import { getValueSourceIcon } from './value-sources.js';
|
||||||
import { CardSection } from '../core/card-sections.js';
|
import { CardSection } from '../core/card-sections.js';
|
||||||
|
|
||||||
// createPatternTemplateCard is imported via window.* to avoid circular deps
|
// createPatternTemplateCard is imported via window.* to avoid circular deps
|
||||||
@@ -184,7 +185,8 @@ function _populateBrightnessVsDropdown(selectedId = '') {
|
|||||||
const select = document.getElementById('target-editor-brightness-vs');
|
const select = document.getElementById('target-editor-brightness-vs');
|
||||||
let html = `<option value="">${t('targets.brightness_vs.none')}</option>`;
|
let html = `<option value="">${t('targets.brightness_vs.none')}</option>`;
|
||||||
_cachedValueSources.forEach(vs => {
|
_cachedValueSources.forEach(vs => {
|
||||||
html += `<option value="${vs.id}"${vs.id === selectedId ? ' selected' : ''}>🔢 ${escapeHtml(vs.name)}</option>`;
|
const icon = getValueSourceIcon(vs.source_type);
|
||||||
|
html += `<option value="${vs.id}"${vs.id === selectedId ? ' selected' : ''}>${icon} ${escapeHtml(vs.name)}</option>`;
|
||||||
});
|
});
|
||||||
select.innerHTML = html;
|
select.innerHTML = html;
|
||||||
}
|
}
|
||||||
@@ -677,7 +679,7 @@ export function createTargetCard(target, deviceMap, colorStripSourceMap, valueSo
|
|||||||
<span class="stream-card-prop" title="${t('targets.device')}">💡 ${escapeHtml(deviceName)}</span>
|
<span class="stream-card-prop" title="${t('targets.device')}">💡 ${escapeHtml(deviceName)}</span>
|
||||||
<span class="stream-card-prop" title="${t('targets.fps')}">⚡ ${target.fps || 30}</span>
|
<span class="stream-card-prop" title="${t('targets.fps')}">⚡ ${target.fps || 30}</span>
|
||||||
<span class="stream-card-prop stream-card-prop-full" title="${t('targets.color_strip_source')}">🎞️ ${cssSummary}</span>
|
<span class="stream-card-prop stream-card-prop-full" title="${t('targets.color_strip_source')}">🎞️ ${cssSummary}</span>
|
||||||
${bvs ? `<span class="stream-card-prop stream-card-prop-full" title="${t('targets.brightness_vs')}">🔆 ${escapeHtml(bvs.name)}</span>` : ''}
|
${bvs ? `<span class="stream-card-prop stream-card-prop-full" title="${t('targets.brightness_vs')}">${getValueSourceIcon(bvs.source_type)} ${escapeHtml(bvs.name)}</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
${isProcessing ? `
|
${isProcessing ? `
|
||||||
|
|||||||
@@ -255,9 +255,15 @@ export async function deleteValueSource(sourceId) {
|
|||||||
|
|
||||||
// ── Card rendering (used by streams.js) ───────────────────────
|
// ── Card rendering (used by streams.js) ───────────────────────
|
||||||
|
|
||||||
|
const _vsTypeIcons = { static: '📊', animated: '🔄', audio: '🎵', adaptive_time: '🕐', adaptive_scene: '🌤️' };
|
||||||
|
|
||||||
|
/** Return the emoji icon for a given value source type. */
|
||||||
|
export function getValueSourceIcon(sourceType) {
|
||||||
|
return _vsTypeIcons[sourceType] || '🎚️';
|
||||||
|
}
|
||||||
|
|
||||||
export function createValueSourceCard(src) {
|
export function createValueSourceCard(src) {
|
||||||
const typeIcons = { static: '📊', animated: '🔄', audio: '🎵', adaptive_time: '🕐', adaptive_scene: '🌤️' };
|
const icon = getValueSourceIcon(src.source_type);
|
||||||
const icon = typeIcons[src.source_type] || '🎚️';
|
|
||||||
|
|
||||||
let propsHtml = '';
|
let propsHtml = '';
|
||||||
if (src.source_type === 'static') {
|
if (src.source_type === 'static') {
|
||||||
|
|||||||
Reference in New Issue
Block a user