diff --git a/index.html b/index.html index d59e61a..68196ef 100644 --- a/index.html +++ b/index.html @@ -329,7 +329,7 @@ "name": "ESPHome", "version": "2021.11.0", "home_assistant_domain": "esphome", - "new_install_skip_erase": false, + "new_install_prompt_erase": false, "builds": [ { "chipFamily": "ESP32", @@ -350,7 +350,7 @@ }

- Each build contains a list of parts to be flashed to the ESP device. + Each build contains a list of parts to be installed to the ESP device. Each part consists of a path to the file and an offset on the flash where it should be installed. Part paths are resolved relative to the path of the manifest, but can also be URLs to other hosts. @@ -361,12 +361,12 @@ Tools will link the user to add this device to Home Assistant.

- By default a new installation will erase the entire flash. If you want - to skip this step, set the optional key - new_install_skip_erase to true. ESP Web Tools - offers users a new installation if it is unable to detect the current - firmware of the device (via Improv Serial) or if the detected firmware - does not match the name specififed in the manifest. + By default a new installation will erase all data before installation. + If you want to leave this choice to the user, set the optional key + new_install_prompt_erase to true. ESP Web + Tools offers users a new installation if it is unable to detect the + current firmware of the device (via Improv Serial) or if the detected + firmware does not match the name specififed in the manifest.

Configuring Wi-Fi

diff --git a/package-lock.json b/package-lock.json index c401e3b..53f5347 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,8 @@ "@material/mwc-checkbox": "^0.25.3", "@material/mwc-circular-progress": "^0.25.3", "@material/mwc-dialog": "^0.25.3", + "@material/mwc-formfield": "^0.25.3", "@material/mwc-icon-button": "^0.25.3", - "@material/mwc-linear-progress": "^0.25.1", "@material/mwc-textfield": "^0.25.3", "esp-web-flasher": "^4.0.0", "improv-wifi-serial-sdk": "^2.1.0", @@ -188,6 +188,20 @@ "tslib": "^2.1.0" } }, + "node_modules/@material/form-field": { + "version": "14.0.0-canary.261f2db59.0", + "resolved": "https://registry.npmjs.org/@material/form-field/-/form-field-14.0.0-canary.261f2db59.0.tgz", + "integrity": "sha512-NCc/o60gwuF28PVMgFkHrKcHxIaCMZK9JRVfoaD0sF2BINYrjaCkFZ+x6AhNjAWLUQMhJMfc+1WXAUE2T85Mug==", + "dependencies": { + "@material/base": "14.0.0-canary.261f2db59.0", + "@material/feature-targeting": "14.0.0-canary.261f2db59.0", + "@material/ripple": "14.0.0-canary.261f2db59.0", + "@material/rtl": "14.0.0-canary.261f2db59.0", + "@material/theme": "14.0.0-canary.261f2db59.0", + "@material/typography": "14.0.0-canary.261f2db59.0", + "tslib": "^2.1.0" + } + }, "node_modules/@material/icon-button": { "version": "14.0.0-canary.261f2db59.0", "resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-14.0.0-canary.261f2db59.0.tgz", @@ -216,20 +230,6 @@ "tslib": "^2.1.0" } }, - "node_modules/@material/linear-progress": { - "version": "14.0.0-canary.261f2db59.0", - "resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-14.0.0-canary.261f2db59.0.tgz", - "integrity": "sha512-qP/iI4CT7i7HhXuUiNWL5pDN6tyTJ4uLl8e9QImz4mcQLUMU3xrNBIsutS+I5GnBE8FwLDozZFccfCxHh+pvzw==", - "dependencies": { - "@material/animation": "14.0.0-canary.261f2db59.0", - "@material/base": "14.0.0-canary.261f2db59.0", - "@material/feature-targeting": "14.0.0-canary.261f2db59.0", - "@material/progress-indicator": "14.0.0-canary.261f2db59.0", - "@material/rtl": "14.0.0-canary.261f2db59.0", - "@material/theme": "14.0.0-canary.261f2db59.0", - "tslib": "^2.1.0" - } - }, "node_modules/@material/mwc-base": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/@material/mwc-base/-/mwc-base-0.25.3.tgz", @@ -301,6 +301,17 @@ "tslib": "^2.0.1" } }, + "node_modules/@material/mwc-formfield": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@material/mwc-formfield/-/mwc-formfield-0.25.3.tgz", + "integrity": "sha512-JP/ZgsWok0ZVwUQfYgaov0Ocn1zDiiw7Po6q8k/n5tOS67S41XUB/ctiUg1gh00LAM0v3eZAexa9ZmKarviVJA==", + "dependencies": { + "@material/form-field": "=14.0.0-canary.261f2db59.0", + "@material/mwc-base": "^0.25.3", + "lit": "^2.0.0", + "tslib": "^2.0.1" + } + }, "node_modules/@material/mwc-icon": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/@material/mwc-icon/-/mwc-icon-0.25.3.tgz", @@ -330,18 +341,6 @@ "tslib": "^2.0.1" } }, - "node_modules/@material/mwc-linear-progress": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@material/mwc-linear-progress/-/mwc-linear-progress-0.25.3.tgz", - "integrity": "sha512-iAsM5zo78rYXXzwEg1RT0+jShxkUjOEUK0Yj6KxqxbXy1VKPTZ4HRB5Fy6wChWQi/Xl8wFlfI6nNAQtH7pakeA==", - "dependencies": { - "@material/linear-progress": "=14.0.0-canary.261f2db59.0", - "@material/mwc-base": "^0.25.3", - "@material/theme": "=14.0.0-canary.261f2db59.0", - "lit": "^2.0.0", - "tslib": "^2.0.1" - } - }, "node_modules/@material/mwc-notched-outline": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/@material/mwc-notched-outline/-/mwc-notched-outline-0.25.3.tgz", @@ -2060,6 +2059,20 @@ "tslib": "^2.1.0" } }, + "@material/form-field": { + "version": "14.0.0-canary.261f2db59.0", + "resolved": "https://registry.npmjs.org/@material/form-field/-/form-field-14.0.0-canary.261f2db59.0.tgz", + "integrity": "sha512-NCc/o60gwuF28PVMgFkHrKcHxIaCMZK9JRVfoaD0sF2BINYrjaCkFZ+x6AhNjAWLUQMhJMfc+1WXAUE2T85Mug==", + "requires": { + "@material/base": "14.0.0-canary.261f2db59.0", + "@material/feature-targeting": "14.0.0-canary.261f2db59.0", + "@material/ripple": "14.0.0-canary.261f2db59.0", + "@material/rtl": "14.0.0-canary.261f2db59.0", + "@material/theme": "14.0.0-canary.261f2db59.0", + "@material/typography": "14.0.0-canary.261f2db59.0", + "tslib": "^2.1.0" + } + }, "@material/icon-button": { "version": "14.0.0-canary.261f2db59.0", "resolved": "https://registry.npmjs.org/@material/icon-button/-/icon-button-14.0.0-canary.261f2db59.0.tgz", @@ -2088,20 +2101,6 @@ "tslib": "^2.1.0" } }, - "@material/linear-progress": { - "version": "14.0.0-canary.261f2db59.0", - "resolved": "https://registry.npmjs.org/@material/linear-progress/-/linear-progress-14.0.0-canary.261f2db59.0.tgz", - "integrity": "sha512-qP/iI4CT7i7HhXuUiNWL5pDN6tyTJ4uLl8e9QImz4mcQLUMU3xrNBIsutS+I5GnBE8FwLDozZFccfCxHh+pvzw==", - "requires": { - "@material/animation": "14.0.0-canary.261f2db59.0", - "@material/base": "14.0.0-canary.261f2db59.0", - "@material/feature-targeting": "14.0.0-canary.261f2db59.0", - "@material/progress-indicator": "14.0.0-canary.261f2db59.0", - "@material/rtl": "14.0.0-canary.261f2db59.0", - "@material/theme": "14.0.0-canary.261f2db59.0", - "tslib": "^2.1.0" - } - }, "@material/mwc-base": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/@material/mwc-base/-/mwc-base-0.25.3.tgz", @@ -2173,6 +2172,17 @@ "tslib": "^2.0.1" } }, + "@material/mwc-formfield": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@material/mwc-formfield/-/mwc-formfield-0.25.3.tgz", + "integrity": "sha512-JP/ZgsWok0ZVwUQfYgaov0Ocn1zDiiw7Po6q8k/n5tOS67S41XUB/ctiUg1gh00LAM0v3eZAexa9ZmKarviVJA==", + "requires": { + "@material/form-field": "=14.0.0-canary.261f2db59.0", + "@material/mwc-base": "^0.25.3", + "lit": "^2.0.0", + "tslib": "^2.0.1" + } + }, "@material/mwc-icon": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/@material/mwc-icon/-/mwc-icon-0.25.3.tgz", @@ -2202,18 +2212,6 @@ "tslib": "^2.0.1" } }, - "@material/mwc-linear-progress": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@material/mwc-linear-progress/-/mwc-linear-progress-0.25.3.tgz", - "integrity": "sha512-iAsM5zo78rYXXzwEg1RT0+jShxkUjOEUK0Yj6KxqxbXy1VKPTZ4HRB5Fy6wChWQi/Xl8wFlfI6nNAQtH7pakeA==", - "requires": { - "@material/linear-progress": "=14.0.0-canary.261f2db59.0", - "@material/mwc-base": "^0.25.3", - "@material/theme": "=14.0.0-canary.261f2db59.0", - "lit": "^2.0.0", - "tslib": "^2.0.1" - } - }, "@material/mwc-notched-outline": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/@material/mwc-notched-outline/-/mwc-notched-outline-0.25.3.tgz", diff --git a/package.json b/package.json index 33b1c9e..10f6ef4 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,8 @@ "@material/mwc-checkbox": "^0.25.3", "@material/mwc-circular-progress": "^0.25.3", "@material/mwc-dialog": "^0.25.3", + "@material/mwc-formfield": "^0.25.3", "@material/mwc-icon-button": "^0.25.3", - "@material/mwc-linear-progress": "^0.25.1", "@material/mwc-textfield": "^0.25.3", "esp-web-flasher": "^4.0.0", "improv-wifi-serial-sdk": "^2.1.0", diff --git a/src/components/ewt-checkbox.ts b/src/components/ewt-checkbox.ts new file mode 100644 index 0000000..901ee03 --- /dev/null +++ b/src/components/ewt-checkbox.ts @@ -0,0 +1,14 @@ +import { CheckboxBase } from "@material/mwc-checkbox/mwc-checkbox-base"; +import { styles } from "@material/mwc-checkbox/mwc-checkbox.css"; + +declare global { + interface HTMLElementTagNameMap { + "ewt-checkbox": EwtCheckbox; + } +} + +export class EwtCheckbox extends CheckboxBase { + static override styles = [styles]; +} + +customElements.define("ewt-checkbox", EwtCheckbox); diff --git a/src/components/ewt-formfield.ts b/src/components/ewt-formfield.ts new file mode 100644 index 0000000..8fafb41 --- /dev/null +++ b/src/components/ewt-formfield.ts @@ -0,0 +1,14 @@ +import { FormfieldBase } from "@material/mwc-formfield/mwc-formfield-base"; +import { styles } from "@material/mwc-formfield/mwc-formfield.css"; + +declare global { + interface HTMLElementTagNameMap { + "ewt-formfield": EwtFormfield; + } +} + +export class EwtFormfield extends FormfieldBase { + static override styles = [styles]; +} + +customElements.define("ewt-formfield", EwtFormfield); diff --git a/src/const.ts b/src/const.ts index 985d1b4..5fbfe42 100644 --- a/src/const.ts +++ b/src/const.ts @@ -16,7 +16,9 @@ export interface Manifest { name: string; version: string; home_assistant_domain?: string; + /** @deprecated use `new_install_prompt_erase` instead */ new_install_skip_erase?: boolean; + new_install_prompt_erase?: boolean; builds: Build[]; } diff --git a/src/install-dialog.ts b/src/install-dialog.ts index 490a2b9..31b1bd4 100644 --- a/src/install-dialog.ts +++ b/src/install-dialog.ts @@ -4,6 +4,8 @@ import "./components/ewt-dialog"; import "./components/ewt-textfield"; import "./components/ewt-button"; import "./components/ewt-icon-button"; +import "./components/ewt-checkbox"; +import "./components/ewt-formfield"; import "./components/ewt-circular-progress"; import type { EwtTextfield } from "./components/ewt-textfield"; import { Logger, Manifest, FlashStateType, FlashState } from "./const.js"; @@ -47,6 +49,7 @@ class EwtInstallDialog extends LitElement { | "DASHBOARD" | "PROVISION" | "INSTALL" + | "ASK_ERASE" | "LOGS" = "DASHBOARD"; @state() private _installErase = false; @@ -83,6 +86,8 @@ class EwtInstallDialog extends LitElement { } } else if (this._state === "INSTALL") { [heading, content, hideActions, allowClosing] = this._renderInstall(); + } else if (this._state === "ASK_ERASE") { + [heading, content] = this._renderAskErase(); } else if (this._state === "ERROR") { heading = "Error"; content = this._renderMessage(ERROR_ICON, this._error!, true); @@ -191,12 +196,15 @@ class EwtInstallDialog extends LitElement { .label=${!this._isSameFirmware ? `Install ${this._manifest!.name}` : `Update ${this._manifest!.name}`} - @click=${() => - this._startInstall( - // Erase if manifest doens't force skipping it and it's not same firmware - !this._manifest.new_install_skip_erase && - !this._isSameFirmware - )} + @click=${() => { + if (this._isSameFirmware) { + this._startInstall(false); + } else if (this._manifest.new_install_prompt_erase) { + this._state = "ASK_ERASE"; + } else { + this._startInstall(true); + } + }} > ` @@ -285,9 +293,14 @@ class EwtInstallDialog extends LitElement {

