From e394b55cfd1ea0a1b6f3755332faf6df76cdf73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Mon, 27 Apr 2026 17:39:44 +0200 Subject: [PATCH] Datumfels Focus verbessert --- .../dist/sternwarte-card.js | 116 ++++++++++++++++-- 1 file changed, 106 insertions(+), 10 deletions(-) diff --git a/sternwarte-homeassistant-card/dist/sternwarte-card.js b/sternwarte-homeassistant-card/dist/sternwarte-card.js index 141d963..1b9e8f1 100644 --- a/sternwarte-homeassistant-card/dist/sternwarte-card.js +++ b/sternwarte-homeassistant-card/dist/sternwarte-card.js @@ -15,6 +15,15 @@ const DEFAULT_ENTITIES = { }; class SternwarteCard extends HTMLElement { + constructor() { + super(); + this._scheduleInputState = { + open: { draft: "", editing: false, pending: false }, + close: { draft: "", editing: false, pending: false }, + }; + this._pendingRender = false; + } + connectedCallback() { this._ensureClockTimer(); } @@ -36,7 +45,7 @@ class SternwarteCard extends HTMLElement { set hass(hass) { this._hass = hass; this._ensureClockTimer(); - this.render(); + this._requestRender(); } getCardSize() { @@ -58,10 +67,73 @@ class SternwarteCard extends HTMLElement { _ensureClockTimer() { if (this._clockTimer) return; this._clockTimer = window.setInterval(() => { - if (this._hass) this.render(); + if (this._hass) this._requestRender(); }, 30000); } + _requestRender() { + if (this._isScheduleEditing()) { + this._pendingRender = true; + return; + } + this._pendingRender = false; + this.render(); + } + + _isScheduleEditing() { + return Object.values(this._scheduleInputState).some((field) => field.editing); + } + + _scheduleFieldState(key) { + return this._scheduleInputState[key]; + } + + _scheduleInputValue(key, fallbackState) { + const field = this._scheduleFieldState(key); + if (field.draft) return field.draft; + return this._isoForInput(fallbackState); + } + + _resetScheduleDrafts() { + for (const field of Object.values(this._scheduleInputState)) { + field.draft = ""; + field.editing = false; + field.pending = false; + } + } + + _beginScheduleEdit(key, fallbackState) { + const field = this._scheduleFieldState(key); + field.editing = true; + field.pending = false; + if (!field.draft) { + field.draft = this._isoForInput(fallbackState); + } + } + + _updateScheduleDraft(key, value) { + const field = this._scheduleFieldState(key); + field.draft = value; + field.pending = false; + } + + _endScheduleEdit(key, event) { + const field = this._scheduleFieldState(key); + field.editing = false; + if (!this._isScheduleEditing() && this._pendingRender) { + this._requestRender(); + } + } + + _bindScheduleInput(key, inputId, fallbackState) { + const input = this.shadowRoot.getElementById(inputId); + if (!input) return; + input.addEventListener("focus", () => this._beginScheduleEdit(key, fallbackState)); + input.addEventListener("input", (event) => this._updateScheduleDraft(key, event.target.value)); + input.addEventListener("change", (event) => this._updateScheduleDraft(key, event.target.value)); + input.addEventListener("blur", (event) => this._endScheduleEdit(key, event)); + } + _firstExistingEntityId(entityIds) { for (const entityId of entityIds) { if (entityId && this._state(entityId)) return entityId; @@ -128,14 +200,22 @@ class SternwarteCard extends HTMLElement { }); } - _setDateTime(entityId, inputId) { + _setDateTime(entityId, inputId, key) { const input = this.shadowRoot.getElementById(inputId); - if (!input || !input.value) return; + const field = this._scheduleFieldState(key); + const value = field?.draft || input?.value || ""; + if (!value) return; if (!entityId) return; + field.pending = true; + field.editing = false; + field.draft = value; this._hass.callService("datetime", "set_value", { entity_id: entityId, - datetime: input.value, + datetime: value, }); + if (this._pendingRender) { + this._requestRender(); + } } _isoForInput(state) { @@ -527,6 +607,16 @@ class SternwarteCard extends HTMLElement { const closeScheduleEntityId = this._scheduleCloseEntityId(); const openSchedule = this._state(openScheduleEntityId); const closeSchedule = this._state(closeScheduleEntityId); + const openInputValue = this._scheduleInputValue("open", openSchedule); + const closeInputValue = this._scheduleInputValue("close", closeSchedule); + if (openInputValue === this._isoForInput(openSchedule)) { + this._scheduleFieldState("open").draft = ""; + this._scheduleFieldState("open").pending = false; + } + if (closeInputValue === this._isoForInput(closeSchedule)) { + this._scheduleFieldState("close").draft = ""; + this._scheduleFieldState("close").pending = false; + } const roofPosition = this._roofPositionValue(); const windIndicator = this._windIndicatorState(); const rainOn = rain?.state === "on"; @@ -1040,11 +1130,11 @@ class SternwarteCard extends HTMLElement {
- +
- +
@@ -1062,9 +1152,15 @@ class SternwarteCard extends HTMLElement { this._bindClick("power-on-btn", () => this._callEntity("switch", "turn_on", powerEntityId)); this._bindClick("power-off-btn", () => this._callEntity("switch", "turn_off", powerEntityId)); this._bindClick("nautical-btn", () => this._call("sternwarte", "set_nautical_schedule")); - this._bindClick("clear-schedule-btn", () => this._call("sternwarte", "clear_schedule")); - this._bindClick("open-schedule-btn", () => this._setDateTime(openScheduleEntityId, "open-schedule-input")); - this._bindClick("close-schedule-btn", () => this._setDateTime(closeScheduleEntityId, "close-schedule-input")); + this._bindClick("clear-schedule-btn", () => { + this._resetScheduleDrafts(); + this._call("sternwarte", "clear_schedule"); + this._requestRender(); + }); + this._bindClick("open-schedule-btn", () => this._setDateTime(openScheduleEntityId, "open-schedule-input", "open")); + this._bindClick("close-schedule-btn", () => this._setDateTime(closeScheduleEntityId, "close-schedule-input", "close")); + this._bindScheduleInput("open", "open-schedule-input", openSchedule); + this._bindScheduleInput("close", "close-schedule-input", closeSchedule); } }