This commit is contained in:
Mateusz Gruszczyński
2026-09-01 09:19:33 +02:00
parent ac5a464d96
commit 1a5c1305dc
20 changed files with 200 additions and 42 deletions
+68 -3
View File
@@ -69,8 +69,9 @@ async function sendZoneControl(id, patch) {
}
}
function queueZoneTemperature(zone, value) {
const next = Math.round(clamp(value, 8, 30) * 2) / 2;
function queueZoneTemperature(zone, value, {snapToHalf=true}={}) {
const clamped = clamp(value, 8, 30);
const next = snapToHalf ? Math.round(clamped * 2) / 2 : Math.round(clamped * 10) / 10;
zone.manual_setpoint = next;
zone.setpoint = next;
zone.effective_setpoint = next;
@@ -79,6 +80,49 @@ function queueZoneTemperature(zone, value) {
app.zoneTemperatureTimers[zone.id] = setTimeout(() => sendZoneControl(zone.id, {setpoint: next}), 160);
}
function beginInlineTemperatureEdit(target) {
if (!target || target.querySelector('input') || target.dataset.editable === 'false') return;
const kind = target.dataset.temperatureKind;
const id = target.dataset.id;
const value = parseDecimal(target.dataset.value);
if (!Number.isFinite(value) || !kind || !id) return;
const decimals = kind === 'zone' ? 1 : 0;
const input = document.createElement('input');
input.className = 'inline-temperature-input';
input.type = 'text';
input.inputMode = 'decimal';
input.value = value.toFixed(decimals);
input.setAttribute('aria-label', tr('common.targetTemperature'));
target.classList.add('editing');
target.replaceChildren(input);
input.focus();
input.select();
let finished = false;
const finish = async commit => {
if (finished) return;
finished = true;
const parsed = parseDecimal(input.value);
if (!commit || !Number.isFinite(parsed) || parsed < 8 || parsed > 30) {
if (commit && (!Number.isFinite(parsed) || parsed < 8 || parsed > 30)) toast(tr('validation.range', {min:8, max:30}), true);
renderAll();
return;
}
if (kind === 'zone') {
const zone = app.zones.find(item => item.id === id);
if (zone) queueZoneTemperature(zone, parsed, {snapToHalf:false});
return;
}
const device = app.devices.find(item => item.id === id);
if (device) await sendDeviceCommand(id, {target_temperature:Math.round(clamp(parsed, 8, 30))});
};
input.addEventListener('keydown', event => {
if (event.key === 'Enter') { event.preventDefault(); input.blur(); }
if (event.key === 'Escape') { event.preventDefault(); finished = true; renderAll(); }
});
input.addEventListener('blur', () => finish(true), {once:true});
}
function showDiscoveryNames(ids) {
const wanted = new Set(Array.isArray(ids) ? ids : []);
const devices = app.devices.filter(device => wanted.has(device.id));
@@ -115,6 +159,22 @@ function openDialog(id) {
}
}
function updateZoneHysteresisFields({syncFromCommon=false}={}) {
const form = $('#zoneForm');
if (!form) return;
const separate = !!form.separate_hysteresis?.checked;
$('#commonHysteresisField').hidden = separate;
$('#separateHysteresisFields').hidden = !separate;
if (separate && syncFromCommon && form.dataset.separateHysteresisInitialized !== 'true') {
const common = parseDecimal(form.hysteresis.value);
if (Number.isFinite(common)) {
form.cool_hysteresis.value = String(common);
form.heat_hysteresis.value = String(common);
}
form.dataset.separateHysteresisInitialized = 'true';
}
}
function updateZoneSensorFields() {
const form = $('#zoneForm');
if (!form) return;
@@ -167,7 +227,12 @@ function populateZone(id) {
form.min_adjust_seconds.value = Number(item.min_adjust_seconds ?? 120);
form.standby_offset_c.value = Number(item.standby_offset_c ?? 2);
form.smart_fan.checked = item.smart_fan !== false;
form.enabled.checked = item.enabled; updateZoneSensorFields(); openDialog('zoneDialog');
form.separate_hysteresis.checked = item.separate_hysteresis === true;
const commonHysteresis = Number(item.hysteresis ?? 0.6);
form.cool_hysteresis.value = Number(item.separate_hysteresis ? (item.cool_hysteresis ?? commonHysteresis) : commonHysteresis);
form.heat_hysteresis.value = Number(item.separate_hysteresis ? (item.heat_hysteresis ?? commonHysteresis) : commonHysteresis);
form.dataset.separateHysteresisInitialized = item.separate_hysteresis === true ? 'true' : 'false';
form.enabled.checked = item.enabled; updateZoneSensorFields(); updateZoneHysteresisFields(); openDialog('zoneDialog');
}
const dateTimeLocalValue = value => {