diff --git a/packages/dashboard/src/components/dialogs/binding/show-node-binding-dialog.ts b/packages/dashboard/src/components/dialogs/binding/show-node-binding-dialog.ts index efa5a3fc..bfd08cdc 100644 --- a/packages/dashboard/src/components/dialogs/binding/show-node-binding-dialog.ts +++ b/packages/dashboard/src/components/dialogs/binding/show-node-binding-dialog.ts @@ -4,12 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { MatterClient, MatterNode } from "@matter-server/ws-client"; +import { MatterNode } from "@matter-server/ws-client"; -export const showNodeBindingDialog = async (client: MatterClient, node: MatterNode, endpoint: number) => { +export const showNodeBindingDialog = async (node: MatterNode, endpoint: number) => { await import("./node-binding-dialog.js"); const dialog = document.createElement("node-binding-dialog"); - dialog.client = client; dialog.node = node; dialog.endpoint = endpoint; document.querySelector("matter-dashboard-app")?.renderRoot.appendChild(dialog); diff --git a/packages/dashboard/src/components/dialogs/commission-node-dialog/commission-node-dialog.ts b/packages/dashboard/src/components/dialogs/commission-node-dialog/commission-node-dialog.ts index 294fc9f5..3f4f766d 100644 --- a/packages/dashboard/src/components/dialogs/commission-node-dialog/commission-node-dialog.ts +++ b/packages/dashboard/src/components/dialogs/commission-node-dialog/commission-node-dialog.ts @@ -6,17 +6,21 @@ import "@material/web/button/text-button"; import "@material/web/dialog/dialog"; -import type { MdDialog } from "@material/web/dialog/dialog.js"; +import { consume } from "@lit/context"; import "@material/web/list/list"; import "@material/web/list/list-item"; +import type { MdDialog } from "@material/web/dialog/dialog.js"; import { MatterClient, MatterNode } from "@matter-server/ws-client"; import { html, LitElement } from "lit"; import { customElement, property, state } from "lit/decorators.js"; +import { clientContext } from "../../../client/client-context.js"; import { preventDefault } from "../../../util/prevent_default.js"; @customElement("commission-node-dialog") export class ComissionNodeDialog extends LitElement { - @property({ attribute: false }) public client!: MatterClient; + @consume({ context: clientContext, subscribe: true }) + @property({ attribute: false }) + public client!: MatterClient; @state() private _mode?: "wifi" | "thread" | "existing"; diff --git a/packages/dashboard/src/components/dialogs/commission-node-dialog/show-commission-node-dialog.ts b/packages/dashboard/src/components/dialogs/commission-node-dialog/show-commission-node-dialog.ts index 11ab1218..9371049e 100644 --- a/packages/dashboard/src/components/dialogs/commission-node-dialog/show-commission-node-dialog.ts +++ b/packages/dashboard/src/components/dialogs/commission-node-dialog/show-commission-node-dialog.ts @@ -4,11 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { MatterClient } from "@matter-server/ws-client"; - -export const showCommissionNodeDialog = async (client: MatterClient) => { +export const showCommissionNodeDialog = async () => { await import("./commission-node-dialog.js"); const dialog = document.createElement("commission-node-dialog"); - dialog.client = client; document.querySelector("matter-dashboard-app")?.renderRoot.appendChild(dialog); }; diff --git a/packages/dashboard/src/components/dialogs/settings/log-level-dialog.ts b/packages/dashboard/src/components/dialogs/settings/log-level-dialog.ts index fdb951f0..47ebe51f 100644 --- a/packages/dashboard/src/components/dialogs/settings/log-level-dialog.ts +++ b/packages/dashboard/src/components/dialogs/settings/log-level-dialog.ts @@ -6,15 +6,18 @@ import "@material/web/button/text-button"; import "@material/web/dialog/dialog"; +import { consume } from "@lit/context"; import type { MdDialog } from "@material/web/dialog/dialog.js"; import { MatterClient } from "@matter-server/ws-client"; import { css, html, LitElement } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { clientContext } from "../../../client/client-context.js"; import { preventDefault } from "../../../util/prevent_default.js"; import "./log-level-section.js"; @customElement("log-level-dialog") export class LogLevelDialog extends LitElement { + @consume({ context: clientContext, subscribe: true }) @property({ attribute: false }) public client!: MatterClient; diff --git a/packages/dashboard/src/components/dialogs/settings/show-log-level-dialog.ts b/packages/dashboard/src/components/dialogs/settings/show-log-level-dialog.ts index 5e3c9d5a..a0ac2188 100644 --- a/packages/dashboard/src/components/dialogs/settings/show-log-level-dialog.ts +++ b/packages/dashboard/src/components/dialogs/settings/show-log-level-dialog.ts @@ -4,11 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { MatterClient } from "@matter-server/ws-client"; - -export const showLogLevelDialog = async (client: MatterClient) => { +export const showLogLevelDialog = async () => { await import("./log-level-dialog.js"); const dialog = document.createElement("log-level-dialog"); - dialog.client = client; document.querySelector("matter-dashboard-app")?.renderRoot.appendChild(dialog); }; diff --git a/packages/dashboard/src/pages/cluster-commands/base-cluster-commands.ts b/packages/dashboard/src/pages/cluster-commands/base-cluster-commands.ts index bcf64947..6ecab32f 100644 --- a/packages/dashboard/src/pages/cluster-commands/base-cluster-commands.ts +++ b/packages/dashboard/src/pages/cluster-commands/base-cluster-commands.ts @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { consume } from "@lit/context"; import { MatterClient, MatterNode } from "@matter-server/ws-client"; import { LitElement, css, type CSSResultGroup } from "lit"; import { property } from "lit/decorators.js"; +import { clientContext } from "../../client/client-context.js"; import { reducedMotionStyles } from "../../util/shared-styles.js"; /** @@ -14,6 +16,7 @@ import { reducedMotionStyles } from "../../util/shared-styles.js"; * Provides shared properties, styling, and helper methods for sending commands. */ export abstract class BaseClusterCommands extends LitElement { + @consume({ context: clientContext, subscribe: true }) @property({ attribute: false }) public client!: MatterClient; diff --git a/packages/dashboard/src/pages/components/header.ts b/packages/dashboard/src/pages/components/header.ts index b218d0a8..93f2003e 100644 --- a/packages/dashboard/src/pages/components/header.ts +++ b/packages/dashboard/src/pages/components/header.ts @@ -9,10 +9,12 @@ import "@material/web/divider/divider"; import "@material/web/iconbutton/icon-button"; import "@material/web/list/list"; import "@material/web/list/list-item"; +import { consume } from "@lit/context"; import { MatterClient } from "@matter-server/ws-client"; import { mdiArrowLeft, mdiBrightnessAuto, mdiCog, mdiLogout, mdiWeatherNight, mdiWeatherSunny } from "@mdi/js"; import { LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators.js"; +import { clientContext } from "../../client/client-context.js"; import { showSettingsDialog } from "../../components/dialogs/settings/show-settings-dialog.js"; import "../../components/ha-svg-icon"; import { DevModeService } from "../../util/dev-mode-service.js"; @@ -35,7 +37,9 @@ export class DashboardHeader extends LitElement { @property({ type: Boolean }) public hasThreadDevices?: boolean; @property({ type: Boolean }) public hasWifiDevices?: boolean; - public client?: MatterClient; + @consume({ context: clientContext, subscribe: true }) + @property({ attribute: false }) + public client!: MatterClient; @state() private _themePreference: ThemePreference = ThemeService.preference; @state() private _effectiveTheme: EffectiveTheme = ThemeService.effectiveTheme; diff --git a/packages/dashboard/src/pages/components/node-details.ts b/packages/dashboard/src/pages/components/node-details.ts index 8db49d65..d3fb9146 100644 --- a/packages/dashboard/src/pages/components/node-details.ts +++ b/packages/dashboard/src/pages/components/node-details.ts @@ -16,6 +16,7 @@ import { MatterClient, MatterNode, UpdateSource } from "@matter-server/ws-client import { mdiChatProcessing, mdiLink, mdiShareVariant, mdiTrashCan, mdiUpdate } from "@mdi/js"; import { LitElement, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators.js"; +import { clientContext } from "../../client/client-context.js"; import { DeviceType } from "../../client/models/descriptions.js"; import { showAlertDialog, showPromptDialog } from "../../components/dialog-box/show-dialog-box.js"; import { showNodeBindingDialog } from "../../components/dialogs/binding/show-node-binding-dialog.js"; @@ -59,6 +60,8 @@ function getNodeDeviceTypes(node: MatterNode): DeviceType[] { @customElement("node-details") export class NodeDetails extends LitElement { + @consume({ context: clientContext, subscribe: true }) + @property({ attribute: false }) public client!: MatterClient; @property() public node?: MatterNode; @@ -199,7 +202,7 @@ export class NodeDetails extends LitElement { private async _binding() { try { - showNodeBindingDialog(this.client, this.node!, this.endpoint); + showNodeBindingDialog(this.node!, this.endpoint); } catch (err: unknown) { console.error("Binding error:", err); } diff --git a/packages/dashboard/src/pages/components/server-details.ts b/packages/dashboard/src/pages/components/server-details.ts index 46226793..444b8799 100644 --- a/packages/dashboard/src/pages/components/server-details.ts +++ b/packages/dashboard/src/pages/components/server-details.ts @@ -11,10 +11,12 @@ import "@material/web/divider/divider"; import "@material/web/iconbutton/icon-button"; import "@material/web/list/list"; import "@material/web/list/list-item"; +import { consume } from "@lit/context"; import { MatterClient } from "@matter-server/ws-client"; import { mdiFile, mdiPlus } from "@mdi/js"; import { LitElement, css, html, nothing } from "lit"; -import { customElement } from "lit/decorators.js"; +import { customElement, property } from "lit/decorators.js"; +import { clientContext } from "../../client/client-context.js"; import { showAlertDialog, showPromptDialog } from "../../components/dialog-box/show-dialog-box.js"; import { showCommissionNodeDialog } from "../../components/dialogs/commission-node-dialog/show-commission-node-dialog.js"; import "../../components/ha-svg-icon"; @@ -22,7 +24,9 @@ import { handleAsync } from "../../util/async-handler.js"; @customElement("server-details") export class ServerDetails extends LitElement { - public client?: MatterClient; + @consume({ context: clientContext, subscribe: true }) + @property({ attribute: false }) + public client!: MatterClient; protected override render() { if (!this.client) return html``; @@ -71,7 +75,7 @@ export class ServerDetails extends LitElement { } private _commissionNode() { - showCommissionNodeDialog(this.client!); + showCommissionNodeDialog(); } private async _uploadDiagnosticsDumpFile() { @@ -96,7 +100,7 @@ export class ServerDetails extends LitElement { reader.readAsText(selectedFile, "UTF-8"); reader.onload = async () => { try { - await this.client!.importTestNode(reader.result?.toString() ?? ""); + await this.client.importTestNode(reader.result?.toString() ?? ""); } catch (err: any) { showAlertDialog({ title: "Failed to import test node", diff --git a/packages/dashboard/src/pages/matter-cluster-view.ts b/packages/dashboard/src/pages/matter-cluster-view.ts index accfbca2..6d289449 100644 --- a/packages/dashboard/src/pages/matter-cluster-view.ts +++ b/packages/dashboard/src/pages/matter-cluster-view.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { provide } from "@lit/context"; +import { consume, provide } from "@lit/context"; import "@material/web/button/outlined-button"; import "@material/web/divider/divider"; import "@material/web/iconbutton/icon-button"; @@ -16,6 +16,7 @@ import { mdiAlertCircleOutline, mdiPencil, mdiPlay, mdiRefresh } from "@mdi/js"; import { css, html, LitElement, nothing, type TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { unsafeHTML } from "lit/directives/unsafe-html.js"; +import { clientContext } from "../client/client-context.js"; import { clusters } from "../client/models/descriptions.js"; import { showAlertDialog } from "../components/dialog-box/show-dialog-box.js"; import { showAttributeWriteDialog } from "../components/dialogs/dev/show-attribute-write-dialog.js"; @@ -74,6 +75,8 @@ function clusterAttributes(attributes: { [key: string]: any }, endpoint: number, @customElement("matter-cluster-view") class MatterClusterView extends LitElement { + @consume({ context: clientContext, subscribe: true }) + @property({ attribute: false }) public client!: MatterClient; @property() @@ -130,12 +133,11 @@ class MatterClusterView extends LitElement {
- +
@@ -375,8 +377,7 @@ class MatterClusterView extends LitElement { const container = this.shadowRoot?.getElementById("cluster-commands-container"); if (container) { const commandsElement = container.firstElementChild as any; - if (commandsElement && this.node && this.client) { - commandsElement.client = this.client; + if (commandsElement && this.node) { commandsElement.node = this.node; commandsElement.endpoint = this.endpoint; commandsElement.cluster = this.cluster; diff --git a/packages/dashboard/src/pages/matter-dashboard-app.ts b/packages/dashboard/src/pages/matter-dashboard-app.ts index feb8f79a..9f877eb5 100644 --- a/packages/dashboard/src/pages/matter-dashboard-app.ts +++ b/packages/dashboard/src/pages/matter-dashboard-app.ts @@ -108,6 +108,7 @@ class MatterDashboardApp extends LitElement { this.client.startListening().then( () => { this._state = "connected"; + this.provider.setValue(clone(this.client)); this._setupEventListeners(); }, (_err: MatterError) => { @@ -198,7 +199,6 @@ class MatterDashboardApp extends LitElement { // cluster level return html` @@ -217,12 +216,7 @@ class MatterDashboardApp extends LitElement { } if (this._route.prefix === "node") { // node level - return html` - - `; + return html` `; } // Get device counts for conditional navigation const { hasThreadDevices, hasWifiDevices } = this._getDeviceCounts(); @@ -230,7 +224,6 @@ class MatterDashboardApp extends LitElement { // Check for Thread view (#thread or #thread/123) if (this._route.prefix === "thread" || this._route.path[0] === "thread") { return html`
- +
diff --git a/packages/dashboard/src/pages/matter-network-view.ts b/packages/dashboard/src/pages/matter-network-view.ts index 515d82a7..5efc7590 100644 --- a/packages/dashboard/src/pages/matter-network-view.ts +++ b/packages/dashboard/src/pages/matter-network-view.ts @@ -4,10 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { consume } from "@lit/context"; import type { MatterClient, MatterNode } from "@matter-server/ws-client"; import { mdiEyeOff, mdiFitToScreen, mdiMagnifyMinus, mdiMagnifyPlus, mdiPause, mdiPlay } from "@mdi/js"; import { css, html, LitElement } from "lit"; import { customElement, property, query, state } from "lit/decorators.js"; +import { clientContext } from "../client/client-context.js"; import "../components/ha-svg-icon"; import { reducedMotionStyles } from "../util/shared-styles.js"; import "./components/footer"; @@ -38,6 +40,8 @@ const HIDE_OPTIONS: readonly { key: HideOptionKey; label: string }[] = [ @customElement("matter-network-view") class MatterNetworkView extends LitElement { + @consume({ context: clientContext, subscribe: true }) + @property({ attribute: false }) public client!: MatterClient; @property({ type: Object }) @@ -426,7 +430,6 @@ class MatterNetworkView extends LitElement { return html` +
@@ -90,7 +90,7 @@ class MatterNodeView extends LitElement { ` : ""}
- + diff --git a/packages/dashboard/src/pages/matter-server-view.ts b/packages/dashboard/src/pages/matter-server-view.ts index 505c6506..2945ec87 100644 --- a/packages/dashboard/src/pages/matter-server-view.ts +++ b/packages/dashboard/src/pages/matter-server-view.ts @@ -8,10 +8,12 @@ import "@material/web/divider/divider"; import "@material/web/iconbutton/icon-button"; import "@material/web/list/list"; import "@material/web/list/list-item"; +import { consume } from "@lit/context"; import { isTestNodeId, MatterClient, MatterNode } from "@matter-server/ws-client"; import { mdiChevronRight } from "@mdi/js"; import { css, html, LitElement, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { clientContext } from "../client/client-context.js"; import "../components/ha-svg-icon"; import { getDeviceIcon } from "../util/device-icons.js"; import { formatNodeAddress } from "../util/format_hex.js"; @@ -28,6 +30,8 @@ declare global { @customElement("matter-server-view") class MatterServerView extends LitElement { + @consume({ context: clientContext, subscribe: true }) + @property({ attribute: false }) public client!: MatterClient; @property() @@ -59,7 +63,6 @@ class MatterServerView extends LitElement { return html`
- +
diff --git a/packages/dashboard/src/pages/network/network-details.ts b/packages/dashboard/src/pages/network/network-details.ts index 1182dc8f..ad4c56e2 100644 --- a/packages/dashboard/src/pages/network/network-details.ts +++ b/packages/dashboard/src/pages/network/network-details.ts @@ -71,7 +71,7 @@ export class NetworkDetails extends LitElement { @property({ type: Object }) public threadEdgePairs: Map = new Map(); - @consume({ context: clientContext }) + @consume({ context: clientContext, subscribe: true }) private client!: MatterClient; @state() @@ -1034,7 +1034,6 @@ export class NetworkDetails extends LitElement { ${this._showUpdateDialog ? html`