mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Display live remaining time for timer on tile card (#21290)
Display timer by default on tile card
This commit is contained in:
parent
d9583582e6
commit
e59c04c685
@ -92,7 +92,7 @@ export const computeDisplayTimer = (
|
||||
return hass.formatEntityState(stateObj);
|
||||
}
|
||||
|
||||
let display = secondsToDuration(timeRemaining || 0);
|
||||
let display = secondsToDuration(timeRemaining || 0) || "0";
|
||||
|
||||
if (stateObj.state === "paused") {
|
||||
display = `${display} (${hass.formatEntityState(stateObj)})`;
|
||||
|
@ -311,10 +311,19 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
if (domain === "update") {
|
||||
return html`${computeUpdateStateDisplay(
|
||||
stateObj as UpdateEntity,
|
||||
this.hass!
|
||||
)}`;
|
||||
return html`
|
||||
${computeUpdateStateDisplay(stateObj as UpdateEntity, this.hass!)}
|
||||
`;
|
||||
}
|
||||
|
||||
if (domain === "timer") {
|
||||
import("../../../state-display/state-display-timer");
|
||||
return html`
|
||||
<state-display-timer
|
||||
.hass=${this.hass}
|
||||
.stateObj=${stateObj}
|
||||
></state-display-timer>
|
||||
`;
|
||||
}
|
||||
|
||||
return this._renderStateContent(stateObj, "state");
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { html, LitElement, PropertyValues, nothing } from "lit";
|
||||
import { LitElement, PropertyValues, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { computeDisplayTimer, timerTimeRemaining } from "../../../data/timer";
|
||||
import "../../../state-display/state-display-timer";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import "../components/hui-generic-entity-row";
|
||||
@ -14,42 +13,11 @@ class HuiTimerEntityRow extends LitElement {
|
||||
|
||||
@state() private _config?: EntityConfig;
|
||||
|
||||
@state() private _timeRemaining?: number;
|
||||
|
||||
private _interval?: number;
|
||||
|
||||
public setConfig(config: EntityConfig): void {
|
||||
if (!config) {
|
||||
throw new Error("Invalid configuration");
|
||||
}
|
||||
this._config = config;
|
||||
|
||||
if (!this.hass) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stateObj = this.hass!.states[this._config.entity];
|
||||
|
||||
if (stateObj) {
|
||||
this._startInterval(stateObj);
|
||||
} else {
|
||||
this._clearInterval();
|
||||
}
|
||||
}
|
||||
|
||||
public disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this._clearInterval();
|
||||
}
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
if (this._config && this._config.entity) {
|
||||
const stateObj = this.hass?.states[this._config!.entity];
|
||||
if (stateObj) {
|
||||
this._startInterval(stateObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
@ -70,61 +38,18 @@ class HuiTimerEntityRow extends LitElement {
|
||||
return html`
|
||||
<hui-generic-entity-row .hass=${this.hass} .config=${this._config}>
|
||||
<div class="text-content">
|
||||
${computeDisplayTimer(this.hass, stateObj, this._timeRemaining)}
|
||||
<state-display-timer
|
||||
.hass=${this.hass}
|
||||
.stateObj=${stateObj}
|
||||
></state-display-timer>
|
||||
</div>
|
||||
</hui-generic-entity-row>
|
||||
`;
|
||||
}
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||
if (changedProps.has("_timeRemaining")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return hasConfigOrEntityChanged(this, changedProps);
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
super.updated(changedProps);
|
||||
|
||||
if (!this._config || !changedProps.has("hass")) {
|
||||
return;
|
||||
}
|
||||
const stateObj = this.hass!.states[this._config!.entity];
|
||||
const oldHass = changedProps.get("hass") as this["hass"];
|
||||
const oldStateObj = oldHass
|
||||
? oldHass.states[this._config!.entity]
|
||||
: undefined;
|
||||
|
||||
if (oldStateObj !== stateObj) {
|
||||
this._startInterval(stateObj);
|
||||
} else if (!stateObj) {
|
||||
this._clearInterval();
|
||||
}
|
||||
}
|
||||
|
||||
private _clearInterval(): void {
|
||||
if (this._interval) {
|
||||
window.clearInterval(this._interval);
|
||||
this._interval = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
private _startInterval(stateObj: HassEntity): void {
|
||||
this._clearInterval();
|
||||
this._calculateRemaining(stateObj);
|
||||
|
||||
if (stateObj.state === "active") {
|
||||
this._interval = window.setInterval(
|
||||
() => this._calculateRemaining(stateObj),
|
||||
1000
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _calculateRemaining(stateObj: HassEntity): void {
|
||||
this._timeRemaining = timerTimeRemaining(stateObj);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
74
src/state-display/state-display-timer.ts
Normal file
74
src/state-display/state-display-timer.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { PropertyValues, ReactiveElement } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { computeDisplayTimer, timerTimeRemaining } from "../data/timer";
|
||||
import type { HomeAssistant } from "../types";
|
||||
|
||||
@customElement("state-display-timer")
|
||||
class StateDisplayTimer extends ReactiveElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public stateObj!: HassEntity;
|
||||
|
||||
@state() private timeRemaining?: number;
|
||||
|
||||
private _updateRemaining: any;
|
||||
|
||||
protected createRenderRoot() {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected update(changedProps: PropertyValues) {
|
||||
super.update(changedProps);
|
||||
this.innerHTML =
|
||||
computeDisplayTimer(this.hass, this.stateObj, this.timeRemaining) ?? "-";
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
if (this.stateObj) {
|
||||
this._startInterval(this.stateObj);
|
||||
}
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this._clearInterval();
|
||||
}
|
||||
|
||||
protected willUpdate(changedProp: PropertyValues): void {
|
||||
super.willUpdate(changedProp);
|
||||
if (changedProp.has("stateObj")) {
|
||||
this._startInterval(this.stateObj);
|
||||
}
|
||||
}
|
||||
|
||||
private _clearInterval() {
|
||||
if (this._updateRemaining) {
|
||||
clearInterval(this._updateRemaining);
|
||||
this._updateRemaining = null;
|
||||
}
|
||||
}
|
||||
|
||||
private _startInterval(stateObj: HassEntity) {
|
||||
this._clearInterval();
|
||||
this._calculateRemaining(stateObj);
|
||||
|
||||
if (stateObj.state === "active") {
|
||||
this._updateRemaining = setInterval(
|
||||
() => this._calculateRemaining(this.stateObj),
|
||||
1000
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _calculateRemaining(stateObj: HassEntity) {
|
||||
this.timeRemaining = timerTimeRemaining(stateObj);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"state-display-timer": StateDisplayTimer;
|
||||
}
|
||||
}
|
@ -1,17 +1,10 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import {
|
||||
css,
|
||||
CSSResultGroup,
|
||||
html,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
} from "lit";
|
||||
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import "../components/entity/state-info";
|
||||
import { computeDisplayTimer, timerTimeRemaining } from "../data/timer";
|
||||
import { HomeAssistant } from "../types";
|
||||
import { haStyle } from "../resources/styles";
|
||||
import "../state-display/state-display-timer";
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
@customElement("state-card-timer")
|
||||
class StateCardTimer extends LitElement {
|
||||
@ -21,10 +14,6 @@ class StateCardTimer extends LitElement {
|
||||
|
||||
@property({ type: Boolean }) public inDialog = false;
|
||||
|
||||
@property({ type: Number }) public timeRemaining?: number;
|
||||
|
||||
private _updateRemaining: any;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<div class="horizontal justified layout">
|
||||
@ -34,63 +23,21 @@ class StateCardTimer extends LitElement {
|
||||
.inDialog=${this.inDialog}
|
||||
></state-info>
|
||||
<div class="state">
|
||||
${this._displayState(this.timeRemaining, this.stateObj)}
|
||||
<state-display-timer
|
||||
.hass=${this.hass}
|
||||
.stateObj=${this.stateObj}
|
||||
></state-display-timer>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this._startInterval(this.stateObj);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this._clearInterval();
|
||||
}
|
||||
|
||||
protected willUpdate(changedProp: PropertyValues): void {
|
||||
super.willUpdate(changedProp);
|
||||
if (changedProp.has("stateObj")) {
|
||||
this._startInterval(this.stateObj);
|
||||
}
|
||||
}
|
||||
|
||||
private _clearInterval() {
|
||||
if (this._updateRemaining) {
|
||||
clearInterval(this._updateRemaining);
|
||||
this._updateRemaining = null;
|
||||
}
|
||||
}
|
||||
|
||||
private _startInterval(stateObj) {
|
||||
this._clearInterval();
|
||||
this._calculateRemaining(stateObj);
|
||||
|
||||
if (stateObj.state === "active") {
|
||||
this._updateRemaining = setInterval(
|
||||
() => this._calculateRemaining(this.stateObj),
|
||||
1000
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _calculateRemaining(stateObj) {
|
||||
this.timeRemaining = timerTimeRemaining(stateObj);
|
||||
}
|
||||
|
||||
private _displayState(timeRemaining, stateObj) {
|
||||
return computeDisplayTimer(this.hass, stateObj, timeRemaining);
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
.state {
|
||||
color: var(--primary-text-color);
|
||||
|
||||
margin-left: 16px;
|
||||
margin-inline-start: 16px;
|
||||
margin-inline-end: initial;
|
||||
|
Loading…
x
Reference in New Issue
Block a user