diff --git a/src/components/ewt-list-item.ts b/src/components/ewt-list-item.ts
new file mode 100644
index 0000000..6494d8e
--- /dev/null
+++ b/src/components/ewt-list-item.ts
@@ -0,0 +1,14 @@
+import { ListItemBase } from "@material/mwc-list/mwc-list-item-base";
+import { styles } from "@material/mwc-list/mwc-list-item.css";
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ewt-list-item": EwtListItem;
+ }
+}
+
+export class EwtListItem extends ListItemBase {
+ static override styles = [styles];
+}
+
+customElements.define("ewt-list-item", EwtListItem);
diff --git a/src/components/ewt-select.ts b/src/components/ewt-select.ts
new file mode 100644
index 0000000..25bd95d
--- /dev/null
+++ b/src/components/ewt-select.ts
@@ -0,0 +1,14 @@
+import { SelectBase } from "@material/mwc-select/mwc-select-base";
+import { styles } from "@material/mwc-select/mwc-select.css";
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ewt-select": EwtSelect;
+ }
+}
+
+export class EwtSelect extends SelectBase {
+ static override styles = [styles];
+}
+
+customElements.define("ewt-select", EwtSelect);
diff --git a/src/install-dialog.ts b/src/install-dialog.ts
index 3dca2f1..b4a2170 100644
--- a/src/install-dialog.ts
+++ b/src/install-dialog.ts
@@ -7,12 +7,14 @@ import "./components/ewt-dialog";
import "./components/ewt-formfield";
import "./components/ewt-icon-button";
import "./components/ewt-textfield";
+import type { EwtTextfield } from "./components/ewt-textfield";
+import "./components/ewt-select";
+import "./components/ewt-list-item";
import "./pages/ewt-page-progress";
import "./pages/ewt-page-message";
import { chipIcon, closeIcon, firmwareIcon } from "./components/svg";
-import type { EwtTextfield } from "./components/ewt-textfield";
import { Logger, Manifest, FlashStateType, FlashState } from "./const.js";
-import { ImprovSerial } from "improv-wifi-serial-sdk/dist/serial";
+import { ImprovSerial, Ssid } from "improv-wifi-serial-sdk/dist/serial";
import {
ImprovSerialCurrentState,
ImprovSerialErrorState,
@@ -61,6 +63,13 @@ class EwtInstallDialog extends LitElement {
@state() private _busy = false;
+ // undefined = not loaded
+ // null = not available
+ @state() private _ssids?: Ssid[] | null;
+
+ // -1 = custom
+ @state() private _selectedSsid = -1;
+
protected render() {
if (!this.port) {
return html``;
@@ -296,7 +305,15 @@ class EwtInstallDialog extends LitElement {
let hideActions = false;
if (this._busy) {
- return [heading, this._renderProgress("Trying to connect"), true];
+ return [
+ heading,
+ this._renderProgress(
+ this._ssids === undefined
+ ? "Scanning for networks"
+ : "Trying to connect"
+ ),
+ true,
+ ];
}
if (
@@ -356,7 +373,6 @@ class EwtInstallDialog extends LitElement {
label="Skip"
@click=${() => {
this._state = "DASHBOARD";
- this._installState = undefined;
}}
>
@@ -392,7 +408,46 @@ class EwtInstallDialog extends LitElement {
to connect to.
${error ? html`
${error}
` : ""}
-
+ ${this._ssids !== null
+ ? html`
+ {
+ const index = ev.detail.index;
+ // The "Join Other" item is always the last item.
+ this._selectedSsid =
+ index === this._ssids!.length ? -1 : index;
+ }}
+ @closed=${(ev: Event) => ev.stopPropagation()}
+ >
+ ${this._ssids!.map(
+ (info, idx) => html`
+
+ ${info.name}
+
+ `
+ )}
+
+ Join other…
+
+
+ `
+ : ""}
+ ${
+ // Show input box if command not supported or "Join Other" selected
+ this._selectedSsid === -1
+ ? html`
+
+ `
+ : ""
+ }
{
- this._installState = undefined;
this._state = "DASHBOARD";
}}
>
@@ -565,7 +619,6 @@ class EwtInstallDialog extends LitElement {
@click=${async () => {
this._initialize();
this._state = "DASHBOARD";
- this._installState = undefined;
}}
>
`;
@@ -622,9 +675,31 @@ class EwtInstallDialog extends LitElement {
if (this._state !== "ERROR") {
this._error = undefined;
}
- if (this._state !== "PROVISION") {
+ // Scan for SSIDs on provision
+ if (this._state === "PROVISION") {
+ this._ssids = undefined;
+ this._busy = true;
+ this._client!.scan().then(
+ (ssids) => {
+ this._busy = false;
+ this._ssids = ssids;
+ this._selectedSsid = ssids.length ? 0 : -1;
+ },
+ () => {
+ this._busy = false;
+ this._ssids = null;
+ this._selectedSsid = -1;
+ }
+ );
+ } else {
+ // Reset this value if we leave provisioning.
this._provisionForce = false;
}
+
+ if (this._state === "INSTALL") {
+ this._installConfirmed = false;
+ this._installState = undefined;
+ }
}
protected override firstUpdated(changedProps: PropertyValues) {
@@ -635,20 +710,29 @@ class EwtInstallDialog extends LitElement {
protected override updated(changedProps: PropertyValues) {
super.updated(changedProps);
- if (!changedProps.has("_state")) {
+ if (changedProps.has("_state")) {
+ this.setAttribute("state", this._state);
+ }
+
+ if (this._state !== "PROVISION") {
return;
}
- this.setAttribute("state", this._state);
+ if (changedProps.has("_selectedSsid") && this._selectedSsid === -1) {
+ // If we pick "Join other", select SSID input.
+ this._focusFormElement("ewt-textfield[name=ssid]");
+ } else if (changedProps.has("_ssids")) {
+ // Form is shown when SSIDs are loaded/marked not supported
+ this._focusFormElement();
+ }
+ }
- if (this._state === "PROVISION") {
- const textfield = this.shadowRoot!.querySelector("ewt-textfield");
- if (textfield) {
- textfield.updateComplete.then(() => textfield.focus());
- }
- } else if (this._state === "INSTALL") {
- this._installConfirmed = false;
- this._installState = undefined;
+ private _focusFormElement(selector = "ewt-textfield, ewt-select") {
+ const formEl = this.shadowRoot!.querySelector(
+ selector
+ ) as LitElement | null;
+ if (formEl) {
+ formEl.updateComplete.then(() => setTimeout(() => formEl.focus(), 100));
}
}
@@ -738,9 +822,14 @@ class EwtInstallDialog extends LitElement {
this._busy = true;
this._wasProvisioned =
this._client!.state === ImprovSerialCurrentState.PROVISIONED;
- const ssid = (
- this.shadowRoot!.querySelector("ewt-textfield[name=ssid]") as EwtTextfield
- ).value;
+ const ssid =
+ this._selectedSsid === -1
+ ? (
+ this.shadowRoot!.querySelector(
+ "ewt-textfield[name=ssid]"
+ ) as EwtTextfield
+ ).value
+ : this._ssids![this._selectedSsid].name;
const password = (
this.shadowRoot!.querySelector(
"ewt-textfield[name=password]"
@@ -810,7 +899,8 @@ class EwtInstallDialog extends LitElement {
width: 20px;
margin-right: 8px;
}
- ewt-textfield {
+ ewt-textfield,
+ ewt-select {
display: block;
margin-top: 16px;
}