Skip to content

Commit d976ab0

Browse files
authored
Show a dialog when no port is selected (#187)
1 parent e697859 commit d976ab0

File tree

8 files changed

+153
-25
lines changed

8 files changed

+153
-25
lines changed

src/install-choose/install-choose-dialog.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,16 +306,16 @@ class ESPHomeInstallChooseDialog extends LitElement {
306306
this._close();
307307
}
308308

309-
private async _handleBrowserInstall() {
309+
private _handleBrowserInstall() {
310310
if (!supportsWebSerial || !allowsWebSerial) {
311311
this._storeDialogWidth();
312312
this._state = "web_instructions";
313313
return;
314314
}
315315

316-
if (await openInstallWebDialog({ configuration: this.configuration })) {
317-
this._close();
318-
}
316+
openInstallWebDialog({ configuration: this.configuration }, () =>
317+
this._close()
318+
);
319319
}
320320

321321
private _close() {

src/install-web/index.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import { connect, ESPLoader } from "esp-web-flasher";
2+
import { openNoPortPickedDialog } from "../no-port-picked";
23
import type { ESPHomeInstallWebDialog } from "./install-web-dialog";
34

45
const preload = () => import("./install-web-dialog");
56

67
export const openInstallWebDialog = async (
7-
params: ESPHomeInstallWebDialog["params"]
8-
): Promise<boolean> => {
8+
params: ESPHomeInstallWebDialog["params"],
9+
// Called if a port has been picked and the dialog will be opened.
10+
onDialogOpen?: () => void
11+
): Promise<void> => {
912
preload();
1013

1114
let esploader: ESPLoader;
@@ -16,16 +19,23 @@ export const openInstallWebDialog = async (
1619
try {
1720
esploader = await connect(console);
1821
} catch (err: any) {
19-
if ((err as DOMException).name !== "NotFoundError") {
22+
if ((err as DOMException).name === "NotFoundError") {
23+
openNoPortPickedDialog(() =>
24+
openInstallWebDialog(params, onDialogOpen)
25+
);
26+
} else {
2027
alert(`Unable to connect: ${err.message}`);
2128
}
22-
return false;
29+
return;
2330
}
2431
}
2532

33+
if (onDialogOpen) {
34+
onDialogOpen();
35+
}
36+
2637
const dialog = document.createElement("esphome-install-web-dialog");
2738
dialog.params = params;
2839
dialog.esploader = esploader;
2940
document.body.append(dialog);
30-
return true;
3141
};

src/install-web/install-web-dialog.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,8 @@ export class ESPHomeInstallWebDialog extends LitElement {
164164
this._close();
165165
}
166166

167-
private async _handleRetry() {
168-
if (await openInstallWebDialog(this.params)) {
169-
this._close();
170-
}
167+
private _handleRetry() {
168+
openInstallWebDialog(this.params, () => this._close());
171169
}
172170

173171
private async _handleInstall() {

src/no-port-picked/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const preload = () => import("./no-port-picked-dialog");
2+
3+
export const openNoPortPickedDialog = async (
4+
doTryAgain?: () => void
5+
): Promise<boolean> => {
6+
preload();
7+
8+
const dialog = document.createElement("esphome-no-port-picked-dialog");
9+
dialog.doTryAgain = doTryAgain;
10+
document.body.append(dialog);
11+
return true;
12+
};
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { LitElement, html, css } from "lit";
2+
import { customElement } from "lit/decorators.js";
3+
import "@material/mwc-dialog";
4+
import "@material/mwc-list/mwc-list-item.js";
5+
import "@material/mwc-circular-progress";
6+
import "@material/mwc-button";
7+
8+
@customElement("esphome-no-port-picked-dialog")
9+
class ESPHomeNoPortPickedDialog extends LitElement {
10+
public doTryAgain?: () => void;
11+
12+
public render() {
13+
return html`
14+
<mwc-dialog
15+
open
16+
heading="No port selected"
17+
scrimClickAction
18+
@closed=${this._handleClose}
19+
>
20+
<p>
21+
If you didn't select a port because you didn't see your device listed,
22+
try the following steps:
23+
</p>
24+
<ol>
25+
<li>
26+
Make sure that the device is connected to this computer (the one
27+
that runs the browser that shows this website)
28+
</li>
29+
<li>
30+
Most devices have a tiny light when it is powered on. Make sure it
31+
is on.
32+
</li>
33+
<li>
34+
Make sure you have the right drivers installed. Below are the
35+
drivers for common chips used in ESP devices:
36+
<ul>
37+
<li>
38+
CP2102 (square chip):
39+
<a
40+
href="https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers"
41+
target="_blank"
42+
rel="noopener"
43+
>driver</a
44+
>
45+
</li>
46+
<li>
47+
CH341:
48+
<a
49+
href="https://github.com/nodemcu/nodemcu-devkit/tree/master/Drivers"
50+
target="_blank"
51+
rel="noopener"
52+
>driver</a
53+
>
54+
</li>
55+
</ul>
56+
</li>
57+
</ol>
58+
${this.doTryAgain
59+
? html`
60+
<mwc-button
61+
slot="primaryAction"
62+
dialogAction="close"
63+
label="Try Again"
64+
@click=${this.doTryAgain}
65+
></mwc-button>
66+
67+
<mwc-button
68+
no-attention
69+
slot="secondaryAction"
70+
dialogAction="close"
71+
label="Cancel"
72+
></mwc-button>
73+
`
74+
: html`
75+
<mwc-button
76+
slot="primaryAction"
77+
dialogAction="close"
78+
label="Close"
79+
></mwc-button>
80+
`}
81+
</mwc-dialog>
82+
`;
83+
}
84+
85+
private async _handleClose() {
86+
this.parentNode!.removeChild(this);
87+
}
88+
89+
static styles = css`
90+
a {
91+
color: var(--mdc-theme-primary);
92+
}
93+
mwc-button[no-attention] {
94+
--mdc-theme-primary: #444;
95+
--mdc-theme-on-primary: white;
96+
}
97+
li + li,
98+
li > ul {
99+
margin-top: 8px;
100+
}
101+
`;
102+
}
103+
104+
declare global {
105+
interface HTMLElementTagNameMap {
106+
"esphome-no-port-picked-dialog": ESPHomeNoPortPickedDialog;
107+
}
108+
}

web.esphome.io/src/dashboard/connect-card.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { LitElement, html, css, PropertyValues } from "lit";
22
import { customElement, property } from "lit/decorators.js";
33
import "../../../src/components/esphome-card";
44
import { DOCS_WEBSERIAL } from "../../../src/const";
5+
import { openNoPortPickedDialog } from "../../../src/no-port-picked";
56
import "./device-card";
67

78
@customElement("ew-connect-card")
@@ -45,6 +46,7 @@ class EWConnectCard extends LitElement {
4546
port = await navigator.serial.requestPort();
4647
} catch (err: any) {
4748
if ((err as DOMException).name === "NotFoundError") {
49+
openNoPortPickedDialog();
4850
return;
4951
}
5052
alert(`Error: ${err.message}`);

web.esphome.io/src/install-adoptable/install-adoptable-dialog.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ class ESPHomeInstallAdoptableDialog extends LitElement {
4242
}
4343
4444
private async _handleInstall() {
45-
if (
46-
await openInstallWebDialog({
45+
openInstallWebDialog(
46+
{
4747
port: this.port,
4848
async filesCallback(platform: string): Promise<FileToFlash[]> {
4949
if (platform !== "ESP8266" && platform !== "ESP32") {
@@ -70,10 +70,9 @@ class ESPHomeInstallAdoptableDialog extends LitElement {
7070
improv.port = this.port;
7171
document.body.appendChild(improv);
7272
},
73-
})
74-
) {
75-
this._close();
76-
}
73+
},
74+
() => this._close()
75+
);
7776
}
7877
7978
private _close() {

web.esphome.io/src/install-upload/install-upload-dialog.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,14 @@ class ESPHomeInstallUploadDialog extends LitElement {
6060
},
6161
];
6262

63-
if (
64-
await openInstallWebDialog({
63+
openInstallWebDialog(
64+
{
6565
port: this.port,
6666
erase: true,
6767
filesCallback: async () => files,
68-
})
69-
) {
70-
this._close();
71-
}
68+
},
69+
() => this._close()
70+
);
7271
}
7372

7473
private _close() {

0 commit comments

Comments
 (0)