mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 11:46:42 +00:00
Improve open and opening state for lock (#20808)
* Add open and opening color * Split isAvailable into multiple function * Use done wording
This commit is contained in:
parent
79abcca3b3
commit
4cc5d2d04b
@ -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 ||
|
||||
(!isLocking(stateObj) && !isUnlocking(stateObj) && !isJammed(stateObj))
|
||||
);
|
||||
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 || (!isUnlocked(stateObj) && !isWaiting(stateObj));
|
||||
}
|
||||
|
||||
export const callProtectedLockService = async (
|
||||
|
@ -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`
|
||||
<div class="buttons">
|
||||
${this._buttonState === "success"
|
||||
${this._buttonState === "done"
|
||||
? html`
|
||||
<p class="open-success">
|
||||
<p class="open-done">
|
||||
<ha-svg-icon path=${mdiCheck}></ha-svg-icon>
|
||||
${this.hass.localize("ui.card.lock.open_door_success")}
|
||||
${this.hass.localize("ui.card.lock.open_door_done")}
|
||||
</p>
|
||||
`
|
||||
: html`
|
||||
<ha-control-button
|
||||
.disabled=${!isAvailable(this.stateObj)}
|
||||
.disabled=${!canOpen(this.stateObj)}
|
||||
class="open-button ${this._buttonState}"
|
||||
@click=${this._open}
|
||||
>
|
||||
@ -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;
|
||||
|
@ -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
|
||||
<ha-control-button-group>
|
||||
<ha-control-button
|
||||
.label=${this.hass.localize("ui.card.lock.lock")}
|
||||
.disabled=${!isAvailable(this.stateObj) || isLocked(this.stateObj)}
|
||||
.disabled=${!canLock(this.stateObj)}
|
||||
@click=${this._onTap}
|
||||
data-service="lock"
|
||||
class=${classMap({
|
||||
pulse: isLocking(this.stateObj) || isUnlocking(this.stateObj),
|
||||
})}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiLock}></ha-svg-icon>
|
||||
</ha-control-button>
|
||||
<ha-control-button
|
||||
.label=${this.hass.localize("ui.card.lock.unlock")}
|
||||
.disabled=${!isAvailable(this.stateObj) || !isLocked(this.stateObj)}
|
||||
.disabled=${!canUnlock(this.stateObj)}
|
||||
@click=${this._onTap}
|
||||
data-service="unlock"
|
||||
class=${classMap({
|
||||
pulse: isLocking(this.stateObj) || isUnlocking(this.stateObj),
|
||||
})}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiLockOpenVariant}></ha-svg-icon>
|
||||
</ha-control-button>
|
||||
@ -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;
|
||||
|
@ -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`
|
||||
<p class="open-success">
|
||||
<p class="open-done">
|
||||
<ha-svg-icon path=${mdiCheck}></ha-svg-icon>
|
||||
${this.hass.localize("ui.card.lock.open_door_success")}
|
||||
${this.hass.localize("ui.card.lock.open_door_done")}
|
||||
</p>
|
||||
`
|
||||
: html`
|
||||
<ha-control-button-group>
|
||||
<ha-control-button
|
||||
.disabled=${!isAvailable(this.stateObj)}
|
||||
.disabled=${!canOpen(this.stateObj)}
|
||||
class="open-button ${this._buttonState}"
|
||||
@click=${this._open}
|
||||
>
|
||||
@ -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;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user