From e89ea47d3aeea9879d8d12a724f6647271b0300f Mon Sep 17 00:00:00 2001 From: TheJulianJES Date: Mon, 12 Jan 2026 15:45:18 +0100 Subject: [PATCH] Add Matter status to config dashboard (#28825) Co-authored-by: Norbert Rittel Co-authored-by: Bram Kragten --- src/panels/config/ha-panel-config.ts | 9 + .../integrations/ha-config-entry-row.ts | 6 +- .../matter/matter-config-dashboard.ts | 301 ++++++++++++++---- src/translations/en.json | 12 +- 4 files changed, 253 insertions(+), 75 deletions(-) diff --git a/src/panels/config/ha-panel-config.ts b/src/panels/config/ha-panel-config.ts index 3d7262f940..fb6dbd526a 100644 --- a/src/panels/config/ha-panel-config.ts +++ b/src/panels/config/ha-panel-config.ts @@ -114,6 +114,15 @@ export const configSections: Record = { }, ], dashboard_2: [ + { + path: "/config/matter", + name: "Matter", + iconPath: + "M7.228375 6.41685c0.98855 0.80195 2.16365 1.3412 3.416275 1.56765V1.30093l1.3612 -0.7854275 1.360125 0.7854275V7.9845c1.252875 -0.226675 2.4283 -0.765875 3.41735 -1.56765l2.471225 1.4293c-4.019075 3.976275 -10.490025 3.976275 -14.5091 0l2.482925 -1.4293Zm3.00335 17.067575c1.43325 -5.47035 -1.8052 -11.074775 -7.2604 -12.564675v2.859675c1.189125 0.455 2.244125 1.202875 3.0672 2.174275L0.25 19.2955v1.5719l1.3611925 0.781175L7.39865 18.3068c0.430175 1.19825 0.550625 2.48575 0.35015 3.743l2.482925 1.434625ZM21.034 10.91975c-5.452225 1.4932 -8.6871 7.09635 -7.254025 12.564675l2.47655 -1.43035c-0.200025 -1.257275 -0.079575 -2.544675 0.35015 -3.743025l5.7832 3.337525L23.75 20.86315V19.2955L17.961475 15.9537c0.8233 -0.97115 1.878225 -1.718975 3.0672 -2.174275l0.005325 -2.859675Z", + iconColor: "#2458B3", + component: "matter", + translationKey: "matter", + }, { path: "/config/zha", name: "Zigbee", diff --git a/src/panels/config/integrations/ha-config-entry-row.ts b/src/panels/config/integrations/ha-config-entry-row.ts index b61e39e6b6..64be533665 100644 --- a/src/panels/config/integrations/ha-config-entry-row.ts +++ b/src/panels/config/integrations/ha-config-entry-row.ts @@ -23,7 +23,6 @@ import { css, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import memoizeOne from "memoize-one"; -import { isDevVersion } from "../../../common/config/version"; import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name"; import { caseInsensitiveStringCompare } from "../../../common/string/compare"; import { copyToClipboard } from "../../../common/util/copy-clipboard"; @@ -213,10 +212,7 @@ class HaConfigEntryRow extends LitElement { ? html` ${this.hass.localize("ui.common.enable")} ` - : configPanel && - (item.domain !== "matter" || - isDevVersion(this.hass.config.version)) && - !stateText + : configPanel && !stateText ? html` + Object.values(devices).filter((device) => + device.identifiers.some((identifier) => identifier[0] === "matter") + ).length + ); + + protected render(): TemplateResult | typeof nothing { + if (!this._configEntry) { + return nothing; + } + const isOnline = this._configEntry.state === "loaded"; return html` - - ${isComponentLoaded(this.hass, "otbr") + + ${isComponentLoaded(this.hass, "thread") ? html` ` - : ""} -
- - ${this.hass.localize( - "ui.panel.config.matter.panel.experimental_note" - )} + : nothing} +
+
- ${this._error - ? html`${this._error}` - : ""} - ${this.hass.localize("ui.panel.config.matter.panel.add_devices")} +
+
+ +
+
+ Matter + ${this.hass.localize( + "ui.panel.config.matter.panel.status_title" + )}: + ${this.hass.localize( + `ui.panel.config.matter.panel.status_${isOnline ? "online" : "offline"}` + )}
+ + ${this.hass.localize( + "ui.panel.config.matter.panel.devices", + { count: this._matterDeviceCount(this.hass.devices) } + )} + +
+
- ${canCommissionMatterExternal(this.hass) - ? html`${this.hass.localize( - "ui.panel.config.matter.panel.mobile_app_commisioning" - )}` - : ""} - ${this.hass.localize( - "ui.panel.config.matter.panel.commission_device" - )} - ${this.hass.localize( - "ui.panel.config.matter.panel.add_shared_device" - )} - ${this.hass.localize( - "ui.panel.config.matter.panel.set_wifi_credentials" - )} - ${this.hass.localize( - "ui.panel.config.matter.panel.set_thread_credentials" - )} + + ${this.hass.localize("ui.panel.config.entities.caption")} +
+ + ${this._error + ? html`${this._error}` + : nothing} +
+

