Reload controls after menu/boolean/button change

Switching a menu control (e.g. exposure auto → manual) changes the
flags on related controls (e.g. exposure_absolute loses FLAG_GRABBED).
Re-fetch and re-render controls silently after any non-slider change so
the updated enabled/read-only states are reflected immediately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-27 01:48:51 +00:00
parent d6b6b0042d
commit ab47729d74

View File

@@ -35,9 +35,10 @@ const CTRL_CLASSES = [
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
const known_peers = new Map(); /* key: addr:name -> peer */ const known_peers = new Map(); /* key: addr:name -> peer */
let selected_peer = null; let selected_peer = null;
let selected_device_idx = null; let selected_device_idx = null;
let device_data = null; let selected_device_path = null;
let device_data = null;
/* ------------------------------------------------------------------------- /* -------------------------------------------------------------------------
* Utilities * Utilities
@@ -244,7 +245,8 @@ function make_device_item(idx, path, label, device_caps, is_capture) {
} }
async function select_device(idx, path) { async function select_device(idx, path) {
selected_device_idx = idx; selected_device_idx = idx;
selected_device_path = path;
document.querySelectorAll('.device-item').forEach(el => { document.querySelectorAll('.device-item').forEach(el => {
el.classList.toggle('selected', parseInt(el.dataset.idx) === idx); el.classList.toggle('selected', parseInt(el.dataset.idx) === idx);
}); });
@@ -272,6 +274,20 @@ async function load_controls(device_idx, device_path) {
} }
} }
/* Silent reload — no loading flash; used after a control change that may
* alter other controls' flags (e.g. switching exposure mode ungrabs
* exposure_absolute). */
async function reload_controls() {
if (selected_device_idx === null || selected_device_path === null) { return; }
try {
const result = await api('GET', `/api/devices/${selected_device_idx}/controls`);
by_id('controls-title').textContent = `Controls — ${selected_device_path}`;
render_controls(selected_device_idx, result.controls ?? []);
} catch (err) {
toast(err.message, 'err');
}
}
function render_controls(device_idx, controls) { function render_controls(device_idx, controls) {
const scroll = by_id('controls-scroll'); const scroll = by_id('controls-scroll');
@@ -377,10 +393,10 @@ function make_ctrl_row(device_idx, ctrl) {
}; };
if (ctrl.type === CTRL_BUTTON) { if (ctrl.type === CTRL_BUTTON) {
input_el.addEventListener('click', send); input_el.addEventListener('click', async () => { await send(); await reload_controls(); });
} else if (ctrl.type === CTRL_BOOLEAN || ctrl.type === CTRL_MENU } else if (ctrl.type === CTRL_BOOLEAN || ctrl.type === CTRL_MENU
|| ctrl.type === CTRL_INTEGER_MENU) { || ctrl.type === CTRL_INTEGER_MENU) {
input_el.addEventListener('change', send); input_el.addEventListener('change', async () => { await send(); await reload_controls(); });
} else { } else {
input_el.addEventListener('pointerup', send); input_el.addEventListener('pointerup', send);
input_el.addEventListener('keyup', send); input_el.addEventListener('keyup', send);