mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Improve Wifi configuration UI (#22471)
* Improve Wifi configuration UI * some UI tweaks based on comments * change label and remove DNS on reset * remove mock code
This commit is contained in:
parent
5843877cc8
commit
fc9a0958d4
@ -17,7 +17,7 @@ export interface NetworkInterface {
|
||||
ipv4?: Partial<IpConfiguration>;
|
||||
ipv6?: Partial<IpConfiguration>;
|
||||
type: "ethernet" | "wireless" | "vlan";
|
||||
wifi?: Partial<WifiConfiguration>;
|
||||
wifi?: Partial<WifiConfiguration> | null;
|
||||
}
|
||||
|
||||
interface DockerNetwork {
|
||||
@ -27,7 +27,7 @@ interface DockerNetwork {
|
||||
interface: string;
|
||||
}
|
||||
|
||||
interface AccessPoint {
|
||||
export interface AccessPoint {
|
||||
mode: "infrastructure" | "mesh" | "adhoc" | "ap";
|
||||
ssid: string;
|
||||
mac: string;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import "@material/mwc-tab";
|
||||
import "@material/mwc-tab-bar";
|
||||
import { mdiDeleteOutline, mdiPlus, mdiMenuDown } from "@mdi/js";
|
||||
import { mdiDeleteOutline, mdiPlus, mdiMenuDown, mdiWifi } from "@mdi/js";
|
||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { cache } from "lit/directives/cache";
|
||||
@ -20,7 +20,7 @@ import "../../../components/ha-textfield";
|
||||
import type { HaTextField } from "../../../components/ha-textfield";
|
||||
import { extractApiErrorMessage } from "../../../data/hassio/common";
|
||||
import {
|
||||
AccessPoints,
|
||||
AccessPoint,
|
||||
accesspointScan,
|
||||
fetchNetworkInfo,
|
||||
formatAddress,
|
||||
@ -58,7 +58,7 @@ const PREDEFINED_DNS = {
|
||||
export class HassioNetwork extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _accessPoints?: AccessPoints;
|
||||
@state() private _accessPoints: AccessPoint[] = [];
|
||||
|
||||
@state() private _curTabIndex = 0;
|
||||
|
||||
@ -113,7 +113,7 @@ export class HassioNetwork extends LitElement {
|
||||
</mwc-tab>`
|
||||
)}
|
||||
</mwc-tab-bar>`
|
||||
: ""}
|
||||
: nothing}
|
||||
${cache(this._renderTab())}
|
||||
</ha-card>
|
||||
`;
|
||||
@ -121,9 +121,6 @@ export class HassioNetwork extends LitElement {
|
||||
|
||||
private _renderTab() {
|
||||
return html`<div class="card-content">
|
||||
${IP_VERSIONS.map((version) =>
|
||||
this._interface![version] ? this._renderIPConfiguration(version) : ""
|
||||
)}
|
||||
${this._interface?.type === "wireless"
|
||||
? html`
|
||||
<ha-expansion-panel
|
||||
@ -131,15 +128,17 @@ export class HassioNetwork extends LitElement {
|
||||
"ui.panel.config.network.supervisor.wifi"
|
||||
)}
|
||||
outlined
|
||||
.expanded=${!this._interface?.wifi?.ssid}
|
||||
>
|
||||
${this._interface?.wifi?.ssid
|
||||
? html`<p>
|
||||
<ha-svg-icon slot="icon" .path=${mdiWifi}></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.network.supervisor.connected_to",
|
||||
{ ssid: this._interface?.wifi?.ssid }
|
||||
)}
|
||||
</p>`
|
||||
: ""}
|
||||
: nothing}
|
||||
<ha-button
|
||||
class="scan"
|
||||
@click=${this._scanForAP}
|
||||
@ -151,37 +150,34 @@ export class HassioNetwork extends LitElement {
|
||||
: this.hass.localize(
|
||||
"ui.panel.config.network.supervisor.scan_ap"
|
||||
)}
|
||||
<ha-svg-icon slot="icon" .path=${mdiWifi}></ha-svg-icon>
|
||||
</ha-button>
|
||||
${this._accessPoints &&
|
||||
this._accessPoints.accesspoints &&
|
||||
this._accessPoints.accesspoints.length !== 0
|
||||
${this._accessPoints.length
|
||||
? html`
|
||||
<mwc-list>
|
||||
${this._accessPoints.accesspoints
|
||||
.filter((ap) => ap.ssid)
|
||||
.map(
|
||||
(ap) => html`
|
||||
<ha-list-item
|
||||
twoline
|
||||
@click=${this._selectAP}
|
||||
.activated=${ap.ssid ===
|
||||
this._wifiConfiguration?.ssid}
|
||||
.ap=${ap}
|
||||
>
|
||||
<span>${ap.ssid}</span>
|
||||
<span slot="secondary">
|
||||
${ap.mac} -
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.network.supervisor.signal_strength"
|
||||
)}:
|
||||
${ap.signal}
|
||||
</span>
|
||||
</ha-list-item>
|
||||
`
|
||||
)}
|
||||
${this._accessPoints.map(
|
||||
(ap) => html`
|
||||
<ha-list-item
|
||||
twoline
|
||||
@click=${this._selectAP}
|
||||
.activated=${ap.ssid ===
|
||||
this._wifiConfiguration?.ssid}
|
||||
.ap=${ap}
|
||||
>
|
||||
<span>${ap.ssid}</span>
|
||||
<span slot="secondary">
|
||||
${ap.mac} -
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.network.supervisor.signal_strength"
|
||||
)}:
|
||||
${ap.signal}
|
||||
</span>
|
||||
</ha-list-item>
|
||||
`
|
||||
)}
|
||||
</mwc-list>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${this._wifiConfiguration
|
||||
? html`
|
||||
<div class="radio-row">
|
||||
@ -244,19 +240,24 @@ export class HassioNetwork extends LitElement {
|
||||
>
|
||||
</ha-password-field>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
</ha-expansion-panel>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
${IP_VERSIONS.map((version) =>
|
||||
this._interface![version]
|
||||
? this._renderIPConfiguration(version)
|
||||
: nothing
|
||||
)}
|
||||
${this._dirty
|
||||
? html`<ha-alert alert-type="warning">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.network.supervisor.warning"
|
||||
)}
|
||||
</ha-alert>`
|
||||
: ""}
|
||||
: nothing}
|
||||
</div>
|
||||
<div class="card-actions">
|
||||
<ha-button @click=${this._updateNetwork} .disabled=${!this._dirty}>
|
||||
@ -265,11 +266,19 @@ export class HassioNetwork extends LitElement {
|
||||
</ha-circular-progress>`
|
||||
: this.hass.localize("ui.common.save")}
|
||||
</ha-button>
|
||||
<ha-button @click=${this._clear}>
|
||||
${this.hass.localize("ui.panel.config.network.supervisor.reset")}
|
||||
</ha-button>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
private _selectAP(event) {
|
||||
this._wifiConfiguration = event.currentTarget.ap;
|
||||
IP_VERSIONS.forEach((version) => {
|
||||
if (this._interface![version]!.method === "disabled") {
|
||||
this._interface![version]!.method = "auto";
|
||||
}
|
||||
});
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
@ -279,10 +288,22 @@ export class HassioNetwork extends LitElement {
|
||||
}
|
||||
this._scanning = true;
|
||||
try {
|
||||
this._accessPoints = await accesspointScan(
|
||||
this.hass,
|
||||
this._interface.interface
|
||||
);
|
||||
const aps = await accesspointScan(this.hass, this._interface.interface);
|
||||
this._accessPoints = [];
|
||||
aps.accesspoints?.forEach((ap) => {
|
||||
if (ap.ssid) {
|
||||
// filter out duplicates
|
||||
const existing = this._accessPoints.find((a) => a.ssid === ap.ssid);
|
||||
if (!existing) {
|
||||
this._accessPoints.push(ap);
|
||||
} else if (ap.signal > existing.signal) {
|
||||
this._accessPoints = this._accessPoints.filter(
|
||||
(a) => a.ssid !== ap.ssid
|
||||
);
|
||||
this._accessPoints.push(ap);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (err: any) {
|
||||
showAlertDialog(this, {
|
||||
title: "Failed to scan for accesspoints",
|
||||
@ -294,6 +315,13 @@ export class HassioNetwork extends LitElement {
|
||||
}
|
||||
|
||||
private _renderIPConfiguration(version: string) {
|
||||
const watingForSSID =
|
||||
this._interface?.type === "wireless" &&
|
||||
!this._wifiConfiguration?.ssid &&
|
||||
!this._interface.wifi?.ssid;
|
||||
if (watingForSSID) {
|
||||
return nothing;
|
||||
}
|
||||
const nameservers = this._interface![version]?.nameservers || [];
|
||||
if (nameservers.length === 0) {
|
||||
nameservers.push(""); // always show input
|
||||
@ -484,7 +512,7 @@ export class HassioNetwork extends LitElement {
|
||||
</ha-list-item>
|
||||
</ha-button-menu>
|
||||
`
|
||||
: ""}
|
||||
: nothing}
|
||||
</ha-expansion-panel>
|
||||
`;
|
||||
}
|
||||
@ -529,9 +557,13 @@ export class HassioNetwork extends LitElement {
|
||||
}
|
||||
|
||||
interfaceOptions.enabled =
|
||||
this._wifiConfiguration !== undefined ||
|
||||
interfaceOptions.ipv4?.method !== "disabled" ||
|
||||
interfaceOptions.ipv6?.method !== "disabled";
|
||||
// at least one ip version is enabled
|
||||
(interfaceOptions.ipv4?.method !== "disabled" ||
|
||||
interfaceOptions.ipv6?.method !== "disabled") &&
|
||||
// require connection if this is a wireless interface
|
||||
(this._interface!.type !== "wireless" ||
|
||||
this._wifiConfiguration !== undefined ||
|
||||
!!this._interface!.wifi);
|
||||
|
||||
try {
|
||||
await updateNetworkInterface(
|
||||
@ -540,6 +572,7 @@ export class HassioNetwork extends LitElement {
|
||||
interfaceOptions
|
||||
);
|
||||
this._dirty = false;
|
||||
await this._fetchNetworkInfo();
|
||||
} catch (err: any) {
|
||||
showAlertDialog(this, {
|
||||
title: this.hass.localize(
|
||||
@ -552,6 +585,20 @@ export class HassioNetwork extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private async _clear() {
|
||||
await this._fetchNetworkInfo();
|
||||
this._interface!.ipv4!.method = "auto";
|
||||
this._interface!.ipv4!.nameservers = [];
|
||||
this._interface!.ipv6!.method = "auto";
|
||||
this._interface!.ipv6!.nameservers = [];
|
||||
// removing the connection will disable the interface
|
||||
// this is the only way to forget the wifi network right now
|
||||
this._interface!.wifi = null;
|
||||
this._wifiConfiguration = undefined;
|
||||
this._dirty = true;
|
||||
this.requestUpdate("_interface");
|
||||
}
|
||||
|
||||
private async _handleTabActivated(ev: CustomEvent): Promise<void> {
|
||||
if (this._dirty) {
|
||||
const confirm = await showConfirmationDialog(this, {
|
||||
|
@ -5225,7 +5225,8 @@
|
||||
"supervisor": {
|
||||
"title": "Configure network interfaces",
|
||||
"connected_to": "Connected to {ssid}",
|
||||
"scan_ap": "Scan for access points",
|
||||
"scan_ap": "Search networks",
|
||||
"reset": "Reset configuration",
|
||||
"signal_strength": "Signal strength",
|
||||
"open": "Open",
|
||||
"wep": "WEP",
|
||||
|
Loading…
x
Reference in New Issue
Block a user