From af6342b91747277eb82b99536e1ce46448ca4bbd Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Thu, 15 Feb 2024 09:59:12 +0100 Subject: [PATCH] Use resize controller for weather card --- .../cards/hui-weather-forecast-card.ts | 111 ++++++------------ 1 file changed, 38 insertions(+), 73 deletions(-) diff --git a/src/panels/lovelace/cards/hui-weather-forecast-card.ts b/src/panels/lovelace/cards/hui-weather-forecast-card.ts index 3d0d2ac047..1b2a0d66b0 100644 --- a/src/panels/lovelace/cards/hui-weather-forecast-card.ts +++ b/src/panels/lovelace/cards/hui-weather-forecast-card.ts @@ -1,3 +1,4 @@ +import { ResizeController } from "@lit-labs/observers/resize-controller"; import { CSSResultGroup, LitElement, @@ -14,7 +15,6 @@ import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_elemen import { computeStateName } from "../../../common/entity/compute_state_name"; import { isValidEntityId } from "../../../common/entity/valid_entity_id"; import { formatNumber } from "../../../common/number/format_number"; -import { debounce } from "../../../common/util/debounce"; import "../../../components/ha-card"; import "../../../components/ha-svg-icon"; import { UNAVAILABLE } from "../../../data/entity"; @@ -31,7 +31,6 @@ import { weatherAttrIcons, weatherSVGStyles, } from "../../../data/weather"; -import { loadPolyfillIfNeeded } from "../../../resources/resize-observer.polyfill"; import type { HomeAssistant } from "../../../types"; import { actionHandler } from "../common/directives/action-handler-directive"; import { findEntities } from "../common/find-entities"; @@ -75,10 +74,25 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { @state() private _subscribed?: Promise<() => void>; - // @todo Consider reworking to eliminate need for attribute since it is manipulated internally - @property({ type: Boolean, reflect: true }) public veryVeryNarrow = false; + private _sizeController = new ResizeController(this, { + callback: (entries) => { + const width = entries[0]?.contentRect.width; + if (width < 245) { + return "very-very-narrow"; + } + if (width < 300) { + return "very-narrow"; + } + if (width < 375) { + return "narrow"; + } + return "regular"; + }, + }); - private _resizeObserver?: ResizeObserver; + protected firstUpdated(): void { + this._sizeController.observe(this.shadowRoot!.querySelector("ha-card")!); + } private _needForecastSubscription() { return ( @@ -119,14 +133,10 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { if (this.hasUpdated && this._config && this.hass) { this._subscribeForecastEvents(); } - this.updateComplete.then(() => this._attachObserver()); } public disconnectedCallback(): void { super.disconnectedCallback(); - if (this._resizeObserver) { - this._resizeObserver.disconnect(); - } this._unsubscribeForecastEvents(); } @@ -160,16 +170,6 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { ); } - public willUpdate(): void { - if (!this.hasUpdated) { - this._measureCard(); - } - } - - protected firstUpdated(): void { - this._attachObserver(); - } - protected updated(changedProps: PropertyValues): void { super.updated(changedProps); if (!this._config || !this.hass) { @@ -227,7 +227,10 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { ); const forecast = this._config?.show_forecast !== false && forecastData?.forecast?.length - ? forecastData.forecast.slice(0, this.veryVeryNarrow ? 3 : 5) + ? forecastData.forecast.slice( + 0, + this._sizeController.value === "very-very-narrow" ? 3 : 5 + ) : undefined; const weather = !forecast || this._config?.show_current !== false; @@ -239,6 +242,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { return html` { - if (!this._resizeObserver) { - await loadPolyfillIfNeeded(); - this._resizeObserver = new ResizeObserver( - debounce(() => this._measureCard(), 250, false) - ); - } - const card = this.shadowRoot!.querySelector("ha-card"); - // If we show an error or warning there is no ha-card - if (!card) { - return; - } - this._resizeObserver.observe(card); - } - - private _measureCard() { - if (!this.isConnected) { - return; - } - - const card = this.shadowRoot!.querySelector("ha-card"); - // If we show an error or warning there is no ha-card - if (!card) { - return; - } - - if (card.offsetWidth < 375) { - this.setAttribute("narrow", ""); - } else { - this.removeAttribute("narrow"); - } - if (card.offsetWidth < 300) { - this.setAttribute("verynarrow", ""); - } else { - this.removeAttribute("verynarrow"); - } - this.veryVeryNarrow = card.offsetWidth < 245; - } - private _showValue(item?: any): boolean { return typeof item !== "undefined" && item !== null; } @@ -614,48 +579,48 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { /* ============= NARROW ============= */ - :host([narrow]) .icon-image { + [class*="narrow"] .icon-image { min-width: 52px; } - :host([narrow]) .weather-image { + [class*="narrow"] .weather-image { flex: 0 0 52px; width: 52px; } - :host([narrow]) .icon-image .weather-icon { + [class*="narrow"] .icon-image .weather-icon { --mdc-icon-size: 52px; } - :host([narrow]) .state, - :host([narrow]) .temp-attribute .temp { + [class*="narrow"] .state, + [class*="narrow"] .temp-attribute .temp { font-size: 22px; } - :host([narrow]) .temp-attribute .temp { + [class*="narrow"] .temp-attribute .temp { margin-right: 16px; margin-inline-end: 16px; margin-inline-start: initial; } - :host([narrow]) .temp span { + [class*="narrow"] .temp span { top: 1px; font-size: 16px; } /* ============= VERY NARROW ============= */ - :host([veryNarrow]) .name, - :host([veryNarrow]) .attribute { + [class*="very-narrow"] .name, + [class*="very-narrow"] .attribute { display: none; } - :host([veryNarrow]) .info { + [class*="very-narrow"] .info { flex-direction: column; align-items: flex-start; } - :host([veryNarrow]) .name-state { + [class*="very-narrow"] .name-state { padding-right: 0; padding-inline-end: 0; padding-inline-start: initial; @@ -663,18 +628,18 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard { /* ============= VERY VERY NARROW ============= */ - :host([veryVeryNarrow]) .info { + [class*="very-very-narrow"] .info { padding-top: 4px; align-items: center; } - :host([veryVeryNarrow]) .content { + [class*="very-very-narrow"] .content { flex-wrap: wrap; justify-content: center; flex-direction: column; } - :host([veryVeryNarrow]) .icon-image { + [class*="very-very-narrow"] .icon-image { margin-right: 0; margin-inline-end: 0; margin-inline-start: initial;