|
|
|
|
@@ -80,6 +80,13 @@ class CSSEditorModal extends Modal {
|
|
|
|
|
notification_filter_list: document.getElementById('css-editor-notification-filter-list').value,
|
|
|
|
|
notification_app_colors: JSON.stringify(_notificationAppColors),
|
|
|
|
|
clock_id: document.getElementById('css-editor-clock').value,
|
|
|
|
|
daylight_speed: document.getElementById('css-editor-daylight-speed').value,
|
|
|
|
|
daylight_use_real_time: document.getElementById('css-editor-daylight-real-time').checked,
|
|
|
|
|
daylight_latitude: document.getElementById('css-editor-daylight-latitude').value,
|
|
|
|
|
candlelight_color: document.getElementById('css-editor-candlelight-color').value,
|
|
|
|
|
candlelight_intensity: document.getElementById('css-editor-candlelight-intensity').value,
|
|
|
|
|
candlelight_num_candles: document.getElementById('css-editor-candlelight-num-candles').value,
|
|
|
|
|
candlelight_speed: document.getElementById('css-editor-candlelight-speed').value,
|
|
|
|
|
tags: JSON.stringify(_cssTagsInput ? _cssTagsInput.getValue() : []),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
@@ -99,7 +106,7 @@ let _cssClockEntitySelect = null;
|
|
|
|
|
const CSS_TYPE_KEYS = [
|
|
|
|
|
'picture', 'picture_advanced', 'static', 'gradient', 'color_cycle',
|
|
|
|
|
'effect', 'composite', 'mapped', 'audio',
|
|
|
|
|
'api_input', 'notification',
|
|
|
|
|
'api_input', 'notification', 'daylight', 'candlelight',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
function _buildCSSTypeItems() {
|
|
|
|
|
@@ -148,6 +155,8 @@ export function onCSSTypeChange() {
|
|
|
|
|
document.getElementById('css-editor-audio-section').style.display = type === 'audio' ? '' : 'none';
|
|
|
|
|
document.getElementById('css-editor-api-input-section').style.display = type === 'api_input' ? '' : 'none';
|
|
|
|
|
document.getElementById('css-editor-notification-section').style.display = type === 'notification' ? '' : 'none';
|
|
|
|
|
document.getElementById('css-editor-daylight-section').style.display = type === 'daylight' ? '' : 'none';
|
|
|
|
|
document.getElementById('css-editor-candlelight-section').style.display = type === 'candlelight' ? '' : 'none';
|
|
|
|
|
|
|
|
|
|
if (isPictureType) _ensureInterpolationIconSelect();
|
|
|
|
|
if (type === 'effect') {
|
|
|
|
|
@@ -197,8 +206,8 @@ export function onCSSTypeChange() {
|
|
|
|
|
document.getElementById('css-editor-led-count-group').style.display =
|
|
|
|
|
hasLedCount.includes(type) ? '' : 'none';
|
|
|
|
|
|
|
|
|
|
// Sync clock — shown for animated types (static, gradient, color_cycle, effect)
|
|
|
|
|
const clockTypes = ['static', 'gradient', 'color_cycle', 'effect'];
|
|
|
|
|
// Sync clock — shown for animated types
|
|
|
|
|
const clockTypes = ['static', 'gradient', 'color_cycle', 'effect', 'daylight', 'candlelight'];
|
|
|
|
|
document.getElementById('css-editor-clock-group').style.display = clockTypes.includes(type) ? '' : 'none';
|
|
|
|
|
if (clockTypes.includes(type)) _populateClockDropdown();
|
|
|
|
|
|
|
|
|
|
@@ -274,6 +283,17 @@ function _syncAnimationSpeedState() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ── Daylight real-time toggle helper ─────────────────────────── */
|
|
|
|
|
|
|
|
|
|
export function onDaylightRealTimeChange() {
|
|
|
|
|
_syncDaylightSpeedVisibility();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function _syncDaylightSpeedVisibility() {
|
|
|
|
|
const isRealTime = document.getElementById('css-editor-daylight-real-time').checked;
|
|
|
|
|
document.getElementById('css-editor-daylight-speed-group').style.display = isRealTime ? 'none' : '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ── Gradient strip preview helper ────────────────────────────── */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@@ -1039,6 +1059,23 @@ export function createColorStripCard(source, pictureSourceMap, audioSourceMap) {
|
|
|
|
|
</span>
|
|
|
|
|
${appCount > 0 ? `<span class="stream-card-prop">${ICON_PALETTE} ${appCount} ${t('color_strip.notification.app_count')}</span>` : ''}
|
|
|
|
|
`;
|
|
|
|
|
} else if (source.source_type === 'daylight') {
|
|
|
|
|
const useRealTime = source.use_real_time;
|
|
|
|
|
const speedVal = (source.speed ?? 1.0).toFixed(1);
|
|
|
|
|
propsHtml = `
|
|
|
|
|
<span class="stream-card-prop">${useRealTime ? '🕐 ' + t('color_strip.daylight.real_time') : '⏩ ' + speedVal + 'x'}</span>
|
|
|
|
|
${clockBadge}
|
|
|
|
|
`;
|
|
|
|
|
} else if (source.source_type === 'candlelight') {
|
|
|
|
|
const hexColor = rgbArrayToHex(source.color || [255, 147, 41]);
|
|
|
|
|
const numCandles = source.num_candles ?? 3;
|
|
|
|
|
propsHtml = `
|
|
|
|
|
<span class="stream-card-prop" title="${t('color_strip.candlelight.color')}">
|
|
|
|
|
<span style="display:inline-block;width:14px;height:14px;background:${hexColor};border:1px solid #888;border-radius:2px;vertical-align:middle;margin-right:4px"></span>${hexColor.toUpperCase()}
|
|
|
|
|
</span>
|
|
|
|
|
<span class="stream-card-prop">${numCandles} ${t('color_strip.candlelight.num_candles')}</span>
|
|
|
|
|
${clockBadge}
|
|
|
|
|
`;
|
|
|
|
|
} else if (isPictureAdvanced) {
|
|
|
|
|
const cal = source.calibration || {};
|
|
|
|
|
const lines = cal.lines || [];
|
|
|
|
|
@@ -1073,7 +1110,9 @@ export function createColorStripCard(source, pictureSourceMap, audioSourceMap) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const icon = getColorStripIcon(source.source_type);
|
|
|
|
|
const isPictureKind = (!isStatic && !isGradient && !isColorCycle && !isEffect && !isComposite && !isMapped && !isAudio && !isApiInput && !isNotification);
|
|
|
|
|
const isDaylight = source.source_type === 'daylight';
|
|
|
|
|
const isCandlelight = source.source_type === 'candlelight';
|
|
|
|
|
const isPictureKind = (!isStatic && !isGradient && !isColorCycle && !isEffect && !isComposite && !isMapped && !isAudio && !isApiInput && !isNotification && !isDaylight && !isCandlelight);
|
|
|
|
|
const calibrationBtn = isPictureKind
|
|
|
|
|
? `<button class="btn btn-icon btn-secondary" onclick="${isPictureAdvanced ? `showAdvancedCalibration('${source.id}')` : `showCSSCalibration('${source.id}')`}" title="${t('calibration.title')}">${ICON_CALIBRATION}</button>`
|
|
|
|
|
: '';
|
|
|
|
|
@@ -1217,6 +1256,20 @@ export async function showCSSEditor(cssId = null, cloneData = null) {
|
|
|
|
|
_showApiInputEndpoints(css.id);
|
|
|
|
|
} else if (sourceType === 'notification') {
|
|
|
|
|
_loadNotificationState(css);
|
|
|
|
|
} else if (sourceType === 'daylight') {
|
|
|
|
|
document.getElementById('css-editor-daylight-speed').value = css.speed ?? 1.0;
|
|
|
|
|
document.getElementById('css-editor-daylight-speed-val').textContent = parseFloat(css.speed ?? 1.0).toFixed(1);
|
|
|
|
|
document.getElementById('css-editor-daylight-real-time').checked = css.use_real_time || false;
|
|
|
|
|
document.getElementById('css-editor-daylight-latitude').value = css.latitude ?? 50.0;
|
|
|
|
|
document.getElementById('css-editor-daylight-latitude-val').textContent = parseFloat(css.latitude ?? 50.0).toFixed(0);
|
|
|
|
|
_syncDaylightSpeedVisibility();
|
|
|
|
|
} else if (sourceType === 'candlelight') {
|
|
|
|
|
document.getElementById('css-editor-candlelight-color').value = rgbArrayToHex(css.color || [255, 147, 41]);
|
|
|
|
|
document.getElementById('css-editor-candlelight-intensity').value = css.intensity ?? 1.0;
|
|
|
|
|
document.getElementById('css-editor-candlelight-intensity-val').textContent = parseFloat(css.intensity ?? 1.0).toFixed(1);
|
|
|
|
|
document.getElementById('css-editor-candlelight-num-candles').value = css.num_candles ?? 3;
|
|
|
|
|
document.getElementById('css-editor-candlelight-speed').value = css.speed ?? 1.0;
|
|
|
|
|
document.getElementById('css-editor-candlelight-speed-val').textContent = parseFloat(css.speed ?? 1.0).toFixed(1);
|
|
|
|
|
} else {
|
|
|
|
|
if (sourceType === 'picture') sourceSelect.value = css.picture_source_id || '';
|
|
|
|
|
|
|
|
|
|
@@ -1313,6 +1366,19 @@ export async function showCSSEditor(cssId = null, cloneData = null) {
|
|
|
|
|
document.getElementById('css-editor-api-input-timeout-val').textContent = '5.0';
|
|
|
|
|
_showApiInputEndpoints(null);
|
|
|
|
|
_resetNotificationState();
|
|
|
|
|
// Daylight defaults
|
|
|
|
|
document.getElementById('css-editor-daylight-speed').value = 1.0;
|
|
|
|
|
document.getElementById('css-editor-daylight-speed-val').textContent = '1.0';
|
|
|
|
|
document.getElementById('css-editor-daylight-real-time').checked = false;
|
|
|
|
|
document.getElementById('css-editor-daylight-latitude').value = 50.0;
|
|
|
|
|
document.getElementById('css-editor-daylight-latitude-val').textContent = '50';
|
|
|
|
|
// Candlelight defaults
|
|
|
|
|
document.getElementById('css-editor-candlelight-color').value = '#ff9329';
|
|
|
|
|
document.getElementById('css-editor-candlelight-intensity').value = 1.0;
|
|
|
|
|
document.getElementById('css-editor-candlelight-intensity-val').textContent = '1.0';
|
|
|
|
|
document.getElementById('css-editor-candlelight-num-candles').value = 3;
|
|
|
|
|
document.getElementById('css-editor-candlelight-speed').value = 1.0;
|
|
|
|
|
document.getElementById('css-editor-candlelight-speed-val').textContent = '1.0';
|
|
|
|
|
document.getElementById('css-editor-title').innerHTML = `${ICON_FILM} ${t('color_strip.add')}`;
|
|
|
|
|
document.getElementById('css-editor-gradient-preset').value = '';
|
|
|
|
|
gradientInit([
|
|
|
|
|
@@ -1473,6 +1539,23 @@ export async function saveCSSEditor() {
|
|
|
|
|
app_colors: _notificationGetAppColorsDict(),
|
|
|
|
|
};
|
|
|
|
|
if (!cssId) payload.source_type = 'notification';
|
|
|
|
|
} else if (sourceType === 'daylight') {
|
|
|
|
|
payload = {
|
|
|
|
|
name,
|
|
|
|
|
speed: parseFloat(document.getElementById('css-editor-daylight-speed').value),
|
|
|
|
|
use_real_time: document.getElementById('css-editor-daylight-real-time').checked,
|
|
|
|
|
latitude: parseFloat(document.getElementById('css-editor-daylight-latitude').value),
|
|
|
|
|
};
|
|
|
|
|
if (!cssId) payload.source_type = 'daylight';
|
|
|
|
|
} else if (sourceType === 'candlelight') {
|
|
|
|
|
payload = {
|
|
|
|
|
name,
|
|
|
|
|
color: hexToRgbArray(document.getElementById('css-editor-candlelight-color').value),
|
|
|
|
|
intensity: parseFloat(document.getElementById('css-editor-candlelight-intensity').value),
|
|
|
|
|
num_candles: parseInt(document.getElementById('css-editor-candlelight-num-candles').value) || 3,
|
|
|
|
|
speed: parseFloat(document.getElementById('css-editor-candlelight-speed').value),
|
|
|
|
|
};
|
|
|
|
|
if (!cssId) payload.source_type = 'candlelight';
|
|
|
|
|
} else if (sourceType === 'picture_advanced') {
|
|
|
|
|
payload = {
|
|
|
|
|
name,
|
|
|
|
|
@@ -1501,7 +1584,7 @@ export async function saveCSSEditor() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Attach clock_id for animated types
|
|
|
|
|
const clockTypes = ['static', 'gradient', 'color_cycle', 'effect'];
|
|
|
|
|
const clockTypes = ['static', 'gradient', 'color_cycle', 'effect', 'daylight', 'candlelight'];
|
|
|
|
|
if (clockTypes.includes(sourceType)) {
|
|
|
|
|
const clockVal = document.getElementById('css-editor-clock').value;
|
|
|
|
|
payload.clock_id = clockVal || null;
|
|
|
|
|
|