Add LEDDeviceProvider abstraction and standby capability flag
Consolidate all device-type-specific logic into LEDDeviceProvider ABC with provider registry. WLEDDeviceProvider handles client creation, health checks, validation, mDNS discovery, and brightness control. Routes now delegate to providers instead of using if/else type checks. Add standby_required capability and expose device capabilities in API. Target editor conditionally shows standby interval based on selected device's capabilities. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -873,6 +873,8 @@ async function fetchDeviceBrightness(deviceId) {
|
||||
}
|
||||
|
||||
// Add device modal
|
||||
let _discoveryScanRunning = false;
|
||||
|
||||
function showAddDevice() {
|
||||
const modal = document.getElementById('add-device-modal');
|
||||
const form = document.getElementById('add-device-form');
|
||||
@@ -892,6 +894,8 @@ function showAddDevice() {
|
||||
modal.style.display = 'flex';
|
||||
lockBody();
|
||||
setTimeout(() => document.getElementById('device-name').focus(), 100);
|
||||
// Auto-start discovery on open
|
||||
scanForDevices();
|
||||
}
|
||||
|
||||
function closeAddDeviceModal() {
|
||||
@@ -901,6 +905,9 @@ function closeAddDeviceModal() {
|
||||
}
|
||||
|
||||
async function scanForDevices() {
|
||||
if (_discoveryScanRunning) return;
|
||||
_discoveryScanRunning = true;
|
||||
|
||||
const loading = document.getElementById('discovery-loading');
|
||||
const list = document.getElementById('discovery-list');
|
||||
const empty = document.getElementById('discovery-empty');
|
||||
@@ -962,6 +969,8 @@ async function scanForDevices() {
|
||||
empty.style.display = 'block';
|
||||
empty.querySelector('small').textContent = t('device.scan.error');
|
||||
console.error('Device scan failed:', err);
|
||||
} finally {
|
||||
_discoveryScanRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3906,6 +3915,15 @@ function closePPTemplateModal() {
|
||||
|
||||
// ===== TARGET EDITOR MODAL =====
|
||||
let targetEditorInitialValues = {};
|
||||
let _targetEditorDevices = []; // cached devices list for capability checks
|
||||
|
||||
function _updateStandbyVisibility() {
|
||||
const deviceSelect = document.getElementById('target-editor-device');
|
||||
const standbyGroup = document.getElementById('target-editor-standby-group');
|
||||
const selectedDevice = _targetEditorDevices.find(d => d.id === deviceSelect.value);
|
||||
const caps = selectedDevice?.capabilities || [];
|
||||
standbyGroup.style.display = caps.includes('standby_required') ? '' : 'none';
|
||||
}
|
||||
|
||||
async function showTargetEditor(targetId = null) {
|
||||
try {
|
||||
@@ -3917,6 +3935,7 @@ async function showTargetEditor(targetId = null) {
|
||||
|
||||
const devices = devicesResp.ok ? (await devicesResp.json()).devices || [] : [];
|
||||
const sources = sourcesResp.ok ? (await sourcesResp.json()).streams || [] : [];
|
||||
_targetEditorDevices = devices;
|
||||
|
||||
// Populate device select
|
||||
const deviceSelect = document.getElementById('target-editor-device');
|
||||
@@ -3929,6 +3948,7 @@ async function showTargetEditor(targetId = null) {
|
||||
opt.textContent = `${d.name} [${devType}]${shortUrl ? ' (' + shortUrl + ')' : ''}`;
|
||||
deviceSelect.appendChild(opt);
|
||||
});
|
||||
deviceSelect.onchange = _updateStandbyVisibility;
|
||||
|
||||
// Populate source select
|
||||
const sourceSelect = document.getElementById('target-editor-source');
|
||||
@@ -3975,6 +3995,9 @@ async function showTargetEditor(targetId = null) {
|
||||
document.getElementById('target-editor-title').textContent = t('targets.add');
|
||||
}
|
||||
|
||||
// Show/hide standby interval based on selected device capabilities
|
||||
_updateStandbyVisibility();
|
||||
|
||||
targetEditorInitialValues = {
|
||||
name: document.getElementById('target-editor-name').value,
|
||||
device: deviceSelect.value,
|
||||
|
||||
Reference in New Issue
Block a user