Skip to content

Commit

Permalink
Merge branch 'piitaya:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
savino authored Mar 5, 2025
2 parents 8786d61 + 6809e63 commit 7294ff0
Show file tree
Hide file tree
Showing 22 changed files with 917 additions and 764 deletions.
2 changes: 1 addition & 1 deletion hacs.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Mushroom",
"filename": "mushroom.js",
"homeassistant": "2024.7.0b0",
"homeassistant": "2024.8",
"render_readme": true
}
1,262 changes: 637 additions & 625 deletions package-lock.json

Large diffs are not rendered by default.

23 changes: 12 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mushroom-cards",
"version": "4.2.1",
"version": "4.3.1",
"description": "Home Assistant Mushroom Cards",
"main": "index.js",
"scripts": {
Expand All @@ -25,26 +25,27 @@
"home-assistant-js-websocket": "^9.4.0",
"lit": "^3.2.1",
"memoize-one": "^6.0.0",
"sortablejs": "^1.15.3",
"object-hash": "^3.0.0",
"sortablejs": "^1.15.6",
"superstruct": "^2.0.2"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@babel/core": "^7.26.9",
"@babel/preset-env": "^7.26.9",
"@material/mwc-ripple": "^0.27.0",
"@material/tab-bar": "^14.0.0",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-commonjs": "^28.0.2",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-node-resolve": "^16.0.0",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.1",
"@rollup/plugin-typescript": "^12.1.2",
"@types/color": "^4.2.0",
"@types/hammerjs": "^2.0.46",
"eslint": "^9.14.0",
"prettier": "^3.3.3",
"rollup": "^4.18.0",
"eslint": "^9.21.0",
"prettier": "^3.5.2",
"rollup": "^4.34.8",
"rollup-plugin-serve": "^1.1.1",
"typescript": "^5.6.3"
"typescript": "^5.7.3"
}
}
43 changes: 37 additions & 6 deletions src/badges/template/template-badge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { customElement, property, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { styleMap } from "lit/directives/style-map.js";
import hash from "object-hash/dist/object_hash";
import {
actionHandler,
ActionHandlerEvent,
Expand All @@ -24,10 +25,17 @@ import {
} from "../../ha";
import { computeCssColor } from "../../ha/common/color/compute-color";
import { registerCustomBadge } from "../../utils/custom-badges";
import { TEMPLATE_BADGE_EDITOR_NAME, TEMPLATE_BADGE_NAME } from "./const";
import { TemplateBadgeConfig } from "./template-badge-config";
import { getWeatherSvgIcon } from "../../utils/icons/weather-icon";
import { weatherSVGStyles } from "../../utils/weather";
import { TEMPLATE_BADGE_EDITOR_NAME, TEMPLATE_BADGE_NAME } from "./const";
import { TemplateBadgeConfig } from "./template-badge-config";
import { CacheManager } from "../../utils/cache-manager";

const templateCache = new CacheManager<TemplateResults>(1000);

type TemplateResults = Partial<
Record<TemplateKey, RenderTemplateResult | undefined>
>;

registerCustomBadge({
type: TEMPLATE_BADGE_NAME,
Expand Down Expand Up @@ -62,9 +70,7 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge {

@state() protected _config?: TemplateBadgeConfig;

@state() private _templateResults: Partial<
Record<TemplateKey, RenderTemplateResult | undefined>
> = {};
@state() private _templateResults?: TemplateResults;

@state() private _unsubRenderTemplates: Map<
TemplateKey,
Expand All @@ -77,9 +83,34 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge {
}

public disconnectedCallback() {
super.disconnectedCallback();
this._tryDisconnect();

if (this._config && this._templateResults) {
const key = this._computeCacheKey();
templateCache.set(key, this._templateResults);
}
}

private _computeCacheKey() {
return hash(this._config);
}

protected willUpdate(_changedProperties: PropertyValues): void {
super.willUpdate(_changedProperties);
if (!this._config) {
return;
}

if (!this._templateResults) {
const key = this._computeCacheKey();
if (templateCache.has(key)) {
this._templateResults = templateCache.get(key)!;
} else {
this._templateResults = {};
}
}
}
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
Expand Down Expand Up @@ -267,7 +298,7 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge {

private getValue(key: TemplateKey) {
return this.isTemplate(key)
? this._templateResults[key]?.result?.toString()
? this._templateResults?.[key]?.result?.toString()
: this._config?.[key];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@ import { html, nothing } from "lit";
import { customElement, state } from "lit/decorators.js";
import memoizeOne from "memoize-one";
import { assert } from "superstruct";
import {
LocalizeFunc,
LovelaceCardEditor,
atLeastHaVersion,
fireEvent,
} from "../../ha";
import { LocalizeFunc, LovelaceCardEditor, fireEvent } from "../../ha";
import setupCustomlocalize from "../../localize";
import { computeActionsFormSchema } from "../../shared/config/actions-config";
import { APPEARANCE_FORM_SCHEMA } from "../../shared/config/appearance-config";
Expand Down Expand Up @@ -42,32 +37,28 @@ const states = [
"armed_custom_bypass",
];

const computeSchema = memoizeOne(
(localize: LocalizeFunc, useCallService: boolean): HaFormSchema[] => [
{
name: "entity",
selector: { entity: { domain: ALARM_CONTROl_PANEL_ENTITY_DOMAINS } },
},
{ name: "name", selector: { text: {} } },
{
name: "icon",
selector: { icon: {} },
context: { icon_entity: "entity" },
},
...APPEARANCE_FORM_SCHEMA,
{
type: "multi_select",
name: "states",
options: states.map((state) => [
state,
localize(
`ui.card.alarm_control_panel.${state.replace("armed", "arm")}`
),
]) as [string, string][],
},
...computeActionsFormSchema(actions, useCallService),
]
);
const computeSchema = memoizeOne((localize: LocalizeFunc): HaFormSchema[] => [
{
name: "entity",
selector: { entity: { domain: ALARM_CONTROl_PANEL_ENTITY_DOMAINS } },
},
{ name: "name", selector: { text: {} } },
{
name: "icon",
selector: { icon: {} },
context: { icon_entity: "entity" },
},
...APPEARANCE_FORM_SCHEMA,
{
type: "multi_select",
name: "states",
options: states.map((state) => [
state,
localize(`ui.card.alarm_control_panel.${state.replace("armed", "arm")}`),
]) as [string, string][],
},
...computeActionsFormSchema(actions),
]);

@customElement(ALARM_CONTROl_PANEL_CARD_EDITOR_NAME)
export class SwitchCardEditor
Expand All @@ -91,8 +82,7 @@ export class SwitchCardEditor
return nothing;
}

const useCallService = !atLeastHaVersion(this.hass.config.version, 2024, 8);
const schema = computeSchema(this.hass!.localize, useCallService);
const schema = computeSchema(this.hass!.localize);

return html`
<ha-form
Expand Down
11 changes: 5 additions & 6 deletions src/cards/chips-card/chips/action-chip-editor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { atLeastHaVersion, fireEvent, HomeAssistant } from "../../../ha";
import memoizeOne from "memoize-one";
import { fireEvent, HomeAssistant } from "../../../ha";
import setupCustomlocalize from "../../../localize";
import { computeActionsFormSchema } from "../../../shared/config/actions-config";
import { GENERIC_LABELS } from "../../../utils/form/generic-fields";
Expand All @@ -10,7 +11,6 @@ import { computeChipEditorComponentName } from "../../../utils/lovelace/chip/chi
import { ActionChipConfig } from "../../../utils/lovelace/chip/types";
import { LovelaceChipEditor } from "../../../utils/lovelace/types";
import { DEFAULT_ACTION_ICON } from "./action-chip";
import memoizeOne from "memoize-one";

const actions: UiAction[] = [
"navigate",
Expand All @@ -20,7 +20,7 @@ const actions: UiAction[] = [
"none",
];

const computeSchema = memoizeOne((useCallService: boolean): HaFormSchema[] => [
const computeSchema = memoizeOne((): HaFormSchema[] => [
{
type: "grid",
name: "",
Expand All @@ -32,7 +32,7 @@ const computeSchema = memoizeOne((useCallService: boolean): HaFormSchema[] => [
{ name: "icon_color", selector: { mush_color: {} } },
],
},
...computeActionsFormSchema(actions, useCallService),
...computeActionsFormSchema(actions),
]);

@customElement(computeChipEditorComponentName("action"))
Expand Down Expand Up @@ -61,8 +61,7 @@ export class EntityChipEditor extends LitElement implements LovelaceChipEditor {
return nothing;
}

const useCallService = !atLeastHaVersion(this.hass.config.version, 2024, 8);
const schema = computeSchema(useCallService);
const schema = computeSchema();

return html`
<ha-form
Expand Down
11 changes: 5 additions & 6 deletions src/cards/chips-card/chips/alarm-control-panel-chip-editor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { atLeastHaVersion, fireEvent, HomeAssistant } from "../../../ha";
import memoizeOne from "memoize-one";
import { fireEvent, HomeAssistant } from "../../../ha";
import setupCustomlocalize from "../../../localize";
import { computeActionsFormSchema } from "../../../shared/config/actions-config";
import { GENERIC_LABELS } from "../../../utils/form/generic-fields";
Expand All @@ -10,7 +11,6 @@ import { computeChipEditorComponentName } from "../../../utils/lovelace/chip/chi
import { AlarmControlPanelChipConfig } from "../../../utils/lovelace/chip/types";
import { LovelaceChipEditor } from "../../../utils/lovelace/types";
import { ALARM_CONTROl_PANEL_ENTITY_DOMAINS } from "../../alarm-control-panel-card/const";
import memoizeOne from "memoize-one";

const actions: UiAction[] = [
"more-info",
Expand All @@ -21,7 +21,7 @@ const actions: UiAction[] = [
"none",
];

const computeSchema = memoizeOne((useCallService: boolean): HaFormSchema[] => [
const computeSchema = memoizeOne((): HaFormSchema[] => [
{
name: "entity",
selector: { entity: { domain: ALARM_CONTROl_PANEL_ENTITY_DOMAINS } },
Expand All @@ -35,7 +35,7 @@ const computeSchema = memoizeOne((useCallService: boolean): HaFormSchema[] => [
],
},
{ name: "icon", selector: { icon: {} }, context: { icon_entity: "entity" } },
...computeActionsFormSchema(actions, useCallService),
...computeActionsFormSchema(actions),
]);

@customElement(computeChipEditorComponentName("alarm-control-panel"))
Expand Down Expand Up @@ -67,8 +67,7 @@ export class AlarmControlPanelChipEditor
return nothing;
}

const useCallService = !atLeastHaVersion(this.hass.config.version, 2024, 8);
const schema = computeSchema(useCallService);
const schema = computeSchema();

return html`
<ha-form
Expand Down
42 changes: 37 additions & 5 deletions src/cards/chips-card/chips/template-chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { styleMap } from "lit/directives/style-map.js";
import hash from "object-hash/dist/object_hash";
import {
actionHandler,
ActionHandlerEvent,
Expand All @@ -20,6 +21,7 @@ import {
RenderTemplateResult,
subscribeRenderTemplate,
} from "../../../ha";
import { CacheManager } from "../../../utils/cache-manager";
import { computeRgbColor } from "../../../utils/colors";
import { getWeatherSvgIcon } from "../../../utils/icons/weather-icon";
import {
Expand All @@ -33,6 +35,12 @@ import {
import { LovelaceChipEditor } from "../../../utils/lovelace/types";
import { weatherSVGStyles } from "../../../utils/weather";

const templateCache = new CacheManager<TemplateResults>(1000);

type TemplateResults = Partial<
Record<TemplateKey, RenderTemplateResult | undefined>
>;

const TEMPLATE_KEYS = ["content", "icon", "icon_color", "picture"] as const;
type TemplateKey = (typeof TEMPLATE_KEYS)[number];

Expand All @@ -57,9 +65,7 @@ export class TemplateChip extends LitElement implements LovelaceChip {

@state() private _config?: TemplateChipConfig;

@state() private _templateResults: Partial<
Record<TemplateKey, RenderTemplateResult | undefined>
> = {};
@state() private _templateResults?: TemplateResults;

@state() private _unsubRenderTemplates: Map<
TemplateKey,
Expand Down Expand Up @@ -92,7 +98,33 @@ export class TemplateChip extends LitElement implements LovelaceChip {
}

public disconnectedCallback() {
super.disconnectedCallback();
this._tryDisconnect();

if (this._config && this._templateResults) {
const key = this._computeCacheKey();
templateCache.set(key, this._templateResults);
}
}

private _computeCacheKey() {
return hash(this._config);
}

protected willUpdate(_changedProperties: PropertyValues): void {
super.willUpdate(_changedProperties);
if (!this._config) {
return;
}

if (!this._templateResults) {
const key = this._computeCacheKey();
if (templateCache.has(key)) {
this._templateResults = templateCache.get(key)!;
} else {
this._templateResults = {};
}
}
}

private _handleAction(ev: ActionHandlerEvent) {
Expand All @@ -106,7 +138,7 @@ export class TemplateChip extends LitElement implements LovelaceChip {

private getValue(key: TemplateKey) {
return this.isTemplate(key)
? this._templateResults[key]?.result?.toString()
? this._templateResults?.[key]?.result?.toString()
: this._config?.[key];
}

Expand All @@ -132,7 +164,7 @@ export class TemplateChip extends LitElement implements LovelaceChip {
hasDoubleClick: hasAction(this._config.double_tap_action),
})}
.avatar=${picture ? (this.hass as any).hassUrl(picture) : undefined}
.avatarOnly=${picture && !content}
.avatarOnly=${(picture && !content) || false}
>
${!picture
? weatherSvg
Expand Down
Loading

0 comments on commit 7294ff0

Please sign in to comment.