+ ${this.hass.localize( + "ui.panel.config.matter.panel.developer_tools_info" + )} +

+
+ ${canCommissionMatterExternal(this.hass) + ? html`${this.hass.localize( + "ui.panel.config.matter.panel.mobile_app_commisioning" + )}` + : nothing} + ${this.hass.localize( + "ui.panel.config.matter.panel.commission_device" + )} + ${this.hass.localize( + "ui.panel.config.matter.panel.add_shared_device" + )} + ${this.hass.localize( + "ui.panel.config.matter.panel.set_wifi_credentials" + )} + ${this.hass.localize( + "ui.panel.config.matter.panel.set_thread_credentials" + )} +
+
+
+ +
+ + + + `; } @@ -236,27 +329,101 @@ export class MatterConfigDashboard extends LitElement { } } - static styles = [ - haStyle, - css` - ha-alert[alert-type="warning"] { - position: relative; - top: -16px; - } - .content { - padding: 24px 0 32px; - max-width: 600px; - margin: 0 auto; - direction: ltr; - } - ha-card:first-child { - margin-bottom: 16px; - } - a[slot="toolbar-icon"] { - text-decoration: none; - } - `, - ]; + private async _fetchConfigEntry(): Promise { + const configEntries = await getConfigEntries(this.hass, { + domain: "matter", + }); + if (configEntries.length) { + this._configEntry = configEntries[0]; + } + } + + static get styles(): CSSResultGroup { + return [ + haStyle, + css` + ha-card { + margin: auto; + margin-top: var(--ha-space-4); + max-width: 500px; + } + + ha-card .card-actions { + display: flex; + justify-content: flex-end; + } + + .network-status div.heading { + display: flex; + align-items: center; + } + + .network-status div.heading .icon { + margin-inline-end: var(--ha-space-4); + } + + .network-status div.heading ha-svg-icon { + --mdc-icon-size: 48px; + } + + .network-status div.heading .details { + font-size: var(--ha-font-size-xl); + } + + .network-status small { + font-size: var(--ha-font-size-m); + } + + .network-status .online { + color: var(--state-on-color, var(--success-color)); + } + + .network-status .offline { + color: var(--error-color, var(--error-color)); + } + + .container { + padding: var(--ha-space-2) var(--ha-space-4) var(--ha-space-4); + } + + ha-expansion-panel { + margin: auto; + margin-top: var(--ha-space-4); + max-width: 500px; + background: var(--card-background-color); + border-radius: var( + --ha-card-border-radius, + var(--ha-border-radius-lg) + ); + --expansion-panel-summary-padding: var(--ha-space-2) var(--ha-space-4); + --expansion-panel-content-padding: 0 var(--ha-space-4); + } + + .dev-tools-content { + padding: 0 0 var(--ha-space-4); + } + + .dev-tools-content p { + margin: 0 0 var(--ha-space-4); + color: var(--primary-text-color); + } + + .dev-tools-actions { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--ha-space-2); + } + + a[slot="toolbar-icon"] { + text-decoration: none; + } + + a[slot="fab"] { + text-decoration: none; + } + `, + ]; + } } declare global { diff --git a/src/translations/en.json b/src/translations/en.json index 2c22107235..cd6c27fa80 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -6845,9 +6845,15 @@ }, "matter": { "panel": { - "thread_panel": "Visit Thread Panel", - "experimental_note": "Matter is still in the early phase of development, it is not meant to be used in production. This panel is for development only.", - "add_devices": "You can add Matter devices by commissioning them if they are not set up yet, or share them from another controller and enter the sharing code.", + "thread_panel": "Visit Thread panel", + "add_device": "Add device", + "status_title": "status", + "status_online": "online", + "status_offline": "offline", + "devices": "{count, plural,\n one {# device}\n other {# devices}\n}", + "developer_tools_title": "Developer tools", + "developer_tools_description": "Advanced commissioning options for development", + "developer_tools_info": "These options are intended for developers and advanced users. In most cases, use the \"Add device\" button in the bottom right corner instead.", "mobile_app_commisioning": "Commission device with mobile app", "commission_device": "Commission device", "add_shared_device": "Add shared device",