- // Erase if manifest doens't force skipping it - this._startInstall(!this._manifest.new_install_skip_erase)} + @click=${() => { + if (this._manifest.new_install_prompt_erase) { + this._state = "ASK_ERASE"; + } else { + // Default is to erase a device that does not support Improv Serial + this._startInstall(true); + } + }} >
@@ -415,7 +428,7 @@ class EwtInstallDialog extends LitElement { + Do you want to erase the device before installing + ${this._manifest.name}? All data on the device will be lost. + + + + + { + const checkbox = this.shadowRoot!.querySelector("ewt-checkbox")!; + this._startInstall(checkbox.checked); + }} + > + { + this._state = "DASHBOARD"; + }} + > + `; + + return [heading, content]; + } + _renderInstall(): [string | undefined, TemplateResult, boolean, boolean] { let heading: string | undefined = `${ this._installConfirmed ? "Installing" : "Install" @@ -630,6 +673,14 @@ class EwtInstallDialog extends LitElement { this._manifest = await fetch(manifestURL).then( (resp): Promise => resp.json() ); + if ("new_install_skip_erase" in this._manifest) { + console.warn( + 'Manifest option "new_install_skip_erase" is deprecated. Use "new_install_prompt_erase" instead.' + ); + if (this._manifest.new_install_skip_erase) { + this._manifest.new_install_prompt_erase = true; + } + } } private async _initialize(justErased = false) { @@ -766,6 +817,10 @@ class EwtInstallDialog extends LitElement { --mdc-dialog-max-width: 390px; --mdc-theme-primary: var(--improv-primary-color, #03a9f4); --mdc-theme-on-primary: var(--improv-on-primary-color, #fff); + --improv-danger-color: #db4437; + --improv-text-color: rgba(0, 0, 0, 0.6); + --mdc-theme-text-primary-on-background: var(--improv-text-color); + --mdc-dialog-content-ink-color: var(--improv-text-color); text-align: left; } ewt-icon-button { @@ -775,7 +830,7 @@ class EwtInstallDialog extends LitElement { } table { border-spacing: 0; - color: rgba(0, 0, 0, 0.6); + color: var(--improv-text-color); margin-bottom: 16px; } table svg { @@ -817,10 +872,11 @@ class EwtInstallDialog extends LitElement { color: black; } .error { - color: #db4437; + color: var(--improv-danger-color); } .danger { - --mdc-theme-primary: #db4437; + --mdc-theme-primary: var(--improv-danger-color); + --mdc-theme-secondary: var(--improv-danger-color); } button.link { background: none;