From 4cc5d2d04b90792cc22fd2883747373759727b5f Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 21 May 2024 09:19:36 +0200 Subject: [PATCH] Improve open and opening state for lock (#20808) * Add open and opening color * Split isAvailable into multiple function * Use done wording --- src/data/lock.ts | 39 ++++++++++++++++--- .../more-info/controls/more-info-lock.ts | 18 ++++----- .../hui-lock-commands-card-feature.ts | 35 +++-------------- .../hui-lock-open-door-card-feature.ts | 23 +++++------ src/resources/ha-style.ts | 2 + src/translations/en.json | 2 +- 6 files changed, 62 insertions(+), 57 deletions(-) diff --git a/src/data/lock.ts b/src/data/lock.ts index 26d42178023f..17acf134877f 100644 --- a/src/data/lock.ts +++ b/src/data/lock.ts @@ -26,6 +26,10 @@ export function isLocked(stateObj: LockEntity) { return stateObj.state === "locked"; } +export function isUnlocked(stateObj: LockEntity) { + return stateObj.state === "unlocked"; +} + export function isUnlocking(stateObj: LockEntity) { return stateObj.state === "unlocking"; } @@ -38,15 +42,40 @@ export function isJammed(stateObj: LockEntity) { return stateObj.state === "jammed"; } -export function isAvailable(stateObj: LockEntity) { +export function isOpen(stateObj: LockEntity) { + return stateObj.state === "open"; +} + +export function isOpening(stateObj: LockEntity) { + return stateObj.state === "opening"; +} + +export function isWaiting(stateObj: LockEntity) { + return ["opening", "unlocking", "locking"].includes(stateObj.state); +} + +export function canOpen(stateObj: LockEntity) { + if (stateObj.state === UNAVAILABLE) { + return false; + } + const assumedState = stateObj.attributes.assumed_state === true; + return assumedState || (!isOpen(stateObj) && !isWaiting(stateObj)); +} + +export function canLock(stateObj: LockEntity) { + if (stateObj.state === UNAVAILABLE) { + return false; + } + const assumedState = stateObj.attributes.assumed_state === true; + return assumedState || (!isLocked(stateObj) && !isWaiting(stateObj)); +} + +export function canUnlock(stateObj: LockEntity) { if (stateObj.state === UNAVAILABLE) { return false; } const assumedState = stateObj.attributes.assumed_state === true; - return ( - assumedState || - (!isLocking(stateObj) && !isUnlocking(stateObj) && !isJammed(stateObj)) - ); + return assumedState || (!isUnlocked(stateObj) && !isWaiting(stateObj)); } export const callProtectedLockService = async ( diff --git a/src/dialogs/more-info/controls/more-info-lock.ts b/src/dialogs/more-info/controls/more-info-lock.ts index 2236a523518b..233a3df6cde0 100644 --- a/src/dialogs/more-info/controls/more-info-lock.ts +++ b/src/dialogs/more-info/controls/more-info-lock.ts @@ -13,7 +13,7 @@ import { LockEntity, LockEntityFeature, callProtectedLockService, - isAvailable, + canOpen, isJammed, } from "../../../data/lock"; import "../../../state-control/lock/ha-state-control-lock-toggle"; @@ -22,9 +22,9 @@ import "../components/ha-more-info-state-header"; import { moreInfoControlStyle } from "../components/more-info-control-style"; const CONFIRM_TIMEOUT_SECOND = 5; -const OPENED_TIMEOUT_SECOND = 3; +const DONE_TIMEOUT_SECOND = 2; -type ButtonState = "normal" | "confirm" | "success"; +type ButtonState = "normal" | "confirm" | "done"; @customElement("more-info-lock") class MoreInfoLock extends LitElement { @@ -54,7 +54,7 @@ class MoreInfoLock extends LitElement { callProtectedLockService(this, this.hass, this.stateObj!, "open"); - this._setButtonState("success", OPENED_TIMEOUT_SECOND); + this._setButtonState("done", DONE_TIMEOUT_SECOND); } private _resetButtonState() { @@ -115,16 +115,16 @@ class MoreInfoLock extends LitElement { ${supportsOpen ? html`
- ${this._buttonState === "success" + ${this._buttonState === "done" ? html` -

+

- ${this.hass.localize("ui.card.lock.open_door_success")} + ${this.hass.localize("ui.card.lock.open_door_done")}

` : html` @@ -175,7 +175,7 @@ class MoreInfoLock extends LitElement { .open-button.confirm { --control-button-background-color: var(--warning-color); } - .open-success { + .open-done { line-height: 60px; display: flex; align-items: center; diff --git a/src/panels/lovelace/card-features/hui-lock-commands-card-feature.ts b/src/panels/lovelace/card-features/hui-lock-commands-card-feature.ts index 2d02345bbf00..19d737bb2172 100644 --- a/src/panels/lovelace/card-features/hui-lock-commands-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-lock-commands-card-feature.ts @@ -1,23 +1,20 @@ import { mdiLock, mdiLockOpenVariant } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; -import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; +import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; -import { classMap } from "lit/directives/class-map"; import { computeDomain } from "../../../common/entity/compute_domain"; import "../../../components/ha-control-button"; import "../../../components/ha-control-button-group"; +import { forwardHaptic } from "../../../data/haptics"; import { callProtectedLockService, - isAvailable, - isLocking, - isUnlocking, - isLocked, + canLock, + canUnlock, } from "../../../data/lock"; import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature } from "../types"; import { LockCommandsCardFeatureConfig } from "./types"; -import { forwardHaptic } from "../../../data/haptics"; export const supportsLockCommandsCardFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -72,23 +69,17 @@ class HuiLockCommandsCardFeature @@ -98,20 +89,6 @@ class HuiLockCommandsCardFeature static get styles(): CSSResultGroup { return css` - @keyframes pulse { - 0% { - opacity: 1; - } - 50% { - opacity: 0; - } - 100% { - opacity: 1; - } - } - .pulse { - animation: pulse 1s infinite; - } ha-control-button-group { margin: 0 12px 12px 12px; --control-button-group-spacing: 12px; diff --git a/src/panels/lovelace/card-features/hui-lock-open-door-card-feature.ts b/src/panels/lovelace/card-features/hui-lock-open-door-card-feature.ts index 7dabb1a3ad06..298daabb559f 100644 --- a/src/panels/lovelace/card-features/hui-lock-open-door-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-lock-open-door-card-feature.ts @@ -8,9 +8,9 @@ import { supportsFeature } from "../../../common/entity/supports-feature"; import "../../../components/ha-control-button"; import "../../../components/ha-control-button-group"; import { - LockEntityFeature, callProtectedLockService, - isAvailable, + canOpen, + LockEntityFeature, } from "../../../data/lock"; import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature } from "../types"; @@ -22,9 +22,9 @@ export const supportsLockOpenDoorCardFeature = (stateObj: HassEntity) => { }; const CONFIRM_TIMEOUT_SECOND = 5; -const OPENED_TIMEOUT_SECOND = 3; +const DONE_TIMEOUT_SECOND = 2; -type ButtonState = "normal" | "confirm" | "success"; +type ButtonState = "normal" | "confirm" | "done"; @customElement("hui-lock-open-door-card-feature") class HuiLockOpenDoorCardFeature @@ -74,7 +74,7 @@ class HuiLockOpenDoorCardFeature } callProtectedLockService(this, this.hass, this.stateObj!, "open"); - this._setButtonState("success", OPENED_TIMEOUT_SECOND); + this._setButtonState("done", DONE_TIMEOUT_SECOND); } protected render() { @@ -88,17 +88,17 @@ class HuiLockOpenDoorCardFeature } return html` - ${this._buttonState === "success" + ${this._buttonState === "done" ? html` -

+

- ${this.hass.localize("ui.card.lock.open_door_success")} + ${this.hass.localize("ui.card.lock.open_door_done")}

` : html` @@ -126,7 +126,7 @@ class HuiLockOpenDoorCardFeature .open-button.confirm { --control-button-background-color: var(--warning-color); } - .open-success { + .open-done { font-size: 14px; line-height: 14px; display: flex; @@ -140,9 +140,6 @@ class HuiLockOpenDoorCardFeature height: 40px; text-align: center; } - ha-control-button-group + ha-attributes:not([empty]) { - margin-top: 16px; - } `; } } diff --git a/src/resources/ha-style.ts b/src/resources/ha-style.ts index 664b2c2cf707..1fa724ac0af8 100644 --- a/src/resources/ha-style.ts +++ b/src/resources/ha-style.ts @@ -165,6 +165,8 @@ const mainStyles = css` --state-lock-locked-color: var(--green-color); --state-lock-pending-color: var(--orange-color); --state-lock-unlocked-color: var(--red-color); + --state-lock-opening-color: var(--orange-color); + --state-lock-open-color: var(--red-color); --state-media_player-active-color: var(--light-blue-color); --state-person-active-color: var(--blue-color); --state-person-home-color: var(--green-color); diff --git a/src/translations/en.json b/src/translations/en.json index c8b5efe192ef..7e63d31fc564 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -190,7 +190,7 @@ "open": "Open", "open_door": "Open door", "open_door_confirm": "Really open?", - "open_door_success": "Door open" + "open_door_done": "Done" }, "media_player": { "source": "Source",