refactor: remove inline gradient editor from CSS modal, use entity picker
Some checks failed
Lint & Test / test (push) Failing after 30s

Replace the gradient stop editor (canvas, markers, stop list) in the
CSS editor gradient section with a simple gradient entity selector.
Gradients are now created/edited exclusively in the Gradients tab.

Fix effect and audio palette pickers to populate from gradient entities
dynamically instead of hardcoded HTML options.
Unify all gradient/palette pickers via _buildGradientEntityItems().

Also: rename "None (use own speed)" → "None (no sync)" for sync clocks.
Add i18n keys for gradient selector and missing error messages.
This commit is contained in:
2026-03-24 14:09:49 +03:00
parent fc62d5d3b1
commit 178d115cc5
3 changed files with 32 additions and 109 deletions

View File

@@ -398,10 +398,7 @@ function _ensureEffectTypeIconSelect() {
function _ensureEffectPaletteIconSelect() {
const sel = document.getElementById('css-editor-effect-palette') as HTMLSelectElement | null;
if (!sel) return;
const gradients = _getGradients();
const items = gradients.map(g => ({
value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
}));
const items = _buildGradientEntityItems();
if (_effectPaletteIconSelect) { _effectPaletteIconSelect.updateItems(items); return; }
_effectPaletteIconSelect = new IconSelect({ target: sel, items, columns: 2 });
}
@@ -435,10 +432,7 @@ function _ensureCandleTypeIconSelect() {
function _ensureAudioPaletteIconSelect() {
const sel = document.getElementById('css-editor-audio-palette') as HTMLSelectElement | null;
if (!sel) return;
const gradients = _getGradients();
const items = gradients.map(g => ({
value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
}));
const items = _buildGradientEntityItems();
if (_audioPaletteIconSelect) { _audioPaletteIconSelect.updateItems(items); return; }
_audioPaletteIconSelect = new IconSelect({ target: sel, items, columns: 2 });
}
@@ -455,37 +449,27 @@ function _ensureAudioVizIconSelect() {
_audioVizIconSelect = new IconSelect({ target: sel, items, columns: 3 });
}
function _buildGradientPresetItems() {
function _buildGradientEntityItems() {
const gradients = _getGradients();
const builtInItems = gradients.filter(g => g.is_builtin).map(g => ({
return gradients.map(g => ({
value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
}));
const userItems = gradients.filter(g => !g.is_builtin).map(g => ({
value: g.id, icon: _gradientEntityStripHTML(g.stops), label: g.name,
isCustom: true,
}));
return [
{ value: '', icon: _icon(P.palette), label: t('color_strip.gradient.preset.custom') },
...builtInItems,
...userItems,
];
}
function _ensureGradientPresetIconSelect() {
const sel = document.getElementById('css-editor-gradient-preset') as HTMLSelectElement | null;
if (!sel) return;
const items = _buildGradientPresetItems();
const items = _buildGradientEntityItems();
if (_gradientPresetIconSelect) { _gradientPresetIconSelect.updateItems(items); return; }
_gradientPresetIconSelect = new IconSelect({ target: sel, items, columns: 3, onChange: (v) => onGradientPresetChange(v) });
_gradientPresetIconSelect = new IconSelect({ target: sel, items, columns: 3 });
}
/** Rebuild the preset picker after adding/removing custom presets. */
/** Rebuild the gradient picker after entity changes. */
export function refreshGradientPresetPicker() {
if (_gradientPresetIconSelect) {
_gradientPresetIconSelect.updateItems(_buildGradientPresetItems());
_gradientPresetIconSelect.setValue('');
}
_renderCustomPresetList();
const items = _buildGradientEntityItems();
if (_gradientPresetIconSelect) _gradientPresetIconSelect.updateItems(items);
if (_effectPaletteIconSelect) _effectPaletteIconSelect.updateItems(items);
if (_audioPaletteIconSelect) _audioPaletteIconSelect.updateItems(items);
}
/** Render the user-created gradient list below the save button. */
@@ -1209,49 +1193,34 @@ const _typeHandlers: Record<string, { load: (...args: any[]) => any; reset: (...
},
gradient: {
load(css) {
const presetId = css.gradient_id || '';
(document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value = presetId;
if (_gradientPresetIconSelect) _gradientPresetIconSelect.setValue(presetId);
// If gradient_id is set, load stops from the gradient entity
let stops = css.stops || [
{ position: 0.0, color: [255, 0, 0] },
{ position: 1.0, color: [0, 0, 255] },
];
if (presetId) {
const g = _findGradient(presetId);
if (g) stops = g.stops;
}
gradientInit(stops);
const gradientId = css.gradient_id || '';
_ensureGradientPresetIconSelect();
(document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value = gradientId;
if (_gradientPresetIconSelect) _gradientPresetIconSelect.setValue(gradientId);
_loadAnimationState(css.animation);
(document.getElementById('css-editor-gradient-easing') as HTMLSelectElement).value = css.easing || 'linear';
if (_gradientEasingIconSelect) _gradientEasingIconSelect.setValue(css.easing || 'linear');
},
reset() {
(document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value = '';
if (_gradientPresetIconSelect) _gradientPresetIconSelect.setValue('');
gradientInit([
{ position: 0.0, color: [255, 0, 0] },
{ position: 1.0, color: [0, 0, 255] },
]);
_ensureGradientPresetIconSelect();
// Default to first gradient
const gradients = _getGradients();
const defaultId = gradients.length > 0 ? gradients[0].id : '';
(document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value = defaultId;
if (_gradientPresetIconSelect) _gradientPresetIconSelect.setValue(defaultId);
_loadAnimationState(null);
(document.getElementById('css-editor-gradient-easing') as HTMLSelectElement).value = 'linear';
if (_gradientEasingIconSelect) _gradientEasingIconSelect.setValue('linear');
},
getPayload(name) {
const gStops = getGradientStops();
if (gStops.length < 2) {
cssEditorModal.showError(t('color_strip.gradient.min_stops'));
const gradientId = (document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value;
if (!gradientId) {
cssEditorModal.showError(t('color_strip.gradient.error.no_gradient'));
return null;
}
const gradientId = (document.getElementById('css-editor-gradient-preset') as HTMLInputElement).value || null;
return {
name,
gradient_id: gradientId,
stops: gStops.map(s => ({
position: s.position,
color: s.color,
...(s.colorRight ? { color_right: s.colorRight } : {}),
})),
animation: _getAnimationPayload(),
easing: (document.getElementById('css-editor-gradient-easing') as HTMLSelectElement).value,
};