diff --git a/package.json b/package.json index e6d2d93726..5f3c81026d 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "google-timezones-json": "^1.0.2", "hammerjs": "^2.0.8", "hls.js": "^1.2.5", - "home-assistant-js-websocket": "^8.0.0", + "home-assistant-js-websocket": "^8.0.1", "idb-keyval": "^5.1.3", "intl-messageformat": "^9.9.1", "js-yaml": "^4.1.0", diff --git a/src/components/country-datalist.ts b/src/components/country-datalist.ts new file mode 100644 index 0000000000..c972a77fd6 --- /dev/null +++ b/src/components/country-datalist.ts @@ -0,0 +1,273 @@ +export const countries = [ + "AD", + "AE", + "AF", + "AG", + "AI", + "AL", + "AM", + "AO", + "AQ", + "AR", + "AS", + "AT", + "AU", + "AW", + "AX", + "AZ", + "BA", + "BB", + "BD", + "BE", + "BF", + "BG", + "BH", + "BI", + "BJ", + "BL", + "BM", + "BN", + "BO", + "BQ", + "BR", + "BS", + "BT", + "BV", + "BW", + "BY", + "BZ", + "CA", + "CC", + "CD", + "CF", + "CG", + "CH", + "CI", + "CK", + "CL", + "CM", + "CN", + "CO", + "CR", + "CU", + "CV", + "CW", + "CX", + "CY", + "CZ", + "DE", + "DJ", + "DK", + "DM", + "DO", + "DZ", + "EC", + "EE", + "EG", + "EH", + "ER", + "ES", + "ET", + "FI", + "FJ", + "FK", + "FM", + "FO", + "FR", + "GA", + "GB", + "GD", + "GE", + "GF", + "GG", + "GH", + "GI", + "GL", + "GM", + "GN", + "GP", + "GQ", + "GR", + "GS", + "GT", + "GU", + "GW", + "GY", + "HK", + "HM", + "HN", + "HR", + "HT", + "HU", + "ID", + "IE", + "IL", + "IM", + "IN", + "IO", + "IQ", + "IR", + "IS", + "IT", + "JE", + "JM", + "JO", + "JP", + "KE", + "KG", + "KH", + "KI", + "KM", + "KN", + "KP", + "KR", + "KW", + "KY", + "KZ", + "LA", + "LB", + "LC", + "LI", + "LK", + "LR", + "LS", + "LT", + "LU", + "LV", + "LY", + "MA", + "MC", + "MD", + "ME", + "MF", + "MG", + "MH", + "MK", + "ML", + "MM", + "MN", + "MO", + "MP", + "MQ", + "MR", + "MS", + "MT", + "MU", + "MV", + "MW", + "MX", + "MY", + "MZ", + "NA", + "NC", + "NE", + "NF", + "NG", + "NI", + "NL", + "NO", + "NP", + "NR", + "NU", + "NZ", + "OM", + "PA", + "PE", + "PF", + "PG", + "PH", + "PK", + "PL", + "PM", + "PN", + "PR", + "PS", + "PT", + "PW", + "PY", + "QA", + "RE", + "RO", + "RS", + "RU", + "RW", + "SA", + "SB", + "SC", + "SD", + "SE", + "SG", + "SH", + "SI", + "SJ", + "SK", + "SL", + "SM", + "SN", + "SO", + "SR", + "SS", + "ST", + "SV", + "SX", + "SY", + "SZ", + "TC", + "TD", + "TF", + "TG", + "TH", + "TJ", + "TK", + "TL", + "TM", + "TN", + "TO", + "TR", + "TT", + "TV", + "TW", + "TZ", + "UA", + "UG", + "UM", + "US", + "UY", + "UZ", + "VA", + "VC", + "VE", + "VG", + "VI", + "VN", + "VU", + "WF", + "WS", + "YE", + "YT", + "ZA", + "ZM", + "ZW", +]; + +export const countryDisplayNames = + Intl && "DisplayNames" in Intl + ? new Intl.DisplayNames(undefined, { + type: "region", + fallback: "code", + }) + : undefined; + +export const createCountryListEl = () => { + const list = document.createElement("datalist"); + list.id = "countries"; + for (const country of countries) { + const option = document.createElement("option"); + option.value = country; + option.innerText = countryDisplayNames + ? countryDisplayNames.of(country)! + : country; + list.appendChild(option); + } + return list; +}; diff --git a/src/components/currency-datalist.ts b/src/components/currency-datalist.ts index 69a69e7222..c725b8258c 100644 --- a/src/components/currency-datalist.ts +++ b/src/components/currency-datalist.ts @@ -158,13 +158,23 @@ export const currencies = [ "ZWL", ]; +export const currencyDisplayNames = + Intl && "DisplayNames" in Intl + ? new Intl.DisplayNames(undefined, { + type: "currency", + fallback: "code", + }) + : undefined; + export const createCurrencyListEl = () => { const list = document.createElement("datalist"); list.id = "currencies"; for (const currency of currencies) { const option = document.createElement("option"); option.value = currency; - option.innerHTML = currency; + option.innerText = currencyDisplayNames + ? currencyDisplayNames.of(currency)! + : currency; list.appendChild(option); } return list; diff --git a/src/components/ha-textfield.ts b/src/components/ha-textfield.ts index dbfbc1cc38..6264784e81 100644 --- a/src/components/ha-textfield.ts +++ b/src/components/ha-textfield.ts @@ -1,7 +1,7 @@ import { TextFieldBase } from "@material/mwc-textfield/mwc-textfield-base"; import { styles } from "@material/mwc-textfield/mwc-textfield.css"; import { TemplateResult, html, PropertyValues, css } from "lit"; -import { customElement, property } from "lit/decorators"; +import { customElement, property, query } from "lit/decorators"; @customElement("ha-textfield") export class HaTextField extends TextFieldBase { @@ -17,6 +17,8 @@ export class HaTextField extends TextFieldBase { @property() public autocomplete?: string; + @query("input") public formElement!: HTMLInputElement; + override updated(changedProperties: PropertyValues) { super.updated(changedProperties); if ( diff --git a/src/components/language-datalist.ts b/src/components/language-datalist.ts new file mode 100644 index 0000000000..bac8b44c9c --- /dev/null +++ b/src/components/language-datalist.ts @@ -0,0 +1,15 @@ +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/components/map/ha-map.ts b/src/components/map/ha-map.ts index ce395d170b..d9294bc58c 100644 --- a/src/components/map/ha-map.ts +++ b/src/components/map/ha-map.ts @@ -133,11 +133,11 @@ export class HaMap extends ReactiveElement { if ( !changedProps.has("darkMode") && (!changedProps.has("hass") || - (oldHass && oldHass.themes.darkMode === this.hass.themes.darkMode)) + (oldHass && oldHass.themes?.darkMode === this.hass.themes?.darkMode)) ) { return; } - const darkMode = this.darkMode ?? this.hass.themes.darkMode; + const darkMode = this.darkMode ?? this.hass.themes?.darkMode; this.shadowRoot!.getElementById("map")!.classList.toggle("dark", darkMode); } diff --git a/src/components/timezone-datalist.ts b/src/components/timezone-datalist.ts index 05bfa1c0ab..1d4a705408 100644 --- a/src/components/timezone-datalist.ts +++ b/src/components/timezone-datalist.ts @@ -6,7 +6,7 @@ export const createTimezoneListEl = () => { Object.keys(timezones).forEach((key) => { const option = document.createElement("option"); option.value = key; - option.innerHTML = timezones[key]; + option.innerText = timezones[key]; list.appendChild(option); }); return list; diff --git a/src/data/core.ts b/src/data/core.ts index 8d5c231e2b..a2b944e3bd 100644 --- a/src/data/core.ts +++ b/src/data/core.ts @@ -11,6 +11,8 @@ export interface ConfigUpdateValues { external_url?: string | null; internal_url?: string | null; currency?: string | null; + country?: string | null; + language?: string | null; } export interface CheckConfigResult { diff --git a/src/fake_data/demo_config.ts b/src/fake_data/demo_config.ts index ae5a528ff3..e9efe63c65 100644 --- a/src/fake_data/demo_config.ts +++ b/src/fake_data/demo_config.ts @@ -32,4 +32,6 @@ export const demoConfig: HassConfig = { internal_url: "http://homeassistant.local:8123", external_url: null, currency: "USD", + language: "en", + country: "NL", }; diff --git a/src/onboarding/ha-onboarding.ts b/src/onboarding/ha-onboarding.ts index 28de65a955..1c4e6ffbe5 100644 --- a/src/onboarding/ha-onboarding.ts +++ b/src/onboarding/ha-onboarding.ts @@ -131,21 +131,6 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { if (window.innerWidth > 450) { import("./particles"); } - if (matchMedia("(prefers-color-scheme: dark)").matches) { - applyThemesOnElement( - document.documentElement, - { - default_theme: "default", - default_dark_theme: null, - themes: {}, - darkMode: true, - theme: "default", - }, - undefined, - undefined, - true - ); - } } protected updated(changedProps: PropertyValues) { @@ -154,10 +139,25 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) { document.querySelector("html")!.setAttribute("lang", this.language!); } if (changedProps.has("hass")) { - this.hassChanged( - this.hass!, - changedProps.get("hass") as HomeAssistant | undefined - ); + const oldHass = changedProps.get("hass") as HomeAssistant | undefined; + this.hassChanged(this.hass!, oldHass); + if (oldHass?.themes !== this.hass!.themes) { + if (matchMedia("(prefers-color-scheme: dark)").matches) { + applyThemesOnElement( + document.documentElement, + { + default_theme: "default", + default_dark_theme: null, + themes: {}, + darkMode: true, + theme: "default", + }, + undefined, + undefined, + true + ); + } + } } } diff --git a/src/onboarding/onboarding-core-config.ts b/src/onboarding/onboarding-core-config.ts index 05a996f6fe..50cb216d87 100644 --- a/src/onboarding/onboarding-core-config.ts +++ b/src/onboarding/onboarding-core-config.ts @@ -1,6 +1,4 @@ import "@material/mwc-button/mwc-button"; -import "@polymer/paper-input/paper-input"; -import type { PaperInputElement } from "@polymer/paper-input/paper-input"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import memoizeOne from "memoize-one"; @@ -25,6 +23,11 @@ import type { HomeAssistant } from "../types"; import "../components/ha-radio"; import "../components/ha-formfield"; import type { HaRadio } from "../components/ha-radio"; +import type { HaTextField } from "../components/ha-textfield"; +import "../components/ha-textfield"; +import { getLocalLanguage } from "../util/common-translation"; +import { createCountryListEl } from "../components/country-datalist"; +import { createLanguageListEl } from "../components/language-datalist"; const amsterdam: [number, number] = [52.3731339, 4.8903147]; const mql = matchMedia("(prefers-color-scheme: dark)"); @@ -50,6 +53,10 @@ class OnboardingCoreConfig extends LitElement { @state() private _timeZone?: string; + @state() private _language?: ConfigUpdateValues["language"]; + + @state() private _country?: ConfigUpdateValues["country"]; + @query("ha-locations-editor", true) private map!: HaLocationsEditor; protected render(): TemplateResult { @@ -62,15 +69,15 @@ class OnboardingCoreConfig extends LitElement { )}
-@@ -105,19 +112,42 @@ class OnboardingCoreConfig extends LitElement {