From b2a9dae5d8df64fea3fbacc6d52e6832e586dc50 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Sun, 9 May 2021 11:35:13 +0200 Subject: [PATCH 1/4] Ensure timer row uses correct state translation keys --- src/panels/lovelace/entity-rows/hui-timer-entity-row.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts index f6238c4e8746..c7e844c392fc 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -126,14 +126,17 @@ class HuiTimerEntityRow extends LitElement { if (stateObj.state === "idle" || this._timeRemaining === 0) { return ( - this.hass!.localize(`state.timer.${stateObj.state}`) || stateObj.state + this.hass!.localize(`component.timer.state._.${stateObj.state}`) || + stateObj.state ); } let display = secondsToDuration(this._timeRemaining || 0); if (stateObj.state === "paused") { - display += ` (${this.hass!.localize("state.timer.paused")})`; + display += ` (${this.hass!.localize( + `component.timer.state._.${stateObj.state}` + )})`; } return display; From c4de695f948415634c281bbda8c489851c5c88fc Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Mon, 10 May 2021 13:24:35 +0200 Subject: [PATCH 2/4] Changes from review --- .../entity-rows/hui-timer-entity-row.ts | 16 ++++++---- src/state-summary/state-card-timer.js | 29 ++++++++++++++++--- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts index c7e844c392fc..a4160366e016 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -2,13 +2,14 @@ import { HassEntity } from "home-assistant-js-websocket"; import { customElement, html, - state, LitElement, property, PropertyValues, + state, TemplateResult, } from "lit-element"; import secondsToDuration from "../../../common/datetime/seconds_to_duration"; +import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { timerTimeRemaining } from "../../../common/entity/timer_time_remaining"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; @@ -125,17 +126,20 @@ class HuiTimerEntityRow extends LitElement { } if (stateObj.state === "idle" || this._timeRemaining === 0) { - return ( - this.hass!.localize(`component.timer.state._.${stateObj.state}`) || - stateObj.state + return computeStateDisplay( + this.hass!.localize, + stateObj, + this.hass!.locale ); } let display = secondsToDuration(this._timeRemaining || 0); if (stateObj.state === "paused") { - display += ` (${this.hass!.localize( - `component.timer.state._.${stateObj.state}` + display += ` (${computeStateDisplay( + this.hass!.localize, + stateObj, + this.hass!.locale )})`; } diff --git a/src/state-summary/state-card-timer.js b/src/state-summary/state-card-timer.js index 17d39fde5c22..2b5917b371da 100644 --- a/src/state-summary/state-card-timer.js +++ b/src/state-summary/state-card-timer.js @@ -5,6 +5,7 @@ import { PolymerElement } from "@polymer/polymer/polymer-element"; import secondsToDuration from "../common/datetime/seconds_to_duration"; import { timerTimeRemaining } from "../common/entity/timer_time_remaining"; import "../components/entity/state-info"; +import { computeStateDisplay } from "../common/entity/compute_state_display"; class StateCardTimer extends PolymerElement { static get template() { @@ -18,6 +19,7 @@ class StateCardTimer extends PolymerElement { margin-left: 16px; text-align: right; line-height: 40px; + white-space: nowrap; } @@ -90,10 +92,29 @@ class StateCardTimer extends PolymerElement { this.timeRemaining = timerTimeRemaining(stateObj); } - _displayState(time, stateObj) { - return time - ? secondsToDuration(time) - : this.hass.localize(`state.timer.${stateObj.state}`) || stateObj.state; + _displayState(timeRemaining, stateObj) { + if (!stateObj) { + return null; + } + + if (stateObj.state === "idle" || timeRemaining === 0) { + return computeStateDisplay( + this.hass.localize, + stateObj, + this.hass.locale + ); + } + + let display = secondsToDuration(timeRemaining || 0); + + if (stateObj.state === "paused") { + display += + " (" + + computeStateDisplay(this.hass.localize, stateObj, this.hass.locale) + + ")"; + } + + return display; } } customElements.define("state-card-timer", StateCardTimer); From d5eca0badf81017e1469808ea9fb1cfccf886aca Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Sun, 16 May 2021 08:55:17 +0200 Subject: [PATCH 3/4] Update src/panels/lovelace/entity-rows/hui-timer-entity-row.ts Co-authored-by: Bram Kragten --- src/panels/lovelace/entity-rows/hui-timer-entity-row.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts index a4160366e016..12a3fa64a826 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -136,7 +136,7 @@ class HuiTimerEntityRow extends LitElement { let display = secondsToDuration(this._timeRemaining || 0); if (stateObj.state === "paused") { - display += ` (${computeStateDisplay( + display = `${display} (${computeStateDisplay( this.hass!.localize, stateObj, this.hass!.locale From 3982aa33e722af17ebf4324e674198f87cce4051 Mon Sep 17 00:00:00 2001 From: Philip Allgaier Date: Fri, 21 May 2021 20:23:53 +0200 Subject: [PATCH 4/4] Move logic to data/timer --- src/common/entity/timer_time_remaining.ts | 19 -------- src/components/entity/ha-state-label-badge.ts | 2 +- src/data/timer.ts | 47 +++++++++++++++++++ .../entity-rows/hui-timer-entity-row.ts | 34 ++------------ src/state-summary/state-card-timer.js | 27 +---------- .../entity/timer_time_remaining_test.ts | 2 +- 6 files changed, 55 insertions(+), 76 deletions(-) delete mode 100644 src/common/entity/timer_time_remaining.ts diff --git a/src/common/entity/timer_time_remaining.ts b/src/common/entity/timer_time_remaining.ts deleted file mode 100644 index 5b2f54654d31..000000000000 --- a/src/common/entity/timer_time_remaining.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { HassEntity } from "home-assistant-js-websocket"; -import durationToSeconds from "../datetime/duration_to_seconds"; - -export const timerTimeRemaining = ( - stateObj: HassEntity -): undefined | number => { - if (!stateObj.attributes.remaining) { - return undefined; - } - let timeRemaining = durationToSeconds(stateObj.attributes.remaining); - - if (stateObj.state === "active") { - const now = new Date().getTime(); - const madeActive = new Date(stateObj.last_changed).getTime(); - timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0); - } - - return timeRemaining; -}; diff --git a/src/components/entity/ha-state-label-badge.ts b/src/components/entity/ha-state-label-badge.ts index 7bed0b3002a0..eaa8f89c5301 100644 --- a/src/components/entity/ha-state-label-badge.ts +++ b/src/components/entity/ha-state-label-badge.ts @@ -15,7 +15,7 @@ import { computeStateDomain } from "../../common/entity/compute_state_domain"; import { computeStateName } from "../../common/entity/compute_state_name"; import { domainIcon } from "../../common/entity/domain_icon"; import { stateIcon } from "../../common/entity/state_icon"; -import { timerTimeRemaining } from "../../common/entity/timer_time_remaining"; +import { timerTimeRemaining } from "../../data/timer"; import { formatNumber } from "../../common/string/format_number"; import { UNAVAILABLE, UNKNOWN } from "../../data/entity"; import { HomeAssistant } from "../../types"; diff --git a/src/data/timer.ts b/src/data/timer.ts index a963d64ea38b..cff601b60abb 100644 --- a/src/data/timer.ts +++ b/src/data/timer.ts @@ -1,7 +1,11 @@ import { + HassEntity, HassEntityAttributeBase, HassEntityBase, } from "home-assistant-js-websocket"; +import durationToSeconds from "../common/datetime/duration_to_seconds"; +import secondsToDuration from "../common/datetime/seconds_to_duration"; +import { computeStateDisplay } from "../common/entity/compute_state_display"; import { HomeAssistant } from "../types"; export type TimerEntity = HassEntityBase & { @@ -55,3 +59,46 @@ export const deleteTimer = (hass: HomeAssistant, id: string) => type: "timer/delete", timer_id: id, }); + +export const timerTimeRemaining = ( + stateObj: HassEntity +): undefined | number => { + if (!stateObj.attributes.remaining) { + return undefined; + } + let timeRemaining = durationToSeconds(stateObj.attributes.remaining); + + if (stateObj.state === "active") { + const now = new Date().getTime(); + const madeActive = new Date(stateObj.last_changed).getTime(); + timeRemaining = Math.max(timeRemaining - (now - madeActive) / 1000, 0); + } + + return timeRemaining; +}; + +export const computeDisplayTimer = ( + hass: HomeAssistant, + stateObj: HassEntity, + timeRemaining?: number +): string | null => { + if (!stateObj) { + return null; + } + + if (stateObj.state === "idle" || timeRemaining === 0) { + return computeStateDisplay(hass.localize, stateObj, hass.locale); + } + + let display = secondsToDuration(timeRemaining || 0); + + if (stateObj.state === "paused") { + display = `${display} (${computeStateDisplay( + hass.localize, + stateObj, + hass.locale + )})`; + } + + return display; +}; diff --git a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts index feb1b3f61c33..a06eeb99055b 100644 --- a/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts +++ b/src/panels/lovelace/entity-rows/hui-timer-entity-row.ts @@ -1,9 +1,7 @@ import { HassEntity } from "home-assistant-js-websocket"; import { html, LitElement, PropertyValues, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; -import secondsToDuration from "../../../common/datetime/seconds_to_duration"; -import { computeStateDisplay } from "../../../common/entity/compute_state_display"; -import { timerTimeRemaining } from "../../../common/entity/timer_time_remaining"; +import { computeDisplayTimer, timerTimeRemaining } from "../../../data/timer"; import { HomeAssistant } from "../../../types"; import { hasConfigOrEntityChanged } from "../common/has-changed"; import "../components/hui-generic-entity-row"; @@ -59,7 +57,9 @@ class HuiTimerEntityRow extends LitElement { return html` -
${this._computeDisplay(stateObj)}
+
+ ${computeDisplayTimer(this.hass, stateObj, this._timeRemaining)} +
`; } @@ -112,32 +112,6 @@ class HuiTimerEntityRow extends LitElement { private _calculateRemaining(stateObj: HassEntity): void { this._timeRemaining = timerTimeRemaining(stateObj); } - - private _computeDisplay(stateObj: HassEntity): string | null { - if (!stateObj) { - return null; - } - - if (stateObj.state === "idle" || this._timeRemaining === 0) { - return computeStateDisplay( - this.hass!.localize, - stateObj, - this.hass!.locale - ); - } - - let display = secondsToDuration(this._timeRemaining || 0); - - if (stateObj.state === "paused") { - display = `${display} (${computeStateDisplay( - this.hass!.localize, - stateObj, - this.hass!.locale - )})`; - } - - return display; - } } declare global { diff --git a/src/state-summary/state-card-timer.js b/src/state-summary/state-card-timer.js index 2b5917b371da..a517a52da16d 100644 --- a/src/state-summary/state-card-timer.js +++ b/src/state-summary/state-card-timer.js @@ -2,10 +2,8 @@ import "@polymer/iron-flex-layout/iron-flex-layout-classes"; import { html } from "@polymer/polymer/lib/utils/html-tag"; /* eslint-plugin-disable lit */ import { PolymerElement } from "@polymer/polymer/polymer-element"; -import secondsToDuration from "../common/datetime/seconds_to_duration"; -import { timerTimeRemaining } from "../common/entity/timer_time_remaining"; import "../components/entity/state-info"; -import { computeStateDisplay } from "../common/entity/compute_state_display"; +import { computeDisplayTimer, timerTimeRemaining } from "../data/timer"; class StateCardTimer extends PolymerElement { static get template() { @@ -93,28 +91,7 @@ class StateCardTimer extends PolymerElement { } _displayState(timeRemaining, stateObj) { - if (!stateObj) { - return null; - } - - if (stateObj.state === "idle" || timeRemaining === 0) { - return computeStateDisplay( - this.hass.localize, - stateObj, - this.hass.locale - ); - } - - let display = secondsToDuration(timeRemaining || 0); - - if (stateObj.state === "paused") { - display += - " (" + - computeStateDisplay(this.hass.localize, stateObj, this.hass.locale) + - ")"; - } - - return display; + return computeDisplayTimer(this.hass, stateObj, timeRemaining); } } customElements.define("state-card-timer", StateCardTimer); diff --git a/test-mocha/common/entity/timer_time_remaining_test.ts b/test-mocha/common/entity/timer_time_remaining_test.ts index 3fb76328695f..8c1ce07e00fd 100644 --- a/test-mocha/common/entity/timer_time_remaining_test.ts +++ b/test-mocha/common/entity/timer_time_remaining_test.ts @@ -1,7 +1,7 @@ import { assert } from "chai"; import * as sinon from "sinon"; -import { timerTimeRemaining } from "../../../src/common/entity/timer_time_remaining"; +import { timerTimeRemaining } from "../../../src/data/timer"; describe("timerTimeRemaining", () => { it("works with idle timers", () => {