mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-11 03:09:57 +00:00
Address review: sparse overrides, hfov clear, readout prune
Three fixes from PR review of the per-pane tuner: - Sync no longer writes back. _syncAspectPanel dispatches synthetic input events to refresh slider labels; guard those with _aspectSyncing so the slider handler skips the write. Previously opening/switching a target populated a full override for every field (defeating sparse inherit) and spammed localStorage. - Unchecking "Override held hFOV" on a pane target now clears the override key (via _aspectClearVal) so the pane re-inherits the base value, instead of pinning hfovDeg:null in the override. On the base target it still sets the explicit auto (null). - _aspectPrunePanes now prunes the matching __h3dAspectReadout slot and drops a dangling __last, so the readout cache can't grow unbounded as songs and arrangements churn. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: topkoa <topkoa@gmail.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
5ef163e9f9
commit
9f914770c6
@@ -1773,11 +1773,23 @@
|
||||
const reg = window.__h3dAspectPanes;
|
||||
if (!reg) return;
|
||||
const now = _aspectNowMs();
|
||||
const ro = window.__h3dAspectReadout;
|
||||
Object.keys(reg).forEach((k) => {
|
||||
if (now - (reg[k].seen || 0) > 1500) { delete reg[k]; _aspectPanesDirty = true; }
|
||||
if (now - (reg[k].seen || 0) > 1500) {
|
||||
delete reg[k];
|
||||
// Prune the matching readout slot so it can't grow unbounded as
|
||||
// songs/arrangements churn, and drop a dangling __last pointer.
|
||||
if (ro) { delete ro[k]; if (ro.__last === k) delete ro.__last; }
|
||||
_aspectPanesDirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// True while _syncAspectPanel is programmatically refreshing controls, so the
|
||||
// synthetic 'input' events it dispatches to update labels don't write back
|
||||
// into the tune (which would populate a full override for every field and
|
||||
// spam localStorage). Real user input runs with this false.
|
||||
let _aspectSyncing = false;
|
||||
// Read/write against the current edit target ('' → base, else pane override).
|
||||
function _aspectReadVal(k) {
|
||||
const base = _aspectTune();
|
||||
@@ -1794,6 +1806,18 @@
|
||||
}
|
||||
_aspectPersist();
|
||||
}
|
||||
// Clear a field: for the base target set the explicit auto value (null); for a
|
||||
// pane target delete the override key so the pane re-inherits the base value
|
||||
// (and drop the pane's override object once it's empty).
|
||||
function _aspectClearVal(k) {
|
||||
const base = _aspectTune();
|
||||
if (!_aspectEditTarget) { base[k] = null; }
|
||||
else {
|
||||
const m = base.__panels, ov = m && m[_aspectEditTarget];
|
||||
if (ov) { delete ov[k]; if (!Object.keys(ov).length) delete m[_aspectEditTarget]; }
|
||||
}
|
||||
_aspectPersist();
|
||||
}
|
||||
|
||||
// (Re)build the Target dropdown from the live pane registry, preserving the
|
||||
// current selection when it's still valid.
|
||||
@@ -1892,7 +1916,8 @@
|
||||
const show = () => { val.textContent = (+sl.value).toFixed(f.step < 1 ? 2 : 0); };
|
||||
show();
|
||||
sl.addEventListener('input', () => {
|
||||
_aspectWriteVal(f.k, parseFloat(sl.value)); show();
|
||||
show(); // label always refreshes
|
||||
if (!_aspectSyncing) _aspectWriteVal(f.k, parseFloat(sl.value));
|
||||
});
|
||||
row.appendChild(sl); wrap.appendChild(row);
|
||||
});
|
||||
@@ -1913,11 +1938,13 @@
|
||||
sl.disabled = !cb.checked;
|
||||
sl.style.cssText = 'width:100%;';
|
||||
cb.addEventListener('change', () => {
|
||||
if (_aspectSyncing) return;
|
||||
sl.disabled = !cb.checked;
|
||||
_aspectWriteVal('hfovDeg', cb.checked ? parseFloat(sl.value) : null);
|
||||
if (cb.checked) _aspectWriteVal('hfovDeg', parseFloat(sl.value));
|
||||
else _aspectClearVal('hfovDeg'); // base → auto (null); pane → re-inherit base
|
||||
});
|
||||
sl.addEventListener('input', () => {
|
||||
if (cb.checked) _aspectWriteVal('hfovDeg', parseFloat(sl.value));
|
||||
if (!_aspectSyncing && cb.checked) _aspectWriteVal('hfovDeg', parseFloat(sl.value));
|
||||
});
|
||||
row.appendChild(sl); wrap.appendChild(row);
|
||||
_aspectHfovCb = cb; _aspectHfovSl = sl;
|
||||
@@ -1972,19 +1999,27 @@
|
||||
function _syncAspectPanel() {
|
||||
if (!_aspectPanelEl) return;
|
||||
_aspectBuildTargets();
|
||||
_aspectPanelEl.querySelectorAll('input[type=checkbox][data-k]').forEach((cb) => {
|
||||
cb.checked = !!_aspectReadVal(cb.dataset.k);
|
||||
});
|
||||
_aspectPanelEl.querySelectorAll('input[type=range][data-k]').forEach((sl) => {
|
||||
const v = _aspectReadVal(sl.dataset.k);
|
||||
if (Number.isFinite(v)) sl.value = v;
|
||||
sl.dispatchEvent(new Event('input')); // refresh the value label
|
||||
});
|
||||
if (_aspectHfovCb) {
|
||||
const hv = _aspectReadVal('hfovDeg');
|
||||
_aspectHfovCb.checked = Number.isFinite(hv);
|
||||
_aspectHfovSl.disabled = !_aspectHfovCb.checked;
|
||||
if (Number.isFinite(hv)) _aspectHfovSl.value = hv;
|
||||
// Guard so the synthetic 'input' events below only refresh labels and
|
||||
// don't write the read-back values into the target (which would turn a
|
||||
// sparse pane override into a full one and spam localStorage).
|
||||
_aspectSyncing = true;
|
||||
try {
|
||||
_aspectPanelEl.querySelectorAll('input[type=checkbox][data-k]').forEach((cb) => {
|
||||
cb.checked = !!_aspectReadVal(cb.dataset.k);
|
||||
});
|
||||
_aspectPanelEl.querySelectorAll('input[type=range][data-k]').forEach((sl) => {
|
||||
const v = _aspectReadVal(sl.dataset.k);
|
||||
if (Number.isFinite(v)) sl.value = v;
|
||||
sl.dispatchEvent(new Event('input')); // refresh the value label only
|
||||
});
|
||||
if (_aspectHfovCb) {
|
||||
const hv = _aspectReadVal('hfovDeg');
|
||||
_aspectHfovCb.checked = Number.isFinite(hv);
|
||||
_aspectHfovSl.disabled = !_aspectHfovCb.checked;
|
||||
if (Number.isFinite(hv)) _aspectHfovSl.value = hv;
|
||||
}
|
||||
} finally {
|
||||
_aspectSyncing = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user