tasmota-esp-web-tools 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devcontainer/Dockerfile +16 -0
- package/.devcontainer/devcontainer.json +44 -0
- package/.github/dependabot.yml +10 -0
- package/.github/release-drafter.yml +12 -0
- package/.github/workflows/ci.yml +22 -0
- package/.github/workflows/npmpublish.yml +22 -0
- package/.github/workflows/release-drafter.yml +14 -0
- package/.prettierignore +1 -0
- package/README.md +68 -0
- package/dist/components/ewt-button.d.ts +9 -0
- package/dist/components/ewt-button.js +17 -0
- package/dist/components/ewt-checkbox.d.ts +9 -0
- package/dist/components/ewt-checkbox.js +6 -0
- package/dist/components/ewt-circular-progress.d.ts +9 -0
- package/dist/components/ewt-circular-progress.js +6 -0
- package/dist/components/ewt-console.d.ts +20 -0
- package/dist/components/ewt-console.js +141 -0
- package/dist/components/ewt-dialog.d.ts +9 -0
- package/dist/components/ewt-dialog.js +14 -0
- package/dist/components/ewt-formfield.d.ts +9 -0
- package/dist/components/ewt-formfield.js +6 -0
- package/dist/components/ewt-icon-button.d.ts +9 -0
- package/dist/components/ewt-icon-button.js +6 -0
- package/dist/components/ewt-list-item.d.ts +9 -0
- package/dist/components/ewt-list-item.js +6 -0
- package/dist/components/ewt-select.d.ts +9 -0
- package/dist/components/ewt-select.js +15 -0
- package/dist/components/ewt-textfield.d.ts +9 -0
- package/dist/components/ewt-textfield.js +15 -0
- package/dist/components/svg.d.ts +3 -0
- package/dist/components/svg.js +24 -0
- package/dist/connect.d.ts +3 -0
- package/dist/connect.js +33 -0
- package/dist/const.d.ts +94 -0
- package/dist/const.js +1 -0
- package/dist/flash.d.ts +4 -0
- package/dist/flash.js +191 -0
- package/dist/install-button.d.ts +17 -0
- package/dist/install-button.js +96 -0
- package/dist/install-dialog.d.ts +70 -0
- package/dist/install-dialog.js +899 -0
- package/dist/no-port-picked/index.d.ts +2 -0
- package/dist/no-port-picked/index.js +7 -0
- package/dist/no-port-picked/no-port-picked-dialog.d.ts +15 -0
- package/dist/no-port-picked/no-port-picked-dialog.js +149 -0
- package/dist/pages/ewt-page-message.d.ts +14 -0
- package/dist/pages/ewt-page-message.js +34 -0
- package/dist/pages/ewt-page-progress.d.ts +14 -0
- package/dist/pages/ewt-page-progress.js +39 -0
- package/dist/styles.d.ts +1 -0
- package/dist/styles.js +32 -0
- package/dist/util/chip-family-name.d.ts +3 -0
- package/dist/util/chip-family-name.js +17 -0
- package/dist/util/console-color.d.ts +19 -0
- package/dist/util/console-color.js +265 -0
- package/dist/util/file-download.d.ts +2 -0
- package/dist/util/file-download.js +15 -0
- package/dist/util/fire-event.d.ts +5 -0
- package/dist/util/fire-event.js +12 -0
- package/dist/util/line-break-transformer.d.ts +5 -0
- package/dist/util/line-break-transformer.js +17 -0
- package/dist/util/manifest.d.ts +2 -0
- package/dist/util/manifest.js +12 -0
- package/dist/util/sleep.d.ts +1 -0
- package/dist/util/sleep.js +1 -0
- package/dist/web/connect-3012e6dd.js +886 -0
- package/dist/web/esp32-5f88817f.js +1 -0
- package/dist/web/esp32c3-596796ad.js +1 -0
- package/dist/web/esp32s2-f7a69530.js +1 -0
- package/dist/web/esp32s3-314fbacd.js +1 -0
- package/dist/web/esp8266-c68f89af.js +1 -0
- package/dist/web/index-f110c132.js +126 -0
- package/dist/web/install-button.js +1 -0
- package/package.json +36 -0
- package/rollup.config.js +28 -0
- package/script/build +8 -0
- package/script/develop +17 -0
- package/script/stubgen.py +161 -0
- package/src/components/ewt-button.ts +25 -0
- package/src/components/ewt-checkbox.ts +14 -0
- package/src/components/ewt-circular-progress.ts +14 -0
- package/src/components/ewt-console.ts +163 -0
- package/src/components/ewt-dialog.ts +22 -0
- package/src/components/ewt-formfield.ts +14 -0
- package/src/components/ewt-icon-button.ts +14 -0
- package/src/components/ewt-list-item.ts +14 -0
- package/src/components/ewt-select.ts +23 -0
- package/src/components/ewt-textfield.ts +23 -0
- package/src/components/svg.ts +27 -0
- package/src/connect.ts +42 -0
- package/src/const.ts +101 -0
- package/src/flash.ts +240 -0
- package/src/install-button.ts +128 -0
- package/src/install-dialog.ts +981 -0
- package/src/no-port-picked/index.ts +10 -0
- package/src/no-port-picked/no-port-picked-dialog.ts +158 -0
- package/src/pages/ewt-page-message.ts +39 -0
- package/src/pages/ewt-page-progress.ts +44 -0
- package/src/styles.ts +34 -0
- package/src/util/chip-family-name.ts +28 -0
- package/src/util/console-color.ts +283 -0
- package/src/util/file-download.ts +17 -0
- package/src/util/fire-event.ts +20 -0
- package/src/util/line-break-transformer.ts +20 -0
- package/src/util/manifest.ts +18 -0
- package/src/util/sleep.ts +2 -0
- package/static/logos/canairio.png +0 -0
- package/static/logos/espeasy.png +0 -0
- package/static/logos/esphome.svg +1 -0
- package/static/logos/tasmota.svg +1 -0
- package/static/logos/wled.png +0 -0
- package/static/screenshots/dashboard.png +0 -0
- package/static/screenshots/logs.png +0 -0
- package/static/social.png +0 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,899 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { LitElement, html, css } from "lit";
|
|
3
|
+
import { state } from "lit/decorators.js";
|
|
4
|
+
import "./components/ewt-button";
|
|
5
|
+
import "./components/ewt-checkbox";
|
|
6
|
+
import "./components/ewt-console";
|
|
7
|
+
import "./components/ewt-dialog";
|
|
8
|
+
import "./components/ewt-formfield";
|
|
9
|
+
import "./components/ewt-icon-button";
|
|
10
|
+
import "./components/ewt-textfield";
|
|
11
|
+
import "./components/ewt-select";
|
|
12
|
+
import "./components/ewt-list-item";
|
|
13
|
+
import "./pages/ewt-page-progress";
|
|
14
|
+
import "./pages/ewt-page-message";
|
|
15
|
+
import { chipIcon, closeIcon, firmwareIcon } from "./components/svg";
|
|
16
|
+
import { ImprovSerial } from "improv-wifi-serial-sdk/dist/serial";
|
|
17
|
+
import { ImprovSerialCurrentState, PortNotReady, } from "improv-wifi-serial-sdk/dist/const";
|
|
18
|
+
import { flash } from "./flash";
|
|
19
|
+
import { textDownload } from "./util/file-download";
|
|
20
|
+
import { fireEvent } from "./util/fire-event";
|
|
21
|
+
import { sleep } from "./util/sleep";
|
|
22
|
+
import { downloadManifest } from "./util/manifest";
|
|
23
|
+
import { dialogStyles } from "./styles";
|
|
24
|
+
const ERROR_ICON = "⚠️";
|
|
25
|
+
const OK_ICON = "🎉";
|
|
26
|
+
export class EwtInstallDialog extends LitElement {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments);
|
|
29
|
+
this.logger = console;
|
|
30
|
+
this._state = "DASHBOARD";
|
|
31
|
+
this._installErase = false;
|
|
32
|
+
this._installConfirmed = false;
|
|
33
|
+
this._provisionForce = false;
|
|
34
|
+
this._wasProvisioned = false;
|
|
35
|
+
this._busy = false;
|
|
36
|
+
// -1 = custom
|
|
37
|
+
this._selectedSsid = -1;
|
|
38
|
+
this._handleDisconnect = () => {
|
|
39
|
+
this._state = "ERROR";
|
|
40
|
+
this._error = "Disconnected";
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
render() {
|
|
44
|
+
if (!this.port) {
|
|
45
|
+
return html ``;
|
|
46
|
+
}
|
|
47
|
+
let heading;
|
|
48
|
+
let content;
|
|
49
|
+
let hideActions = false;
|
|
50
|
+
let allowClosing = false;
|
|
51
|
+
// During installation phase we temporarily remove the client
|
|
52
|
+
if (this._client === undefined &&
|
|
53
|
+
this._state !== "INSTALL" &&
|
|
54
|
+
this._state !== "LOGS") {
|
|
55
|
+
if (this._error) {
|
|
56
|
+
[heading, content, hideActions] = this._renderError(this._error);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
content = this._renderProgress("Connecting");
|
|
60
|
+
hideActions = true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else if (this._state === "INSTALL") {
|
|
64
|
+
[heading, content, hideActions, allowClosing] = this._renderInstall();
|
|
65
|
+
}
|
|
66
|
+
else if (this._state === "ASK_ERASE") {
|
|
67
|
+
[heading, content] = this._renderAskErase();
|
|
68
|
+
}
|
|
69
|
+
else if (this._state === "ERROR") {
|
|
70
|
+
[heading, content, hideActions] = this._renderError(this._error);
|
|
71
|
+
}
|
|
72
|
+
else if (this._state === "DASHBOARD") {
|
|
73
|
+
[heading, content, hideActions, allowClosing] = this._client
|
|
74
|
+
? this._renderDashboard()
|
|
75
|
+
: this._renderDashboardNoImprov();
|
|
76
|
+
}
|
|
77
|
+
else if (this._state === "PROVISION") {
|
|
78
|
+
[heading, content, hideActions] = this._renderProvision();
|
|
79
|
+
}
|
|
80
|
+
else if (this._state === "LOGS") {
|
|
81
|
+
[heading, content, hideActions] = this._renderLogs();
|
|
82
|
+
}
|
|
83
|
+
return html `
|
|
84
|
+
<ewt-dialog
|
|
85
|
+
open
|
|
86
|
+
.heading=${heading}
|
|
87
|
+
scrimClickAction
|
|
88
|
+
@closed=${this._handleClose}
|
|
89
|
+
.hideActions=${hideActions}
|
|
90
|
+
>
|
|
91
|
+
${heading && allowClosing
|
|
92
|
+
? html `
|
|
93
|
+
<ewt-icon-button dialogAction="close">
|
|
94
|
+
${closeIcon}
|
|
95
|
+
</ewt-icon-button>
|
|
96
|
+
`
|
|
97
|
+
: ""}
|
|
98
|
+
${content}
|
|
99
|
+
</ewt-dialog>
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
_renderProgress(label, progress) {
|
|
103
|
+
return html `
|
|
104
|
+
<ewt-page-progress
|
|
105
|
+
.label=${label}
|
|
106
|
+
.progress=${progress}
|
|
107
|
+
></ewt-page-progress>
|
|
108
|
+
`;
|
|
109
|
+
}
|
|
110
|
+
_renderError(label) {
|
|
111
|
+
const heading = "Error";
|
|
112
|
+
const content = html `
|
|
113
|
+
<ewt-page-message .icon=${ERROR_ICON} .label=${label}></ewt-page-message>
|
|
114
|
+
<ewt-button
|
|
115
|
+
slot="primaryAction"
|
|
116
|
+
dialogAction="ok"
|
|
117
|
+
label="Close"
|
|
118
|
+
></ewt-button>
|
|
119
|
+
`;
|
|
120
|
+
const hideActions = false;
|
|
121
|
+
return [heading, content, hideActions];
|
|
122
|
+
}
|
|
123
|
+
_renderDashboard() {
|
|
124
|
+
const heading = this._info.name;
|
|
125
|
+
let content;
|
|
126
|
+
let hideActions = true;
|
|
127
|
+
let allowClosing = true;
|
|
128
|
+
content = html `
|
|
129
|
+
<div class="table-row">
|
|
130
|
+
${firmwareIcon}
|
|
131
|
+
<div>${this._info.firmware} ${this._info.version}</div>
|
|
132
|
+
</div>
|
|
133
|
+
<div class="table-row last">
|
|
134
|
+
${chipIcon}
|
|
135
|
+
<div>${this._info.chipFamily}</div>
|
|
136
|
+
</div>
|
|
137
|
+
<div class="dashboard-buttons">
|
|
138
|
+
${!this._isSameVersion
|
|
139
|
+
? html `
|
|
140
|
+
<div>
|
|
141
|
+
<ewt-button
|
|
142
|
+
text-left
|
|
143
|
+
.label=${!this._isSameFirmware
|
|
144
|
+
? `Install ${this._manifest.name}`
|
|
145
|
+
: `Update ${this._manifest.name}`}
|
|
146
|
+
@click=${() => {
|
|
147
|
+
if (this._isSameFirmware) {
|
|
148
|
+
this._startInstall(false);
|
|
149
|
+
}
|
|
150
|
+
else if (this._manifest.new_install_prompt_erase) {
|
|
151
|
+
this._state = "ASK_ERASE";
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
this._startInstall(true);
|
|
155
|
+
}
|
|
156
|
+
}}
|
|
157
|
+
></ewt-button>
|
|
158
|
+
</div>
|
|
159
|
+
`
|
|
160
|
+
: ""}
|
|
161
|
+
${this._client.nextUrl === undefined
|
|
162
|
+
? ""
|
|
163
|
+
: html `
|
|
164
|
+
<div>
|
|
165
|
+
<a
|
|
166
|
+
href=${this._client.nextUrl}
|
|
167
|
+
class="has-button"
|
|
168
|
+
target="_blank"
|
|
169
|
+
>
|
|
170
|
+
<ewt-button label="Visit Device"></ewt-button>
|
|
171
|
+
</a>
|
|
172
|
+
</div>
|
|
173
|
+
`}
|
|
174
|
+
${!this._manifest.home_assistant_domain ||
|
|
175
|
+
this._client.state !== ImprovSerialCurrentState.PROVISIONED
|
|
176
|
+
? ""
|
|
177
|
+
: html `
|
|
178
|
+
<div>
|
|
179
|
+
<a
|
|
180
|
+
href=${`https://my.home-assistant.io/redirect/config_flow_start/?domain=${this._manifest.home_assistant_domain}`}
|
|
181
|
+
class="has-button"
|
|
182
|
+
target="_blank"
|
|
183
|
+
>
|
|
184
|
+
<ewt-button label="Add to Home Assistant"></ewt-button>
|
|
185
|
+
</a>
|
|
186
|
+
</div>
|
|
187
|
+
`}
|
|
188
|
+
<div>
|
|
189
|
+
<ewt-button
|
|
190
|
+
.label=${this._client.state === ImprovSerialCurrentState.READY
|
|
191
|
+
? "Connect to Wi-Fi"
|
|
192
|
+
: "Change Wi-Fi"}
|
|
193
|
+
@click=${() => {
|
|
194
|
+
this._state = "PROVISION";
|
|
195
|
+
if (this._client.state === ImprovSerialCurrentState.PROVISIONED) {
|
|
196
|
+
this._provisionForce = true;
|
|
197
|
+
}
|
|
198
|
+
}}
|
|
199
|
+
></ewt-button>
|
|
200
|
+
</div>
|
|
201
|
+
<div>
|
|
202
|
+
<ewt-button
|
|
203
|
+
label="Logs & Console"
|
|
204
|
+
@click=${async () => {
|
|
205
|
+
const client = this._client;
|
|
206
|
+
if (client) {
|
|
207
|
+
await this._closeClientWithoutEvents(client);
|
|
208
|
+
await sleep(100);
|
|
209
|
+
}
|
|
210
|
+
// Also set `null` back to undefined.
|
|
211
|
+
this._client = undefined;
|
|
212
|
+
this._state = "LOGS";
|
|
213
|
+
}}
|
|
214
|
+
></ewt-button>
|
|
215
|
+
</div>
|
|
216
|
+
${this._isSameFirmware && this._manifest.funding_url
|
|
217
|
+
? html `
|
|
218
|
+
<div>
|
|
219
|
+
<a
|
|
220
|
+
class="button"
|
|
221
|
+
href=${this._manifest.funding_url}
|
|
222
|
+
target="_blank"
|
|
223
|
+
>
|
|
224
|
+
<ewt-button label="Fund Development"></ewt-button>
|
|
225
|
+
</a>
|
|
226
|
+
</div>
|
|
227
|
+
`
|
|
228
|
+
: ""}
|
|
229
|
+
${this._isSameVersion
|
|
230
|
+
? html `
|
|
231
|
+
<div>
|
|
232
|
+
<ewt-button
|
|
233
|
+
class="danger"
|
|
234
|
+
label="Erase User Data"
|
|
235
|
+
@click=${() => this._startInstall(true)}
|
|
236
|
+
></ewt-button>
|
|
237
|
+
</div>
|
|
238
|
+
`
|
|
239
|
+
: ""}
|
|
240
|
+
</div>
|
|
241
|
+
`;
|
|
242
|
+
return [heading, content, hideActions, allowClosing];
|
|
243
|
+
}
|
|
244
|
+
_renderDashboardNoImprov() {
|
|
245
|
+
const heading = "Device Dashboard";
|
|
246
|
+
let content;
|
|
247
|
+
let hideActions = true;
|
|
248
|
+
let allowClosing = true;
|
|
249
|
+
content = html `
|
|
250
|
+
<div class="dashboard-buttons">
|
|
251
|
+
<div>
|
|
252
|
+
<ewt-button
|
|
253
|
+
text-left
|
|
254
|
+
.label=${`Install ${this._manifest.name}`}
|
|
255
|
+
@click=${() => {
|
|
256
|
+
if (this._manifest.new_install_prompt_erase) {
|
|
257
|
+
this._state = "ASK_ERASE";
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
// Default is to erase a device that does not support Improv Serial
|
|
261
|
+
this._startInstall(true);
|
|
262
|
+
}
|
|
263
|
+
}}
|
|
264
|
+
></ewt-button>
|
|
265
|
+
</div>
|
|
266
|
+
|
|
267
|
+
<div>
|
|
268
|
+
<ewt-button
|
|
269
|
+
label="Logs & Console"
|
|
270
|
+
@click=${async () => {
|
|
271
|
+
// Also set `null` back to undefined.
|
|
272
|
+
this._client = undefined;
|
|
273
|
+
this._state = "LOGS";
|
|
274
|
+
}}
|
|
275
|
+
></ewt-button>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
`;
|
|
279
|
+
return [heading, content, hideActions, allowClosing];
|
|
280
|
+
}
|
|
281
|
+
_renderProvision() {
|
|
282
|
+
let heading = "Configure Wi-Fi";
|
|
283
|
+
let content;
|
|
284
|
+
let hideActions = false;
|
|
285
|
+
if (this._busy) {
|
|
286
|
+
return [
|
|
287
|
+
heading,
|
|
288
|
+
this._renderProgress(this._ssids === undefined
|
|
289
|
+
? "Scanning for networks"
|
|
290
|
+
: "Trying to connect"),
|
|
291
|
+
true,
|
|
292
|
+
];
|
|
293
|
+
}
|
|
294
|
+
if (!this._provisionForce &&
|
|
295
|
+
this._client.state === ImprovSerialCurrentState.PROVISIONED) {
|
|
296
|
+
heading = undefined;
|
|
297
|
+
const showSetupLinks = !this._wasProvisioned &&
|
|
298
|
+
(this._client.nextUrl !== undefined ||
|
|
299
|
+
"home_assistant_domain" in this._manifest);
|
|
300
|
+
hideActions = showSetupLinks;
|
|
301
|
+
content = html `
|
|
302
|
+
<ewt-page-message
|
|
303
|
+
.icon=${OK_ICON}
|
|
304
|
+
label="Device connected to the network!"
|
|
305
|
+
></ewt-page-message>
|
|
306
|
+
${showSetupLinks
|
|
307
|
+
? html `
|
|
308
|
+
<div class="dashboard-buttons">
|
|
309
|
+
${this._client.nextUrl === undefined
|
|
310
|
+
? ""
|
|
311
|
+
: html `
|
|
312
|
+
<div>
|
|
313
|
+
<a
|
|
314
|
+
href=${this._client.nextUrl}
|
|
315
|
+
class="has-button"
|
|
316
|
+
target="_blank"
|
|
317
|
+
@click=${() => {
|
|
318
|
+
this._state = "DASHBOARD";
|
|
319
|
+
}}
|
|
320
|
+
>
|
|
321
|
+
<ewt-button label="Visit Device"></ewt-button>
|
|
322
|
+
</a>
|
|
323
|
+
</div>
|
|
324
|
+
`}
|
|
325
|
+
${!this._manifest.home_assistant_domain
|
|
326
|
+
? ""
|
|
327
|
+
: html `
|
|
328
|
+
<div>
|
|
329
|
+
<a
|
|
330
|
+
href=${`https://my.home-assistant.io/redirect/config_flow_start/?domain=${this._manifest.home_assistant_domain}`}
|
|
331
|
+
class="has-button"
|
|
332
|
+
target="_blank"
|
|
333
|
+
@click=${() => {
|
|
334
|
+
this._state = "DASHBOARD";
|
|
335
|
+
}}
|
|
336
|
+
>
|
|
337
|
+
<ewt-button
|
|
338
|
+
label="Add to Home Assistant"
|
|
339
|
+
></ewt-button>
|
|
340
|
+
</a>
|
|
341
|
+
</div>
|
|
342
|
+
`}
|
|
343
|
+
<div>
|
|
344
|
+
<ewt-button
|
|
345
|
+
label="Skip"
|
|
346
|
+
@click=${() => {
|
|
347
|
+
this._state = "DASHBOARD";
|
|
348
|
+
}}
|
|
349
|
+
></ewt-button>
|
|
350
|
+
</div>
|
|
351
|
+
</div>
|
|
352
|
+
`
|
|
353
|
+
: html `
|
|
354
|
+
<ewt-button
|
|
355
|
+
slot="primaryAction"
|
|
356
|
+
label="Continue"
|
|
357
|
+
@click=${() => {
|
|
358
|
+
this._state = "DASHBOARD";
|
|
359
|
+
}}
|
|
360
|
+
></ewt-button>
|
|
361
|
+
`}
|
|
362
|
+
`;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
let error;
|
|
366
|
+
switch (this._client.error) {
|
|
367
|
+
case 3 /* ImprovSerialErrorState.UNABLE_TO_CONNECT */:
|
|
368
|
+
error = "Unable to connect";
|
|
369
|
+
break;
|
|
370
|
+
case 0 /* ImprovSerialErrorState.NO_ERROR */:
|
|
371
|
+
// Happens when list SSIDs not supported.
|
|
372
|
+
case 2 /* ImprovSerialErrorState.UNKNOWN_RPC_COMMAND */:
|
|
373
|
+
break;
|
|
374
|
+
default:
|
|
375
|
+
error = `Unknown error (${this._client.error})`;
|
|
376
|
+
}
|
|
377
|
+
content = html `
|
|
378
|
+
<div>
|
|
379
|
+
Enter the credentials of the Wi-Fi network that you want your device
|
|
380
|
+
to connect to.
|
|
381
|
+
</div>
|
|
382
|
+
${error ? html `<p class="error">${error}</p>` : ""}
|
|
383
|
+
${this._ssids !== null
|
|
384
|
+
? html `
|
|
385
|
+
<ewt-select
|
|
386
|
+
fixedMenuPosition
|
|
387
|
+
label="Network"
|
|
388
|
+
@selected=${(ev) => {
|
|
389
|
+
const index = ev.detail.index;
|
|
390
|
+
// The "Join Other" item is always the last item.
|
|
391
|
+
this._selectedSsid =
|
|
392
|
+
index === this._ssids.length ? -1 : index;
|
|
393
|
+
}}
|
|
394
|
+
@closed=${(ev) => ev.stopPropagation()}
|
|
395
|
+
>
|
|
396
|
+
${this._ssids.map((info, idx) => html `
|
|
397
|
+
<ewt-list-item
|
|
398
|
+
.selected=${this._selectedSsid === idx}
|
|
399
|
+
value=${idx}
|
|
400
|
+
>
|
|
401
|
+
${info.name}
|
|
402
|
+
</ewt-list-item>
|
|
403
|
+
`)}
|
|
404
|
+
<ewt-list-item
|
|
405
|
+
.selected=${this._selectedSsid === -1}
|
|
406
|
+
value="-1"
|
|
407
|
+
>
|
|
408
|
+
Join other…
|
|
409
|
+
</ewt-list-item>
|
|
410
|
+
</ewt-select>
|
|
411
|
+
`
|
|
412
|
+
: ""}
|
|
413
|
+
${
|
|
414
|
+
// Show input box if command not supported or "Join Other" selected
|
|
415
|
+
this._selectedSsid === -1
|
|
416
|
+
? html `
|
|
417
|
+
<ewt-textfield label="Network Name" name="ssid"></ewt-textfield>
|
|
418
|
+
`
|
|
419
|
+
: ""}
|
|
420
|
+
<ewt-textfield
|
|
421
|
+
label="Password"
|
|
422
|
+
name="password"
|
|
423
|
+
type="password"
|
|
424
|
+
></ewt-textfield>
|
|
425
|
+
<ewt-button
|
|
426
|
+
slot="primaryAction"
|
|
427
|
+
label="Connect"
|
|
428
|
+
@click=${this._doProvision}
|
|
429
|
+
></ewt-button>
|
|
430
|
+
<ewt-button
|
|
431
|
+
slot="secondaryAction"
|
|
432
|
+
.label=${this._installState && this._installErase ? "Skip" : "Back"}
|
|
433
|
+
@click=${() => {
|
|
434
|
+
this._state = "DASHBOARD";
|
|
435
|
+
}}
|
|
436
|
+
></ewt-button>
|
|
437
|
+
`;
|
|
438
|
+
}
|
|
439
|
+
return [heading, content, hideActions];
|
|
440
|
+
}
|
|
441
|
+
_renderAskErase() {
|
|
442
|
+
const heading = "Erase device";
|
|
443
|
+
const content = html `
|
|
444
|
+
<div>
|
|
445
|
+
Do you want to erase the device before installing
|
|
446
|
+
${this._manifest.name}? All data on the device will be lost.
|
|
447
|
+
</div>
|
|
448
|
+
<ewt-formfield label="Erase device" class="danger">
|
|
449
|
+
<ewt-checkbox></ewt-checkbox>
|
|
450
|
+
</ewt-formfield>
|
|
451
|
+
<ewt-button
|
|
452
|
+
slot="primaryAction"
|
|
453
|
+
label="Next"
|
|
454
|
+
@click=${() => {
|
|
455
|
+
const checkbox = this.shadowRoot.querySelector("ewt-checkbox");
|
|
456
|
+
this._startInstall(checkbox.checked);
|
|
457
|
+
}}
|
|
458
|
+
></ewt-button>
|
|
459
|
+
<ewt-button
|
|
460
|
+
slot="secondaryAction"
|
|
461
|
+
label="Back"
|
|
462
|
+
@click=${() => {
|
|
463
|
+
this._state = "DASHBOARD";
|
|
464
|
+
}}
|
|
465
|
+
></ewt-button>
|
|
466
|
+
`;
|
|
467
|
+
return [heading, content];
|
|
468
|
+
}
|
|
469
|
+
_renderInstall() {
|
|
470
|
+
let heading;
|
|
471
|
+
let content;
|
|
472
|
+
let hideActions = false;
|
|
473
|
+
const allowClosing = false;
|
|
474
|
+
const isUpdate = !this._installErase && this._isSameFirmware;
|
|
475
|
+
if (!this._installConfirmed && this._isSameVersion) {
|
|
476
|
+
heading = "Erase User Data";
|
|
477
|
+
content = html `
|
|
478
|
+
Do you want to reset your device and erase all user data from your
|
|
479
|
+
device?
|
|
480
|
+
<ewt-button
|
|
481
|
+
class="danger"
|
|
482
|
+
slot="primaryAction"
|
|
483
|
+
label="Erase User Data"
|
|
484
|
+
@click=${this._confirmInstall}
|
|
485
|
+
></ewt-button>
|
|
486
|
+
`;
|
|
487
|
+
}
|
|
488
|
+
else if (!this._installConfirmed) {
|
|
489
|
+
heading = "Confirm Installation";
|
|
490
|
+
const action = isUpdate ? "update to" : "install";
|
|
491
|
+
content = html `
|
|
492
|
+
${isUpdate
|
|
493
|
+
? html `Your device is running
|
|
494
|
+
${this._info.firmware} ${this._info.version}.<br /><br />`
|
|
495
|
+
: ""}
|
|
496
|
+
Do you want to ${action}
|
|
497
|
+
${this._manifest.name} ${this._manifest.version}?
|
|
498
|
+
${this._installErase
|
|
499
|
+
? html `<br /><br />All data on the device will be erased.`
|
|
500
|
+
: ""}
|
|
501
|
+
<ewt-button
|
|
502
|
+
slot="primaryAction"
|
|
503
|
+
label="Install"
|
|
504
|
+
@click=${this._confirmInstall}
|
|
505
|
+
></ewt-button>
|
|
506
|
+
<ewt-button
|
|
507
|
+
slot="secondaryAction"
|
|
508
|
+
label="Back"
|
|
509
|
+
@click=${() => {
|
|
510
|
+
this._state = "DASHBOARD";
|
|
511
|
+
}}
|
|
512
|
+
></ewt-button>
|
|
513
|
+
`;
|
|
514
|
+
}
|
|
515
|
+
else if (!this._installState ||
|
|
516
|
+
this._installState.state === "initializing" /* FlashStateType.INITIALIZING */ ||
|
|
517
|
+
this._installState.state === "manifest" /* FlashStateType.MANIFEST */ ||
|
|
518
|
+
this._installState.state === "preparing" /* FlashStateType.PREPARING */) {
|
|
519
|
+
heading = "Installing";
|
|
520
|
+
content = this._renderProgress("Preparing installation");
|
|
521
|
+
hideActions = true;
|
|
522
|
+
}
|
|
523
|
+
else if (this._installState.state === "erasing" /* FlashStateType.ERASING */) {
|
|
524
|
+
heading = "Installing";
|
|
525
|
+
content = this._renderProgress("Erasing");
|
|
526
|
+
hideActions = true;
|
|
527
|
+
}
|
|
528
|
+
else if (this._installState.state === "writing" /* FlashStateType.WRITING */ ||
|
|
529
|
+
// When we're finished, keep showing this screen with 100% written
|
|
530
|
+
// until Improv is initialized / not detected.
|
|
531
|
+
(this._installState.state === "finished" /* FlashStateType.FINISHED */ &&
|
|
532
|
+
this._client === undefined)) {
|
|
533
|
+
heading = "Installing";
|
|
534
|
+
let percentage;
|
|
535
|
+
let undeterminateLabel;
|
|
536
|
+
if (this._installState.state === "finished" /* FlashStateType.FINISHED */) {
|
|
537
|
+
// We're done writing and detecting improv, show spinner
|
|
538
|
+
undeterminateLabel = "Wrapping up";
|
|
539
|
+
}
|
|
540
|
+
else if (this._installState.details.percentage < 4) {
|
|
541
|
+
// We're writing the firmware under 4%, show spinner or else we don't show any pixels
|
|
542
|
+
undeterminateLabel = "Installing";
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
// We're writing the firmware over 4%, show progress bar
|
|
546
|
+
percentage = this._installState.details.percentage;
|
|
547
|
+
}
|
|
548
|
+
content = this._renderProgress(html `
|
|
549
|
+
${undeterminateLabel ? html `${undeterminateLabel}<br />` : ""}
|
|
550
|
+
<br />
|
|
551
|
+
This will take
|
|
552
|
+
${this._installState.chipFamily === "ESP8266"
|
|
553
|
+
? "a minute"
|
|
554
|
+
: "2 minutes"}.<br />
|
|
555
|
+
Keep this page visible to prevent slow down
|
|
556
|
+
`, percentage);
|
|
557
|
+
hideActions = true;
|
|
558
|
+
}
|
|
559
|
+
else if (this._installState.state === "finished" /* FlashStateType.FINISHED */) {
|
|
560
|
+
heading = undefined;
|
|
561
|
+
const supportsImprov = this._client !== null;
|
|
562
|
+
content = html `
|
|
563
|
+
<ewt-page-message
|
|
564
|
+
.icon=${OK_ICON}
|
|
565
|
+
label="Installation complete!"
|
|
566
|
+
></ewt-page-message>
|
|
567
|
+
<ewt-button
|
|
568
|
+
slot="primaryAction"
|
|
569
|
+
label="Next"
|
|
570
|
+
@click=${() => {
|
|
571
|
+
this._state =
|
|
572
|
+
supportsImprov && this._installErase ? "PROVISION" : "DASHBOARD";
|
|
573
|
+
}}
|
|
574
|
+
></ewt-button>
|
|
575
|
+
`;
|
|
576
|
+
}
|
|
577
|
+
else if (this._installState.state === "error" /* FlashStateType.ERROR */) {
|
|
578
|
+
heading = "Installation failed";
|
|
579
|
+
content = html `
|
|
580
|
+
<ewt-page-message
|
|
581
|
+
.icon=${ERROR_ICON}
|
|
582
|
+
.label=${this._installState.message}
|
|
583
|
+
></ewt-page-message>
|
|
584
|
+
<ewt-button
|
|
585
|
+
slot="primaryAction"
|
|
586
|
+
label="Back"
|
|
587
|
+
@click=${async () => {
|
|
588
|
+
this._initialize();
|
|
589
|
+
this._state = "DASHBOARD";
|
|
590
|
+
}}
|
|
591
|
+
></ewt-button>
|
|
592
|
+
`;
|
|
593
|
+
}
|
|
594
|
+
return [heading, content, hideActions, allowClosing];
|
|
595
|
+
}
|
|
596
|
+
_renderLogs() {
|
|
597
|
+
let heading = `Logs`;
|
|
598
|
+
let content;
|
|
599
|
+
let hideActions = false;
|
|
600
|
+
content = html `
|
|
601
|
+
<ewt-console .port=${this.port} .logger=${this.logger}></ewt-console>
|
|
602
|
+
<ewt-button
|
|
603
|
+
slot="primaryAction"
|
|
604
|
+
label="Back"
|
|
605
|
+
@click=${async () => {
|
|
606
|
+
await this.shadowRoot.querySelector("ewt-console").disconnect();
|
|
607
|
+
this._state = "DASHBOARD";
|
|
608
|
+
this._initialize();
|
|
609
|
+
}}
|
|
610
|
+
></ewt-button>
|
|
611
|
+
<ewt-button
|
|
612
|
+
slot="secondaryAction"
|
|
613
|
+
label="Download Logs"
|
|
614
|
+
@click=${() => {
|
|
615
|
+
textDownload(this.shadowRoot.querySelector("ewt-console").logs(), `esp-web-tools-logs.txt`);
|
|
616
|
+
this.shadowRoot.querySelector("ewt-console").reset();
|
|
617
|
+
}}
|
|
618
|
+
></ewt-button>
|
|
619
|
+
<ewt-button
|
|
620
|
+
slot="secondaryAction"
|
|
621
|
+
label="Reset Device"
|
|
622
|
+
@click=${async () => {
|
|
623
|
+
await this.shadowRoot.querySelector("ewt-console").reset();
|
|
624
|
+
}}
|
|
625
|
+
></ewt-button>
|
|
626
|
+
`;
|
|
627
|
+
return [heading, content, hideActions];
|
|
628
|
+
}
|
|
629
|
+
willUpdate(changedProps) {
|
|
630
|
+
if (!changedProps.has("_state")) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
// Clear errors when changing between pages unless we change
|
|
634
|
+
// to the error page.
|
|
635
|
+
if (this._state !== "ERROR") {
|
|
636
|
+
this._error = undefined;
|
|
637
|
+
}
|
|
638
|
+
// Scan for SSIDs on provision
|
|
639
|
+
if (this._state === "PROVISION") {
|
|
640
|
+
this._ssids = undefined;
|
|
641
|
+
this._busy = true;
|
|
642
|
+
this._client.scan().then((ssids) => {
|
|
643
|
+
this._busy = false;
|
|
644
|
+
this._ssids = ssids;
|
|
645
|
+
this._selectedSsid = ssids.length ? 0 : -1;
|
|
646
|
+
}, () => {
|
|
647
|
+
this._busy = false;
|
|
648
|
+
this._ssids = null;
|
|
649
|
+
this._selectedSsid = -1;
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
// Reset this value if we leave provisioning.
|
|
654
|
+
this._provisionForce = false;
|
|
655
|
+
}
|
|
656
|
+
if (this._state === "INSTALL") {
|
|
657
|
+
this._installConfirmed = false;
|
|
658
|
+
this._installState = undefined;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
firstUpdated(changedProps) {
|
|
662
|
+
super.firstUpdated(changedProps);
|
|
663
|
+
this._initialize();
|
|
664
|
+
}
|
|
665
|
+
updated(changedProps) {
|
|
666
|
+
super.updated(changedProps);
|
|
667
|
+
if (changedProps.has("_state")) {
|
|
668
|
+
this.setAttribute("state", this._state);
|
|
669
|
+
}
|
|
670
|
+
if (this._state !== "PROVISION") {
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
if (changedProps.has("_selectedSsid") && this._selectedSsid === -1) {
|
|
674
|
+
// If we pick "Join other", select SSID input.
|
|
675
|
+
this._focusFormElement("ewt-textfield[name=ssid]");
|
|
676
|
+
}
|
|
677
|
+
else if (changedProps.has("_ssids")) {
|
|
678
|
+
// Form is shown when SSIDs are loaded/marked not supported
|
|
679
|
+
this._focusFormElement();
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
_focusFormElement(selector = "ewt-textfield, ewt-select") {
|
|
683
|
+
const formEl = this.shadowRoot.querySelector(selector);
|
|
684
|
+
if (formEl) {
|
|
685
|
+
formEl.updateComplete.then(() => setTimeout(() => formEl.focus(), 100));
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
async _initialize(justInstalled = false) {
|
|
689
|
+
if (this.port.readable === null || this.port.writable === null) {
|
|
690
|
+
this._state = "ERROR";
|
|
691
|
+
this._error =
|
|
692
|
+
"Serial port is not readable/writable. Close any other application using it and try again.";
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
try {
|
|
696
|
+
this._manifest = await downloadManifest(this.manifestPath);
|
|
697
|
+
}
|
|
698
|
+
catch (err) {
|
|
699
|
+
this._state = "ERROR";
|
|
700
|
+
this._error = "Failed to download manifest";
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
if (this._manifest.new_install_improv_wait_time === 0) {
|
|
704
|
+
this._client = null;
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
const client = new ImprovSerial(this.port, this.logger);
|
|
708
|
+
client.addEventListener("state-changed", () => {
|
|
709
|
+
this.requestUpdate();
|
|
710
|
+
});
|
|
711
|
+
client.addEventListener("error-changed", () => this.requestUpdate());
|
|
712
|
+
try {
|
|
713
|
+
// If a device was just installed, give new firmware 10 seconds (overridable) to
|
|
714
|
+
// format the rest of the flash and do other stuff.
|
|
715
|
+
const timeout = !justInstalled
|
|
716
|
+
? 1000
|
|
717
|
+
: this._manifest.new_install_improv_wait_time !== undefined
|
|
718
|
+
? this._manifest.new_install_improv_wait_time * 1000
|
|
719
|
+
: 10000;
|
|
720
|
+
this._info = await client.initialize(timeout);
|
|
721
|
+
this._client = client;
|
|
722
|
+
client.addEventListener("disconnect", this._handleDisconnect);
|
|
723
|
+
}
|
|
724
|
+
catch (err) {
|
|
725
|
+
// Clear old value
|
|
726
|
+
this._info = undefined;
|
|
727
|
+
if (err instanceof PortNotReady) {
|
|
728
|
+
this._state = "ERROR";
|
|
729
|
+
this._error =
|
|
730
|
+
"Serial port is not ready. Close any other application using it and try again.";
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
this._client = null; // not supported
|
|
734
|
+
this.logger.error("Improv initialization failed.", err);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
_startInstall(erase) {
|
|
739
|
+
this._state = "INSTALL";
|
|
740
|
+
this._installErase = erase;
|
|
741
|
+
this._installConfirmed = false;
|
|
742
|
+
}
|
|
743
|
+
async _confirmInstall() {
|
|
744
|
+
this._installConfirmed = true;
|
|
745
|
+
this._installState = undefined;
|
|
746
|
+
if (this._client) {
|
|
747
|
+
await this._closeClientWithoutEvents(this._client);
|
|
748
|
+
}
|
|
749
|
+
this._client = undefined;
|
|
750
|
+
flash((state) => {
|
|
751
|
+
this._installState = state;
|
|
752
|
+
if (state.state === "finished" /* FlashStateType.FINISHED */) {
|
|
753
|
+
sleep(100)
|
|
754
|
+
.then(() => this._initialize(true))
|
|
755
|
+
.then(() => this.requestUpdate());
|
|
756
|
+
}
|
|
757
|
+
}, this.port, this.logger, this.manifestPath, this._installErase);
|
|
758
|
+
}
|
|
759
|
+
async _doProvision() {
|
|
760
|
+
this._busy = true;
|
|
761
|
+
this._wasProvisioned =
|
|
762
|
+
this._client.state === ImprovSerialCurrentState.PROVISIONED;
|
|
763
|
+
const ssid = this._selectedSsid === -1
|
|
764
|
+
? this.shadowRoot.querySelector("ewt-textfield[name=ssid]").value
|
|
765
|
+
: this._ssids[this._selectedSsid].name;
|
|
766
|
+
const password = this.shadowRoot.querySelector("ewt-textfield[name=password]").value;
|
|
767
|
+
try {
|
|
768
|
+
await this._client.provision(ssid, password);
|
|
769
|
+
}
|
|
770
|
+
catch (err) {
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
finally {
|
|
774
|
+
this._busy = false;
|
|
775
|
+
this._provisionForce = false;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
async _handleClose() {
|
|
779
|
+
if (this._client) {
|
|
780
|
+
await this._closeClientWithoutEvents(this._client);
|
|
781
|
+
}
|
|
782
|
+
fireEvent(this, "closed");
|
|
783
|
+
this.parentNode.removeChild(this);
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Return if the device runs same firmware as manifest.
|
|
787
|
+
*/
|
|
788
|
+
get _isSameFirmware() {
|
|
789
|
+
var _a;
|
|
790
|
+
return !this._info
|
|
791
|
+
? false
|
|
792
|
+
: ((_a = this.overrides) === null || _a === void 0 ? void 0 : _a.checkSameFirmware)
|
|
793
|
+
? this.overrides.checkSameFirmware(this._manifest, this._info)
|
|
794
|
+
: this._info.firmware === this._manifest.name;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Return if the device runs same firmware and version as manifest.
|
|
798
|
+
*/
|
|
799
|
+
get _isSameVersion() {
|
|
800
|
+
return (this._isSameFirmware && this._info.version === this._manifest.version);
|
|
801
|
+
}
|
|
802
|
+
async _closeClientWithoutEvents(client) {
|
|
803
|
+
client.removeEventListener("disconnect", this._handleDisconnect);
|
|
804
|
+
await client.close();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
EwtInstallDialog.styles = [
|
|
808
|
+
dialogStyles,
|
|
809
|
+
css `
|
|
810
|
+
:host {
|
|
811
|
+
--mdc-dialog-max-width: 390px;
|
|
812
|
+
}
|
|
813
|
+
ewt-icon-button {
|
|
814
|
+
position: absolute;
|
|
815
|
+
right: 4px;
|
|
816
|
+
top: 10px;
|
|
817
|
+
}
|
|
818
|
+
.table-row {
|
|
819
|
+
display: flex;
|
|
820
|
+
}
|
|
821
|
+
.table-row.last {
|
|
822
|
+
margin-bottom: 16px;
|
|
823
|
+
}
|
|
824
|
+
.table-row svg {
|
|
825
|
+
width: 20px;
|
|
826
|
+
margin-right: 8px;
|
|
827
|
+
}
|
|
828
|
+
ewt-textfield,
|
|
829
|
+
ewt-select {
|
|
830
|
+
display: block;
|
|
831
|
+
margin-top: 16px;
|
|
832
|
+
}
|
|
833
|
+
.dashboard-buttons {
|
|
834
|
+
margin: 0 0 -16px -8px;
|
|
835
|
+
}
|
|
836
|
+
.dashboard-buttons div {
|
|
837
|
+
display: block;
|
|
838
|
+
margin: 4px 0;
|
|
839
|
+
}
|
|
840
|
+
a.has-button {
|
|
841
|
+
text-decoration: none;
|
|
842
|
+
}
|
|
843
|
+
.error {
|
|
844
|
+
color: var(--improv-danger-color);
|
|
845
|
+
}
|
|
846
|
+
.danger {
|
|
847
|
+
--mdc-theme-primary: var(--improv-danger-color);
|
|
848
|
+
--mdc-theme-secondary: var(--improv-danger-color);
|
|
849
|
+
}
|
|
850
|
+
button.link {
|
|
851
|
+
background: none;
|
|
852
|
+
color: inherit;
|
|
853
|
+
border: none;
|
|
854
|
+
padding: 0;
|
|
855
|
+
font: inherit;
|
|
856
|
+
text-align: left;
|
|
857
|
+
text-decoration: underline;
|
|
858
|
+
cursor: pointer;
|
|
859
|
+
}
|
|
860
|
+
:host([state="LOGS"]) ewt-dialog {
|
|
861
|
+
--mdc-dialog-max-width: 90vw;
|
|
862
|
+
}
|
|
863
|
+
ewt-console {
|
|
864
|
+
width: calc(80vw - 48px);
|
|
865
|
+
height: 80vh;
|
|
866
|
+
}
|
|
867
|
+
`,
|
|
868
|
+
];
|
|
869
|
+
__decorate([
|
|
870
|
+
state()
|
|
871
|
+
], EwtInstallDialog.prototype, "_client", void 0);
|
|
872
|
+
__decorate([
|
|
873
|
+
state()
|
|
874
|
+
], EwtInstallDialog.prototype, "_state", void 0);
|
|
875
|
+
__decorate([
|
|
876
|
+
state()
|
|
877
|
+
], EwtInstallDialog.prototype, "_installErase", void 0);
|
|
878
|
+
__decorate([
|
|
879
|
+
state()
|
|
880
|
+
], EwtInstallDialog.prototype, "_installConfirmed", void 0);
|
|
881
|
+
__decorate([
|
|
882
|
+
state()
|
|
883
|
+
], EwtInstallDialog.prototype, "_installState", void 0);
|
|
884
|
+
__decorate([
|
|
885
|
+
state()
|
|
886
|
+
], EwtInstallDialog.prototype, "_provisionForce", void 0);
|
|
887
|
+
__decorate([
|
|
888
|
+
state()
|
|
889
|
+
], EwtInstallDialog.prototype, "_error", void 0);
|
|
890
|
+
__decorate([
|
|
891
|
+
state()
|
|
892
|
+
], EwtInstallDialog.prototype, "_busy", void 0);
|
|
893
|
+
__decorate([
|
|
894
|
+
state()
|
|
895
|
+
], EwtInstallDialog.prototype, "_ssids", void 0);
|
|
896
|
+
__decorate([
|
|
897
|
+
state()
|
|
898
|
+
], EwtInstallDialog.prototype, "_selectedSsid", void 0);
|
|
899
|
+
customElements.define("ewt-install-dialog", EwtInstallDialog);
|