feat: use IconSelect grid for frequency band selector in band extract editor
Some checks failed
Lint & Test / test (push) Failing after 1m1s

Replace plain HTML select with icon grid picker (bass/mid/treble/custom)
using volume, music, zap, and sliders icons for visual differentiation.
This commit is contained in:
2026-03-24 19:59:55 +03:00
parent c1940dadb7
commit d6f796a499
3 changed files with 34 additions and 4 deletions

View File

@@ -148,7 +148,7 @@ import {
showAudioSourceModal, closeAudioSourceModal, saveAudioSource, showAudioSourceModal, closeAudioSourceModal, saveAudioSource,
editAudioSource, cloneAudioSource, deleteAudioSource, editAudioSource, cloneAudioSource, deleteAudioSource,
testAudioSource, closeTestAudioSourceModal, testAudioSource, closeTestAudioSourceModal,
refreshAudioDevices, onBandPresetChange, refreshAudioDevices,
} from './features/audio-sources.ts'; } from './features/audio-sources.ts';
// Layer 5: value sources // Layer 5: value sources
@@ -474,7 +474,6 @@ Object.assign(window, {
testAudioSource, testAudioSource,
closeTestAudioSourceModal, closeTestAudioSourceModal,
refreshAudioDevices, refreshAudioDevices,
onBandPresetChange,
// value sources // value sources
showValueSourceModal, showValueSourceModal,

View File

@@ -18,7 +18,9 @@ import { showToast, showConfirm, lockBody, unlockBody } from '../core/ui.ts';
import { Modal } from '../core/modal.ts'; import { Modal } from '../core/modal.ts';
import { ICON_MUSIC, getAudioSourceIcon, ICON_AUDIO_TEMPLATE, ICON_AUDIO_INPUT, ICON_AUDIO_LOOPBACK } from '../core/icons.ts'; import { ICON_MUSIC, getAudioSourceIcon, ICON_AUDIO_TEMPLATE, ICON_AUDIO_INPUT, ICON_AUDIO_LOOPBACK } from '../core/icons.ts';
import { EntitySelect } from '../core/entity-palette.ts'; import { EntitySelect } from '../core/entity-palette.ts';
import { IconSelect } from '../core/icon-select.ts';
import { TagInput } from '../core/tag-input.ts'; import { TagInput } from '../core/tag-input.ts';
import * as P from '../core/icon-paths.ts';
import { loadPictureSources } from './streams.ts'; import { loadPictureSources } from './streams.ts';
let _audioSourceTagsInput: TagInput | null = null; let _audioSourceTagsInput: TagInput | null = null;
@@ -50,11 +52,23 @@ class AudioSourceModal extends Modal {
const audioSourceModal = new AudioSourceModal(); const audioSourceModal = new AudioSourceModal();
// ── EntitySelect instances for audio source editor ── // ── EntitySelect / IconSelect instances for audio source editor ──
let _asTemplateEntitySelect: EntitySelect | null = null; let _asTemplateEntitySelect: EntitySelect | null = null;
let _asDeviceEntitySelect: EntitySelect | null = null; let _asDeviceEntitySelect: EntitySelect | null = null;
let _asParentEntitySelect: EntitySelect | null = null; let _asParentEntitySelect: EntitySelect | null = null;
let _asBandParentEntitySelect: EntitySelect | null = null; let _asBandParentEntitySelect: EntitySelect | null = null;
let _asBandIconSelect: IconSelect | null = null;
const _svg = (d: string): string => `<svg class="icon" viewBox="0 0 24 24">${d}</svg>`;
function _buildBandItems() {
return [
{ value: 'bass', icon: _svg(P.volume2), label: t('audio_source.band.bass'), desc: '20250 Hz' },
{ value: 'mid', icon: _svg(P.music), label: t('audio_source.band.mid'), desc: '2504000 Hz' },
{ value: 'treble', icon: _svg(P.zap), label: t('audio_source.band.treble'), desc: '4k20k Hz' },
{ value: 'custom', icon: _svg(P.slidersHorizontal), label: t('audio_source.band.custom') },
];
}
// ── Modal ───────────────────────────────────────────────────── // ── Modal ─────────────────────────────────────────────────────
@@ -94,6 +108,7 @@ export async function showAudioSourceModal(sourceType: any, editData?: any) {
} else if (editData.source_type === 'band_extract') { } else if (editData.source_type === 'band_extract') {
_loadBandParentSources(editData.audio_source_id); _loadBandParentSources(editData.audio_source_id);
(document.getElementById('audio-source-band') as HTMLSelectElement).value = editData.band || 'bass'; (document.getElementById('audio-source-band') as HTMLSelectElement).value = editData.band || 'bass';
_ensureBandIconSelect();
(document.getElementById('audio-source-freq-low') as HTMLInputElement).value = String(editData.freq_low ?? 20); (document.getElementById('audio-source-freq-low') as HTMLInputElement).value = String(editData.freq_low ?? 20);
(document.getElementById('audio-source-freq-high') as HTMLInputElement).value = String(editData.freq_high ?? 20000); (document.getElementById('audio-source-freq-high') as HTMLInputElement).value = String(editData.freq_high ?? 20000);
onBandPresetChange(); onBandPresetChange();
@@ -111,6 +126,7 @@ export async function showAudioSourceModal(sourceType: any, editData?: any) {
} else if (sourceType === 'band_extract') { } else if (sourceType === 'band_extract') {
_loadBandParentSources(); _loadBandParentSources();
(document.getElementById('audio-source-band') as HTMLSelectElement).value = 'bass'; (document.getElementById('audio-source-band') as HTMLSelectElement).value = 'bass';
_ensureBandIconSelect();
(document.getElementById('audio-source-freq-low') as HTMLInputElement).value = '20'; (document.getElementById('audio-source-freq-low') as HTMLInputElement).value = '20';
(document.getElementById('audio-source-freq-high') as HTMLInputElement).value = '20000'; (document.getElementById('audio-source-freq-high') as HTMLInputElement).value = '20000';
onBandPresetChange(); onBandPresetChange();
@@ -357,6 +373,21 @@ function _loadMultichannelSources(selectedId?: any) {
} }
} }
function _ensureBandIconSelect() {
const sel = document.getElementById('audio-source-band') as HTMLSelectElement | null;
if (!sel) return;
if (_asBandIconSelect) {
_asBandIconSelect.updateItems(_buildBandItems());
return;
}
_asBandIconSelect = new IconSelect({
target: sel,
items: _buildBandItems(),
columns: 2,
onChange: () => onBandPresetChange(),
});
}
function _loadBandParentSources(selectedId?: any) { function _loadBandParentSources(selectedId?: any) {
const select = document.getElementById('audio-source-band-parent') as HTMLSelectElement | null; const select = document.getElementById('audio-source-band-parent') as HTMLSelectElement | null;
if (!select) return; if (!select) return;

View File

@@ -99,7 +99,7 @@
<button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button> <button type="button" class="hint-toggle" onclick="toggleHint(this)" title="?" data-i18n-aria-label="aria.hint">?</button>
</div> </div>
<small class="input-hint" style="display:none" data-i18n="audio_source.band.hint">Select a frequency band preset or custom range</small> <small class="input-hint" style="display:none" data-i18n="audio_source.band.hint">Select a frequency band preset or custom range</small>
<select id="audio-source-band" onchange="onBandPresetChange()"> <select id="audio-source-band">
<option value="bass" data-i18n="audio_source.band.bass">Bass (20250 Hz)</option> <option value="bass" data-i18n="audio_source.band.bass">Bass (20250 Hz)</option>
<option value="mid" data-i18n="audio_source.band.mid">Mid (2504000 Hz)</option> <option value="mid" data-i18n="audio_source.band.mid">Mid (2504000 Hz)</option>
<option value="treble" data-i18n="audio_source.band.treble">Treble (400020000 Hz)</option> <option value="treble" data-i18n="audio_source.band.treble">Treble (400020000 Hz)</option>