Override blend mode, FPS sparkline, fix api_input persistence

New features:
- Override composite blend mode: per-pixel alpha from brightness
  (black=transparent, bright=opaque). Ideal for API input over effects.
- API input test preview FPS chart uses shared createFpsSparkline
  (same look as target card charts)

Fixes:
- Fix api_input source not surviving server restart: from_dict was
  still passing removed led_count field to constructor
- Fix composite layer brightness/processing selectors not aligned:
  labels get fixed width, selects fill remaining space
- Fix CSPT input selector showing in non-CSPT CSS test mode
- Fix test modal LED/FPS controls showing for api_input sources
- Server only sends test WS frames when api_input push_generation changes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 15:12:57 +03:00
parent be356f30eb
commit afd4a3bc05
8 changed files with 47 additions and 2 deletions

View File

@@ -1516,6 +1516,19 @@
min-width: 0;
}
.composite-layer-brightness-label {
flex-shrink: 0;
width: 90px;
font-size: 0.8rem;
color: var(--text-secondary);
}
.composite-layer-brightness,
.composite-layer-cspt {
flex: 1;
min-width: 0;
}
.composite-layer-blend {
width: 100px;
flex-shrink: 0;

View File

@@ -685,6 +685,7 @@ function _getCompositeBlendItems() {
{ value: 'add', icon: _icon(P.sun), label: t('color_strip.composite.blend_mode.add'), desc: t('color_strip.composite.blend_mode.add.desc') },
{ value: 'multiply', icon: _icon(P.eye), label: t('color_strip.composite.blend_mode.multiply'), desc: t('color_strip.composite.blend_mode.multiply.desc') },
{ value: 'screen', icon: _icon(P.monitor), label: t('color_strip.composite.blend_mode.screen'), desc: t('color_strip.composite.blend_mode.screen.desc') },
{ value: 'override', icon: _icon(P.zap), label: t('color_strip.composite.blend_mode.override'), desc: t('color_strip.composite.blend_mode.override.desc') },
];
}
@@ -741,6 +742,7 @@ function _compositeRenderList() {
<option value="add"${layer.blend_mode === 'add' ? ' selected' : ''}>${t('color_strip.composite.blend_mode.add')}</option>
<option value="multiply"${layer.blend_mode === 'multiply' ? ' selected' : ''}>${t('color_strip.composite.blend_mode.multiply')}</option>
<option value="screen"${layer.blend_mode === 'screen' ? ' selected' : ''}>${t('color_strip.composite.blend_mode.screen')}</option>
<option value="override"${layer.blend_mode === 'override' ? ' selected' : ''}>${t('color_strip.composite.blend_mode.override')}</option>
</select>
</div>
<div class="composite-layer-row">

View File

@@ -1131,6 +1131,8 @@
"color_strip.composite.blend_mode.multiply.desc": "Darkens by multiplying colors",
"color_strip.composite.blend_mode.screen": "Screen",
"color_strip.composite.blend_mode.screen.desc": "Brightens, inverse of multiply",
"color_strip.composite.blend_mode.override": "Override",
"color_strip.composite.blend_mode.override.desc": "Black = transparent, bright = opaque",
"color_strip.composite.opacity": "Opacity",
"color_strip.composite.brightness": "Brightness",
"color_strip.composite.brightness.none": "None (full brightness)",

View File

@@ -1131,6 +1131,8 @@
"color_strip.composite.blend_mode.multiply.desc": "Затемняет, умножая цвета",
"color_strip.composite.blend_mode.screen": "Экран",
"color_strip.composite.blend_mode.screen.desc": "Осветляет, обратное умножение",
"color_strip.composite.blend_mode.override": "Замена",
"color_strip.composite.blend_mode.override.desc": "Чёрный = прозрачный, яркий = непрозрачный",
"color_strip.composite.opacity": "Непрозрачность",
"color_strip.composite.brightness": "Яркость",
"color_strip.composite.brightness.none": "Нет (полная яркость)",

View File

@@ -1131,6 +1131,8 @@
"color_strip.composite.blend_mode.multiply.desc": "通过相乘颜色变暗",
"color_strip.composite.blend_mode.screen": "滤色",
"color_strip.composite.blend_mode.screen.desc": "提亮,正片叠底的反转",
"color_strip.composite.blend_mode.override": "覆盖",
"color_strip.composite.blend_mode.override.desc": "黑色=透明,亮色=不透明",
"color_strip.composite.opacity": "不透明度",
"color_strip.composite.brightness": "亮度",
"color_strip.composite.brightness.none": "无(全亮度)",