Skip to content

Commit

Permalink
Use resize controller for weather card (#19806)
Browse files Browse the repository at this point in the history
* Use resize controller for weather card

* Don't use observe
  • Loading branch information
piitaya authored Jun 26, 2024
1 parent 7d28f3f commit ae94231
Showing 1 changed file with 40 additions and 72 deletions.
112 changes: 40 additions & 72 deletions src/panels/lovelace/cards/hui-weather-forecast-card.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ResizeController } from "@lit-labs/observers/resize-controller";
import {
CSSResultGroup,
LitElement,
Expand All @@ -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";
Expand Down Expand Up @@ -74,10 +74,21 @@ 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 _resizeObserver?: ResizeObserver;
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 _needForecastSubscription() {
return (
Expand Down Expand Up @@ -118,14 +129,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();
}

Expand Down Expand Up @@ -159,16 +166,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) {
Expand Down Expand Up @@ -226,7 +223,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;

Expand All @@ -238,6 +238,7 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {

return html`
<ha-card
class=${ifDefined(this._sizeController.value)}

This comment has been minimized.

Copy link
@shnizmuffin

shnizmuffin Oct 9, 2024

Hey, this implementation of applying classes to ha-card with the ResizeController is blowing away any other classes applied to the element. This is detrimentally affecting users who do custom theming using Thomas Lovelace's Card Mod, including all the people implementing LCARS. Can you instead only remove the classes you initially set?

@action=${this._handleAction}
.actionHandler=${actionHandler({
hasHold: hasAction(this._config!.hold_action),
Expand Down Expand Up @@ -416,44 +417,6 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
handleAction(this, this.hass!, this._config!, ev.detail.action!);
}

private async _attachObserver(): Promise<void> {
if (!this._resizeObserver) {
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;
}
Expand All @@ -462,6 +425,11 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
return [
weatherSVGStyles,
css`
:host {
position: relative;
display: block;
height: 100%;
}
ha-card {
cursor: pointer;
outline: none;
Expand Down Expand Up @@ -612,67 +580,67 @@ 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;
}
/* ============= 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;
Expand Down

0 comments on commit ae94231

Please sign in to comment.