diff --git a/hassio/src/dialogs/backup/dialog-hassio-backup.ts b/hassio/src/dialogs/backup/dialog-hassio-backup.ts index 230ecc1f22..66f5b6b829 100644 --- a/hassio/src/dialogs/backup/dialog-hassio-backup.ts +++ b/hassio/src/dialogs/backup/dialog-hassio-backup.ts @@ -173,6 +173,7 @@ class HassioBackupDialog private async _restoreClicked() { const backupDetails = this._backupContent.backupDetails(); this._restoringBackup = true; + this._dialogParams?.onRestoring?.(); if (this._backupContent.backupType === "full") { await this._fullRestoreClicked(backupDetails); } else { diff --git a/hassio/src/dialogs/backup/show-dialog-hassio-backup.ts b/hassio/src/dialogs/backup/show-dialog-hassio-backup.ts index 39c438e217..42f00da445 100644 --- a/hassio/src/dialogs/backup/show-dialog-hassio-backup.ts +++ b/hassio/src/dialogs/backup/show-dialog-hassio-backup.ts @@ -5,6 +5,7 @@ import { Supervisor } from "../../../../src/data/supervisor/supervisor"; export interface HassioBackupDialogParams { slug: string; onDelete?: () => void; + onRestoring?: () => void; onboarding?: boolean; supervisor?: Supervisor; localize?: LocalizeFunc; diff --git a/public/static/images/logo_discord.png b/public/static/images/logo_discord.png new file mode 100644 index 0000000000..24e567e1eb Binary files /dev/null and b/public/static/images/logo_discord.png differ diff --git a/public/static/images/logo_twitter.png b/public/static/images/logo_twitter.png new file mode 100644 index 0000000000..7b470c3bc3 Binary files /dev/null and b/public/static/images/logo_twitter.png differ diff --git a/src/components/ha-dialog.ts b/src/components/ha-dialog.ts index 5ecff68570..f061931322 100644 --- a/src/components/ha-dialog.ts +++ b/src/components/ha-dialog.ts @@ -10,12 +10,12 @@ import "./ha-icon-button"; const SUPPRESS_DEFAULT_PRESS_SELECTOR = ["button", "ha-list-item"]; export const createCloseHeading = ( - hass: HomeAssistant, + hass: HomeAssistant | undefined, title: string | TemplateResult ) => html`
${title}
option.value === this.value @@ -78,11 +79,11 @@ export class HaLanguagePicker extends LitElement { } private _getLanguagesOptions = memoizeOne( - (languages: string[], locale: FrontendLocaleData, nativeName: boolean) => { + (languages: string[], nativeName: boolean, locale?: FrontendLocaleData) => { let options: { label: string; value: string }[] = []; if (nativeName) { - const translations = this.hass.translationMetadata.translations; + const translations = translationMetadata.translations; options = languages.map((lang) => { let label = translations[lang]?.nativeName; if (!label) { @@ -101,14 +102,14 @@ export class HaLanguagePicker extends LitElement { label, }; }); - } else { + } else if (locale) { options = languages.map((lang) => ({ value: lang, label: formatLanguageCode(lang, locale), })); } - if (!this.noSort) { + if (!this.noSort && locale) { options.sort((a, b) => caseInsensitiveStringCompare(a.label, b.label, locale.language) ); @@ -118,20 +119,14 @@ export class HaLanguagePicker extends LitElement { ); private _computeDefaultLanguageOptions() { - if (!this.hass.translationMetadata?.translations) { - return; - } - - this._defaultLanguages = Object.keys( - this.hass.translationMetadata.translations - ); + this._defaultLanguages = Object.keys(translationMetadata.translations); } protected render() { const languageOptions = this._getLanguagesOptions( this.languages ?? this._defaultLanguages, - this.hass.locale, - this.nativeName + this.nativeName, + this.hass?.locale ); const value = @@ -139,9 +134,10 @@ export class HaLanguagePicker extends LitElement { return html` ${languageOptions.length === 0 ? html`${this.hass.localize( + >${this.hass?.localize( "ui.components.language-picker.no_languages" - )}` : languageOptions.map( (option) => html` @@ -176,7 +172,7 @@ export class HaLanguagePicker extends LitElement { private _changed(ev): void { const target = ev.target as HaSelect; - if (!this.hass || target.value === "" || target.value === this.value) { + if (target.value === "" || target.value === this.value) { return; } this.value = target.value; diff --git a/src/components/ha-select.ts b/src/components/ha-select.ts index 7471149051..bb3cfb4ae7 100644 --- a/src/components/ha-select.ts +++ b/src/components/ha-select.ts @@ -47,6 +47,9 @@ export class HaSelect extends SelectBase { .mdc-select__anchor { width: var(--ha-select-min-width, 200px); } + .mdc-select--filled .mdc-select__anchor { + height: var(--ha-select-height, 56px); + } .mdc-select--filled .mdc-floating-label { inset-inline-start: 12px; inset-inline-end: initial; diff --git a/src/components/language-datalist.ts b/src/components/language-datalist.ts deleted file mode 100644 index bac8b44c9c..0000000000 --- a/src/components/language-datalist.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { HomeAssistant } from "../types"; - -export const createLanguageListEl = (hass: HomeAssistant) => { - const list = document.createElement("datalist"); - list.id = "languages"; - for (const [language, metadata] of Object.entries( - hass.translationMetadata.translations - )) { - const option = document.createElement("option"); - option.value = language; - option.innerText = metadata.nativeName; - list.appendChild(option); - } - return list; -}; diff --git a/src/html/onboarding.html.template b/src/html/onboarding.html.template index aed5a62a79..9f89da79f0 100644 --- a/src/html/onboarding.html.template +++ b/src/html/onboarding.html.template @@ -6,44 +6,40 @@ <%= renderTemplate("_style_base.html.template") %> @@ -51,8 +47,7 @@
- - Home Assistant + Home Assistant
diff --git a/src/onboarding/dialogs/app-dialog.ts b/src/onboarding/dialogs/app-dialog.ts new file mode 100644 index 0000000000..087adfc3a7 --- /dev/null +++ b/src/onboarding/dialogs/app-dialog.ts @@ -0,0 +1,6759 @@ +import { LitElement, css, html, nothing } from "lit"; +import { customElement, property } from "lit/decorators"; +import { LocalizeFunc } from "../../common/translations/localize"; +import { fireEvent } from "../../common/dom/fire_event"; +import { createCloseHeading } from "../../components/ha-dialog"; + +@customElement("app-dialog") +class DialogApp extends LitElement { + @property({ attribute: false }) public localize?: LocalizeFunc; + + public async showDialog(params): Promise { + this.localize = params.localize; + } + + public async closeDialog(): Promise { + this.localize = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + protected render() { + if (!this.localize) { + return nothing; + } + return html` +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
`; + } + + static styles = css` + ha-dialog { + --mdc-dialog-min-width: min(500px, 90vw); + } + div { + display: flex; + justify-content: space-between; + } + a:first-child { + margin-right: 16px; + } + svg { + width: 100%; + } + .light { + fill: var(--card-background-color); + } + .dark { + fill: var(--primary-text-color); + } + @media (prefers-color-scheme: dark) { + .mask { + fill: var(--primary-text-color); + } + .logo { + filter: invert(100%); + } + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + "app-dialog": DialogApp; + } +} diff --git a/src/onboarding/dialogs/community-dialog.ts b/src/onboarding/dialogs/community-dialog.ts new file mode 100644 index 0000000000..f2bffcb3cc --- /dev/null +++ b/src/onboarding/dialogs/community-dialog.ts @@ -0,0 +1,106 @@ +import "@material/mwc-list/mwc-list"; +import { mdiOpenInNew } from "@mdi/js"; +import { LitElement, css, html, nothing } from "lit"; +import { customElement, property } from "lit/decorators"; +import { fireEvent } from "../../common/dom/fire_event"; +import { LocalizeFunc } from "../../common/translations/localize"; +import { createCloseHeading } from "../../components/ha-dialog"; +import "../../components/ha-list-item"; + +@customElement("community-dialog") +class DialogCommunity extends LitElement { + @property({ attribute: false }) public localize?: LocalizeFunc; + + public async showDialog(params): Promise { + this.localize = params.localize; + } + + public async closeDialog(): Promise { + this.localize = undefined; + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + + protected render() { + if (!this.localize) { + return nothing; + } + return html` + + + + + ${this.localize("ui.panel.page-onboarding.welcome.forums")} + + + + + + + ${this.localize( + "ui.panel.page-onboarding.welcome.open_home_newsletter" + )} + + + + + + + ${this.localize("ui.panel.page-onboarding.welcome.discord")} + + + + + + + ${this.localize("ui.panel.page-onboarding.welcome.twitter")} + + + + + `; + } + + static styles = css` + ha-dialog { + --mdc-dialog-min-width: min(400px, 90vw); + --dialog-content-padding: 0; + } + ha-list-item { + height: 56px; + --mdc-list-item-meta-size: 20px; + } + a { + text-decoration: none; + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + "community-dialog": DialogCommunity; + } +} diff --git a/src/onboarding/dialogs/show-app-dialog.ts b/src/onboarding/dialogs/show-app-dialog.ts new file mode 100644 index 0000000000..49dbac5205 --- /dev/null +++ b/src/onboarding/dialogs/show-app-dialog.ts @@ -0,0 +1,15 @@ +import { fireEvent } from "../../common/dom/fire_event"; +import { LocalizeFunc } from "../../common/translations/localize"; + +export const loadAppDialog = () => import("./app-dialog"); + +export const showAppDialog = ( + element: HTMLElement, + params: { localize: LocalizeFunc } +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "app-dialog", + dialogImport: loadAppDialog, + dialogParams: params, + }); +}; diff --git a/src/onboarding/dialogs/show-community-dialog.ts b/src/onboarding/dialogs/show-community-dialog.ts new file mode 100644 index 0000000000..236df5cc70 --- /dev/null +++ b/src/onboarding/dialogs/show-community-dialog.ts @@ -0,0 +1,15 @@ +import { fireEvent } from "../../common/dom/fire_event"; +import { LocalizeFunc } from "../../common/translations/localize"; + +export const loadCommunityDialog = () => import("./community-dialog"); + +export const showCommunityDialog = ( + element: HTMLElement, + params: { localize: LocalizeFunc } +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "community-dialog", + dialogImport: loadCommunityDialog, + dialogParams: params, + }); +}; diff --git a/src/onboarding/ha-onboarding.ts b/src/onboarding/ha-onboarding.ts index 5a2872f9fb..7a06c0e3cf 100644 --- a/src/onboarding/ha-onboarding.ts +++ b/src/onboarding/ha-onboarding.ts @@ -1,3 +1,4 @@ +import "@material/mwc-linear-progress/mwc-linear-progress"; import { Auth, createConnection, @@ -5,38 +6,45 @@ import { getAuth, subscribeConfig, } from "home-assistant-js-websocket"; -import { html, PropertyValues, nothing, css } from "lit"; +import { PropertyValues, css, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; +import { + enableWrite, + loadTokens, + saveTokens, +} from "../common/auth/token_storage"; import { applyThemesOnElement } from "../common/dom/apply_themes_on_element"; import { HASSDomEvent } from "../common/dom/fire_event"; import { extractSearchParamsObject } from "../common/url/search-params"; import { subscribeOne } from "../common/util/subscribe-one"; +import "../components/ha-card"; +import "../components/ha-language-picker"; import { AuthUrlSearchParams, hassUrl } from "../data/auth"; import { - fetchInstallationType, - fetchOnboardingOverview, OnboardingResponses, OnboardingStep, + fetchInstallationType, + fetchOnboardingOverview, onboardIntegrationStep, } from "../data/onboarding"; import { subscribeUser } from "../data/ws-user"; import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin"; import { HassElement } from "../state/hass-element"; import { HomeAssistant } from "../types"; +import { storeState } from "../util/ha-pref-storage"; import { registerServiceWorker } from "../util/register-service-worker"; import "./onboarding-analytics"; import "./onboarding-create-user"; import "./onboarding-loading"; -import "../components/ha-language-picker"; -import "../components/ha-card"; -import { storeState } from "../util/ha-pref-storage"; -import { - enableWrite, - loadTokens, - saveTokens, -} from "../common/auth/token_storage"; +import "./onboarding-welcome"; +import "./onboarding-welcome-links"; +import { makeDialogManager } from "../dialogs/make-dialog-manager"; type OnboardingEvent = + | { + type: "init"; + result: { restore: boolean }; + } | { type: "user"; result: OnboardingResponses["user"]; @@ -52,13 +60,21 @@ type OnboardingEvent = type: "analytics"; }; +interface OnboardingProgressEvent { + increase?: number; + decrease?: number; + progress?: number; +} + declare global { interface HASSDomEvents { "onboarding-step": OnboardingEvent; + "onboarding-progress": OnboardingProgressEvent; } interface GlobalEventHandlersEventMap { "onboarding-step": HASSDomEvent; + "onboarding-progress": HASSDomEvent; } } @@ -68,8 +84,12 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { @property() public translationFragment = "page-onboarding"; + @state() private _progress = 0; + @state() private _loading = false; + @state() private _init = false; + @state() private _restoring = false; @state() private _supervisor?: boolean; @@ -77,44 +97,58 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { @state() private _steps?: OnboardingStep[]; protected render() { - return html` + return html` +
${this._renderStep()}
- ${this.hass - ? html`` - : nothing} `; + ${this._init + ? html`` + : nothing} + `; } private _renderStep() { + if (this._init) { + return html``; + } + + if (this._restoring) { + return html` + `; + } + const step = this._curStep()!; if (this._loading || !step) { return html` `; } if (step.step === "user") { - return html` - ${!this._restoring - ? html` - ` - : ""} - ${this._supervisor - ? html` - ` - : ""} - `; + return html` + `; } if (step.step === "core_config") { return html` @@ -150,9 +184,13 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { import("./onboarding-core-config"); registerServiceWorker(this, false); this.addEventListener("onboarding-step", (ev) => this._handleStepDone(ev)); + this.addEventListener("onboarding-progress", (ev) => + this._handleProgress(ev) + ); if (window.innerWidth > 450) { import("./particles"); } + makeDialogManager(this, this.shadowRoot!); } protected updated(changedProps: PropertyValues) { @@ -187,10 +225,6 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { return this._steps ? this._steps.find((stp) => !stp.done) : undefined; } - private _restoringBackup() { - this._restoring = true; - } - private async _fetchInstallationType(): Promise { try { const response = await fetchInstallationType(); @@ -239,8 +273,12 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { }); history.replaceState(null, "", location.pathname); await this._connectHass(auth); + const currentStep = steps.findIndex((stp) => !stp.done); + const singelStepProgress = 1 / steps.length; + this._progress = currentStep * singelStepProgress + singelStepProgress; } else { - // User creating screen needs to know the installation type. + this._init = true; + // Init screen needs to know the installation type. this._fetchInstallationType(); } @@ -250,15 +288,35 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { } } + private _handleProgress(ev: HASSDomEvent) { + const stepSize = 1 / this._steps!.length; + if (ev.detail.increase) { + this._progress += ev.detail.increase * stepSize; + } + if (ev.detail.decrease) { + this._progress -= ev.detail.decrease * stepSize; + } + if (ev.detail.progress) { + this._progress = ev.detail.progress; + } + } + private async _handleStepDone(ev: HASSDomEvent) { const stepResult = ev.detail; this._steps = this._steps!.map((step) => step.step === stepResult.type ? { ...step, done: true } : step ); - if (stepResult.type === "user") { + if (stepResult.type === "init") { + this._init = false; + this._restoring = stepResult.result.restore; + if (!this._restoring) { + this._progress = 0.25; + } + } else if (stepResult.type === "user") { const result = stepResult.result as OnboardingResponses["user"]; this._loading = true; + this._progress = 0.5; enableWrite(); try { const auth = await getAuth({ @@ -275,6 +333,10 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { this._loading = false; } } else if (stepResult.type === "core_config") { + this._progress = 0.75; + // We do nothing + } else if (stepResult.type === "analytics") { + this._progress = 1; // We do nothing } else if (stepResult.type === "integration") { this._loading = true; @@ -348,6 +410,14 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { subscribeOne(conn, subscribeUser), ]); this.initializeHass(auth, conn); + if (this.language && this.language !== this.hass!.language) { + this._updateHass({ + locale: { ...this.hass!.locale, language: this.language }, + language: this.language, + selectedLanguage: this.language, + }); + storeState(this.hass!); + } // Load config strings for integrations (this as any)._loadFragmentTranslations(this.hass!.language, "config"); // Make sure hass is initialized + the config/user callbacks have called. @@ -359,25 +429,54 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { private _languageChanged(ev: CustomEvent) { const language = ev.detail.value; this.language = language; - this._updateHass({ - locale: { ...this.hass!.locale, language }, - language, - selectedLanguage: language, - }); - storeState(this.hass!); + if (this.hass) { + this._updateHass({ + locale: { ...this.hass!.locale, language }, + language, + selectedLanguage: language, + }); + storeState(this.hass!); + } else { + try { + localStorage.setItem("selectedLanguage", JSON.stringify(language)); + } catch (err: any) { + // Ignore + } + } } static styles = css` + mwc-linear-progress { + position: fixed; + top: 0; + left: 0; + width: 100%; + z-index: 10; + } + .footer { + display: flex; + justify-content: space-between; + align-items: center; + } ha-language-picker { display: block; width: 200px; margin-top: 8px; + border-radius: 4px; + overflow: hidden; + --ha-select-height: 40px; --mdc-select-fill-color: none; - --mdc-select-label-ink-color: var(--text-primary-color, #fff); - --mdc-select-ink-color: var(--text-primary-color, #fff); - --mdc-select-idle-line-color: var(--text-primary-color, #fff); - --mdc-select-hover-line-color: var(--text-primary-color, #fff); - --mdc-select-dropdown-icon-color: var(--text-primary-color, #fff); + --mdc-select-label-ink-color: var(--primary-text-color, #212121); + --mdc-select-ink-color: var(--primary-text-color, #212121); + --mdc-select-idle-line-color: transparent; + --mdc-select-hover-line-color: transparent; + --mdc-select-dropdown-icon-color: var(--primary-text-color, #212121); + --mdc-shape-small: 0; + } + a { + text-decoration: none; + color: var(--primary-text-color); + margin-right: 16px; } `; } diff --git a/src/onboarding/onboarding-analytics.ts b/src/onboarding/onboarding-analytics.ts index aeddcb4cc7..0bf36b8159 100644 --- a/src/onboarding/onboarding-analytics.ts +++ b/src/onboarding/onboarding-analytics.ts @@ -1,4 +1,5 @@ import "@material/mwc-button/mwc-button"; +import { mdiOpenInNew } from "@mdi/js"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; @@ -8,6 +9,7 @@ import { Analytics, setAnalyticsPreferences } from "../data/analytics"; import { onboardAnalyticsStep } from "../data/onboarding"; import type { HomeAssistant } from "../types"; import { documentationUrl } from "../util/documentation-url"; +import { onBoardingStyles } from "./styles"; @customElement("onboarding-analytics") class OnboardingAnalytics extends LitElement { @@ -23,7 +25,18 @@ class OnboardingAnalytics extends LitElement { protected render(): TemplateResult { return html` +

${this.localize("ui.panel.page-onboarding.analytics.header")}

${this.localize("ui.panel.page-onboarding.analytics.intro")}

+

+ + ${this.localize("ui.panel.page-onboarding.analytics.learn_more")} + + +

${this._error ? html`
${this._error}
` : ""} `; } @@ -81,27 +91,19 @@ class OnboardingAnalytics extends LitElement { } static get styles(): CSSResultGroup { - return css` - p { - font-size: 14px; - line-height: 20px; - } - .error { - color: var(--error-color); - } - .footer { - margin-top: 16px; - display: flex; - justify-content: space-between; - align-items: center; - flex-direction: row-reverse; - } - a { - color: var(--primary-color); - } - `; - - // footer is direction reverse to tab to "NEXT" first + return [ + onBoardingStyles, + css` + .error { + color: var(--error-color); + } + a { + color: var(--primary-color); + text-decoration: none; + --mdc-icon-size: 14px; + } + `, + ]; } } diff --git a/src/onboarding/onboarding-core-config.ts b/src/onboarding/onboarding-core-config.ts index 67ca87b9a9..6306e8ba64 100644 --- a/src/onboarding/onboarding-core-config.ts +++ b/src/onboarding/onboarding-core-config.ts @@ -13,15 +13,6 @@ import { fireEvent } from "../common/dom/fire_event"; import type { LocalizeFunc } from "../common/translations/localize"; import "../components/ha-alert"; import "../components/ha-country-picker"; -import "../components/ha-currency-picker"; -import "../components/ha-formfield"; -import "../components/ha-language-picker"; -import "../components/ha-radio"; -import type { HaRadio } from "../components/ha-radio"; -import "../components/ha-textfield"; -import type { HaTextField } from "../components/ha-textfield"; -import "../components/ha-timezone-picker"; -import "../components/map/ha-locations-editor"; import { ConfigUpdateValues, saveCoreConfig } from "../data/core"; import { countryCurrency } from "../data/currency"; import { onboardCoreConfigStep } from "../data/onboarding"; @@ -39,15 +30,16 @@ class OnboardingCoreConfig extends LitElement { @state() private _location?: [number, number]; - @state() private _elevation?: string; + private _elevation = "0"; - @state() private _unitSystem?: ConfigUpdateValues["unit_system"]; + private _unitSystem: ConfigUpdateValues["unit_system"] = "metric"; - @state() private _currency?: ConfigUpdateValues["currency"]; + private _currency: ConfigUpdateValues["currency"] = "EUR"; - @state() private _timeZone?: ConfigUpdateValues["time_zone"]; + private _timeZone: ConfigUpdateValues["time_zone"] = + Intl.DateTimeFormat?.().resolvedOptions?.().timeZone; - @state() private _language: ConfigUpdateValues["language"]; + private _language: ConfigUpdateValues["language"] = getLocalLanguage(); @state() private _country?: ConfigUpdateValues["country"]; @@ -69,155 +61,28 @@ class OnboardingCoreConfig extends LitElement { `; } return html` - ${ - this._error - ? html`${this._error}` - : nothing - } + ${this._error + ? html`${this._error}` + : nothing}

- ${this.onboardingLocalize( - "ui.panel.page-onboarding.core-config.intro_core_config" - )} + ${this.onboardingLocalize( + "ui.panel.page-onboarding.core-config.country_intro" + )}

-
- - - - -
- -
- - - - - -
- -
-
- ${this.hass.localize( - "ui.panel.config.core.section.core.core_config.unit_system" - )} -
-
- - ${this.hass.localize( - "ui.panel.config.core.section.core.core_config.metric_example" - )} -
`} - > - - - - ${this.hass.localize( - "ui.panel.config.core.section.core.core_config.us_customary_example" - )} -
`} - > - - - - - -
-
- ${this.hass.localize( - "ui.panel.config.core.section.core.core_config.currency" - )}
- ${this.hass.localize( - "ui.panel.config.core.section.core.core_config.find_currency_value" - )} -
- - -
- + +