mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-09 02:16:35 +00:00
Isolate hass state from base el (#3157)
This commit is contained in:
parent
8729410dce
commit
fcdb1b48a2
@ -1,4 +1,4 @@
|
||||
import { HomeAssistantAppEl } from "../../src/layouts/app/home-assistant";
|
||||
import { HomeAssistantAppEl } from "../../src/layouts/home-assistant";
|
||||
import {
|
||||
provideHass,
|
||||
MockHomeAssistant,
|
||||
@ -18,7 +18,7 @@ import { HomeAssistant } from "../../src/types";
|
||||
import { mockFrontend } from "./stubs/frontend";
|
||||
|
||||
class HaDemo extends HomeAssistantAppEl {
|
||||
protected async _handleConnProm() {
|
||||
protected async _initialize() {
|
||||
const initial: Partial<MockHomeAssistant> = {
|
||||
panelUrl: (this as any).panelUrl,
|
||||
// Override updateHass so that the correct hass lifecycle methods are called
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { HassEntity } from "home-assistant-js-websocket";
|
||||
import { forwardHaptic } from "../../util/haptics";
|
||||
import { forwardHaptic } from "../../data/haptics";
|
||||
|
||||
const isOn = (stateObj?: HassEntity) =>
|
||||
stateObj !== undefined && !STATES_OFF.includes(stateObj.state);
|
||||
@ -90,7 +90,7 @@ class HaEntityToggle extends LitElement {
|
||||
if (!this.hass || !this.stateObj) {
|
||||
return;
|
||||
}
|
||||
forwardHaptic(this, "light");
|
||||
forwardHaptic("light");
|
||||
const stateDomain = computeStateDomain(this.stateObj);
|
||||
let serviceDomain;
|
||||
let service;
|
||||
|
22
src/data/connection-status.ts
Normal file
22
src/data/connection-status.ts
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Broadcast connection status updates
|
||||
*/
|
||||
|
||||
import { fireEvent, HASSDomEvent } from "../common/dom/fire_event";
|
||||
|
||||
export type ConnectionStatus = "connected" | "auth-invalid" | "disconnected";
|
||||
|
||||
declare global {
|
||||
// for fire event
|
||||
interface HASSDomEvents {
|
||||
"connection-status": ConnectionStatus;
|
||||
}
|
||||
|
||||
interface GlobalEventHandlersEventMap {
|
||||
"connection-status": HASSDomEvent<ConnectionStatus>;
|
||||
}
|
||||
}
|
||||
|
||||
export const broadcastConnectionStatus = (status: ConnectionStatus) => {
|
||||
fireEvent(window, "connection-status", status);
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Utility function that enables haptic feedback
|
||||
* Broadcast haptic feedback requests
|
||||
*/
|
||||
|
||||
import { fireEvent, HASSDomEvent } from "../common/dom/fire_event";
|
||||
@ -27,6 +27,6 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
export const forwardHaptic = (el: HTMLElement, hapticType: HapticType) => {
|
||||
fireEvent(el, "haptic", hapticType);
|
||||
export const forwardHaptic = (hapticType: HapticType) => {
|
||||
fireEvent(window, "haptic", hapticType);
|
||||
};
|
@ -11,7 +11,7 @@ import "../resources/roboto";
|
||||
// properly into iron-meta, which is used to transfer iconsets to iron-icon.
|
||||
import "../components/ha-iconset-svg";
|
||||
|
||||
import "../layouts/app/home-assistant";
|
||||
import "../layouts/home-assistant";
|
||||
|
||||
setPassiveTouchGestures(true);
|
||||
/* LastPass createElement workaround. See #428 */
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ExternalMessaging } from "./external_messaging";
|
||||
|
||||
export const externalForwardConnectionEvents = (bus: ExternalMessaging) => {
|
||||
document.addEventListener("connection-status", (ev) =>
|
||||
window.addEventListener("connection-status", (ev) =>
|
||||
bus.fireMessage({
|
||||
type: "connection-status",
|
||||
payload: { event: ev.detail },
|
||||
@ -10,6 +10,6 @@ export const externalForwardConnectionEvents = (bus: ExternalMessaging) => {
|
||||
};
|
||||
|
||||
export const externalForwardHaptics = (bus: ExternalMessaging) =>
|
||||
document.addEventListener("haptic", (ev) =>
|
||||
window.addEventListener("haptic", (ev) =>
|
||||
bus.fireMessage({ type: "haptic", payload: { hapticType: ev.detail } })
|
||||
);
|
||||
|
@ -1,161 +0,0 @@
|
||||
import {
|
||||
ERR_INVALID_AUTH,
|
||||
subscribeEntities,
|
||||
subscribeConfig,
|
||||
subscribeServices,
|
||||
callService,
|
||||
} from "home-assistant-js-websocket";
|
||||
|
||||
import { translationMetadata } from "../../resources/translations-metadata";
|
||||
|
||||
import LocalizeMixin from "../../mixins/localize-mixin";
|
||||
import EventsMixin from "../../mixins/events-mixin";
|
||||
|
||||
import { getState } from "../../util/ha-pref-storage";
|
||||
import { getLocalLanguage } from "../../util/hass-translation";
|
||||
import { fetchWithAuth } from "../../util/fetch-with-auth";
|
||||
import hassCallApi from "../../util/hass-call-api";
|
||||
import { subscribePanels } from "../../data/ws-panels";
|
||||
import { forwardHaptic } from "../../util/haptics";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
|
||||
export default (superClass) =>
|
||||
class extends EventsMixin(LocalizeMixin(superClass)) {
|
||||
firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
this._handleConnProm();
|
||||
}
|
||||
|
||||
async _handleConnProm() {
|
||||
let auth;
|
||||
let conn;
|
||||
try {
|
||||
const result = await window.hassConnection;
|
||||
auth = result.auth;
|
||||
conn = result.conn;
|
||||
} catch (err) {
|
||||
this._error = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.hass = Object.assign(
|
||||
{
|
||||
auth,
|
||||
connection: conn,
|
||||
connected: true,
|
||||
states: null,
|
||||
config: null,
|
||||
themes: null,
|
||||
panels: null,
|
||||
services: null,
|
||||
user: null,
|
||||
panelUrl: this._panelUrl,
|
||||
|
||||
language: getLocalLanguage(),
|
||||
// If resources are already loaded, don't discard them
|
||||
resources: (this.hass && this.hass.resources) || null,
|
||||
localize: () => "",
|
||||
|
||||
translationMetadata: translationMetadata,
|
||||
dockedSidebar: false,
|
||||
moreInfoEntityId: null,
|
||||
callService: async (domain, service, serviceData = {}) => {
|
||||
if (__DEV__) {
|
||||
// eslint-disable-next-line
|
||||
console.log("Calling service", domain, service, serviceData);
|
||||
}
|
||||
try {
|
||||
await callService(conn, domain, service, serviceData);
|
||||
} catch (err) {
|
||||
if (__DEV__) {
|
||||
// eslint-disable-next-line
|
||||
console.error(
|
||||
"Error calling service",
|
||||
domain,
|
||||
service,
|
||||
serviceData,
|
||||
err
|
||||
);
|
||||
}
|
||||
forwardHaptic(this, "error");
|
||||
const message =
|
||||
this.hass.localize(
|
||||
"ui.notification_toast.service_call_failed",
|
||||
"service",
|
||||
`${domain}/${service}`
|
||||
) + ` ${err.message}`;
|
||||
this.fire("hass-notification", { message });
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
callApi: async (method, path, parameters) =>
|
||||
hassCallApi(auth, method, path, parameters),
|
||||
fetchWithAuth: (path, init) =>
|
||||
fetchWithAuth(auth, `${auth.data.hassUrl}${path}`, init),
|
||||
// For messages that do not get a response
|
||||
sendWS: (msg) => {
|
||||
if (__DEV__) {
|
||||
// eslint-disable-next-line
|
||||
console.log("Sending", msg);
|
||||
}
|
||||
conn.sendMessage(msg);
|
||||
},
|
||||
// For messages that expect a response
|
||||
callWS: (msg) => {
|
||||
if (__DEV__) {
|
||||
/* eslint-disable no-console */
|
||||
console.log("Sending", msg);
|
||||
}
|
||||
|
||||
const resp = conn.sendMessagePromise(msg);
|
||||
|
||||
if (__DEV__) {
|
||||
resp.then(
|
||||
(result) => console.log("Received", result),
|
||||
(err) => console.error("Error", err)
|
||||
);
|
||||
}
|
||||
return resp;
|
||||
},
|
||||
},
|
||||
getState()
|
||||
);
|
||||
|
||||
this.hassConnected();
|
||||
}
|
||||
|
||||
hassConnected() {
|
||||
super.hassConnected();
|
||||
|
||||
const conn = this.hass.connection;
|
||||
|
||||
fireEvent(document, "connection-status", "connected");
|
||||
|
||||
conn.addEventListener("ready", () => this.hassReconnected());
|
||||
conn.addEventListener("disconnected", () => this.hassDisconnected());
|
||||
// If we reconnect after losing connection and auth is no longer valid.
|
||||
conn.addEventListener("reconnect-error", (_conn, err) => {
|
||||
if (err === ERR_INVALID_AUTH) {
|
||||
fireEvent(document, "connection-status", "auth-invalid");
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
subscribeEntities(conn, (states) => this._updateHass({ states }));
|
||||
subscribeConfig(conn, (config) => this._updateHass({ config }));
|
||||
subscribeServices(conn, (services) => this._updateHass({ services }));
|
||||
subscribePanels(conn, (panels) => this._updateHass({ panels }));
|
||||
}
|
||||
|
||||
hassReconnected() {
|
||||
super.hassReconnected();
|
||||
this._updateHass({ connected: true });
|
||||
fireEvent(document, "connection-status", "connected");
|
||||
}
|
||||
|
||||
hassDisconnected() {
|
||||
super.hassDisconnected();
|
||||
this._updateHass({ connected: false });
|
||||
fireEvent(document, "connection-status", "disconnected");
|
||||
}
|
||||
};
|
@ -1,45 +1,20 @@
|
||||
import "@polymer/app-route/app-location";
|
||||
import { html, LitElement, PropertyValues, css, property } from "lit-element";
|
||||
|
||||
import "../home-assistant-main";
|
||||
import "../ha-init-page";
|
||||
import "../../resources/ha-style";
|
||||
import { registerServiceWorker } from "../../util/register-service-worker";
|
||||
import { DEFAULT_PANEL } from "../../common/const";
|
||||
import "./home-assistant-main";
|
||||
import "./ha-init-page";
|
||||
import "../resources/ha-style";
|
||||
import { registerServiceWorker } from "../util/register-service-worker";
|
||||
import { DEFAULT_PANEL } from "../common/const";
|
||||
|
||||
import HassBaseMixin from "./hass-base-mixin";
|
||||
import AuthMixin from "./auth-mixin";
|
||||
import TranslationsMixin from "./translations-mixin";
|
||||
import ThemesMixin from "./themes-mixin";
|
||||
import MoreInfoMixin from "./more-info-mixin";
|
||||
import SidebarMixin from "./sidebar-mixin";
|
||||
import { dialogManagerMixin } from "./dialog-manager-mixin";
|
||||
import ConnectionMixin from "./connection-mixin";
|
||||
import NotificationMixin from "./notification-mixin";
|
||||
import DisconnectToastMixin from "./disconnect-toast-mixin";
|
||||
import { urlSyncMixin } from "./url-sync-mixin";
|
||||
|
||||
import { Route, HomeAssistant } from "../../types";
|
||||
import { navigate } from "../../common/navigate";
|
||||
import { Route, HomeAssistant } from "../types";
|
||||
import { navigate } from "../common/navigate";
|
||||
import { HassElement } from "../state/hass-element";
|
||||
|
||||
(LitElement.prototype as any).html = html;
|
||||
(LitElement.prototype as any).css = css;
|
||||
|
||||
const ext = <T>(baseClass: T, mixins): T =>
|
||||
mixins.reduceRight((base, mixin) => mixin(base), baseClass);
|
||||
|
||||
export class HomeAssistantAppEl extends ext(HassBaseMixin(LitElement), [
|
||||
AuthMixin,
|
||||
ThemesMixin,
|
||||
TranslationsMixin,
|
||||
MoreInfoMixin,
|
||||
SidebarMixin,
|
||||
DisconnectToastMixin,
|
||||
ConnectionMixin,
|
||||
NotificationMixin,
|
||||
dialogManagerMixin,
|
||||
urlSyncMixin,
|
||||
]) {
|
||||
export class HomeAssistantAppEl extends HassElement {
|
||||
@property() private _route?: Route;
|
||||
@property() private _error?: boolean;
|
||||
@property() private _panelUrl?: string;
|
||||
@ -69,6 +44,7 @@ export class HomeAssistantAppEl extends ext(HassBaseMixin(LitElement), [
|
||||
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
this._initialize();
|
||||
setTimeout(registerServiceWorker, 1000);
|
||||
/* polyfill for paper-dropdown */
|
||||
import(/* webpackChunkName: "polyfill-web-animations-next" */ "web-animations-js/web-animations-next-lite.min");
|
||||
@ -86,6 +62,16 @@ export class HomeAssistantAppEl extends ext(HassBaseMixin(LitElement), [
|
||||
}
|
||||
}
|
||||
|
||||
protected async _initialize() {
|
||||
try {
|
||||
const { auth, conn } = await window.hassConnection;
|
||||
this.initializeHass(auth, conn);
|
||||
} catch (err) {
|
||||
this._error = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private _routeChanged(ev) {
|
||||
const route = ev.detail.value as Route;
|
||||
// If it's the first route that we process,
|
@ -13,7 +13,7 @@ import { PaperToggleButtonElement } from "@polymer/paper-toggle-button/paper-tog
|
||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||
import { turnOnOffEntities } from "../common/entity/turn-on-off-entities";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { forwardHaptic } from "../../../util/haptics";
|
||||
import { forwardHaptic } from "../../../data/haptics";
|
||||
|
||||
@customElement("hui-entities-toggle")
|
||||
class HuiEntitiesToggle extends LitElement {
|
||||
@ -66,7 +66,7 @@ class HuiEntitiesToggle extends LitElement {
|
||||
}
|
||||
|
||||
private _callService(ev: MouseEvent): void {
|
||||
forwardHaptic(this, "light");
|
||||
forwardHaptic("light");
|
||||
const turnOn = (ev.target as PaperToggleButtonElement).checked;
|
||||
turnOnOffEntities(this.hass!, this._toggleEntities!, turnOn!);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import { HomeAssistant, InputSelectEntity } from "../../../types";
|
||||
import { EntityRow, EntityConfig } from "./types";
|
||||
import { setInputSelectOption } from "../../../data/input-select";
|
||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { forwardHaptic } from "../../../util/haptics";
|
||||
import { forwardHaptic } from "../../../data/haptics";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
|
||||
@customElement("hui-input-select-entity-row")
|
||||
@ -128,7 +128,7 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
|
||||
return;
|
||||
}
|
||||
|
||||
forwardHaptic(this, "light");
|
||||
forwardHaptic("light");
|
||||
|
||||
setInputSelectOption(
|
||||
this.hass!,
|
||||
|
@ -1,16 +1,5 @@
|
||||
import * as translationMetadata_ from "../../build-translations/translationMetadata.json";
|
||||
|
||||
interface TranslationMetadata {
|
||||
fragments: string[];
|
||||
translations: {
|
||||
[language: string]: {
|
||||
nativeName: string;
|
||||
fingerprints: {
|
||||
[filename: string]: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
import { TranslationMetadata } from "../types.js";
|
||||
|
||||
export const translationMetadata = (translationMetadata_ as any)
|
||||
.default as TranslationMetadata;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { clearState } from "../../util/ha-pref-storage";
|
||||
import { askWrite } from "../../common/auth/token_storage";
|
||||
import { subscribeUser, userCollection } from "../../data/ws-user";
|
||||
import { clearState } from "../util/ha-pref-storage";
|
||||
import { askWrite } from "../common/auth/token_storage";
|
||||
import { subscribeUser, userCollection } from "../data/ws-user";
|
||||
import { Constructor, LitElement } from "lit-element";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
|
||||
@ -30,7 +30,7 @@ export default (superClass: Constructor<LitElement & HassBaseEl>) =>
|
||||
if (askWrite()) {
|
||||
this.updateComplete
|
||||
.then(() =>
|
||||
import(/* webpackChunkName: "ha-store-auth-card" */ "../../dialogs/ha-store-auth-card")
|
||||
import(/* webpackChunkName: "ha-store-auth-card" */ "../dialogs/ha-store-auth-card")
|
||||
)
|
||||
.then(() => {
|
||||
const el = document.createElement("ha-store-auth-card");
|
149
src/state/connection-mixin.ts
Normal file
149
src/state/connection-mixin.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import {
|
||||
ERR_INVALID_AUTH,
|
||||
subscribeEntities,
|
||||
subscribeConfig,
|
||||
subscribeServices,
|
||||
callService,
|
||||
Auth,
|
||||
Connection,
|
||||
} from "home-assistant-js-websocket";
|
||||
|
||||
import { translationMetadata } from "../resources/translations-metadata";
|
||||
|
||||
import { getState } from "../util/ha-pref-storage";
|
||||
import { getLocalLanguage } from "../util/hass-translation";
|
||||
import { fetchWithAuth } from "../util/fetch-with-auth";
|
||||
import hassCallApi from "../util/hass-call-api";
|
||||
import { subscribePanels } from "../data/ws-panels";
|
||||
import { forwardHaptic } from "../data/haptics";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
import { Constructor, LitElement } from "lit-element";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { broadcastConnectionStatus } from "../data/connection-status";
|
||||
|
||||
export const connectionMixin = (
|
||||
superClass: Constructor<LitElement & HassBaseEl>
|
||||
) =>
|
||||
class extends superClass {
|
||||
protected initializeHass(auth: Auth, conn: Connection) {
|
||||
this.hass = {
|
||||
auth,
|
||||
connection: conn,
|
||||
connected: true,
|
||||
states: null as any,
|
||||
config: null as any,
|
||||
themes: null as any,
|
||||
panels: null as any,
|
||||
services: null as any,
|
||||
user: null as any,
|
||||
panelUrl: (this as any)._panelUrl,
|
||||
|
||||
language: getLocalLanguage(),
|
||||
selectedLanguage: null,
|
||||
resources: null as any,
|
||||
localize: () => "",
|
||||
|
||||
translationMetadata,
|
||||
dockedSidebar: false,
|
||||
moreInfoEntityId: null,
|
||||
callService: async (domain, service, serviceData = {}) => {
|
||||
if (__DEV__) {
|
||||
// tslint:disable-next-line: no-console
|
||||
console.log("Calling service", domain, service, serviceData);
|
||||
}
|
||||
try {
|
||||
await callService(conn, domain, service, serviceData);
|
||||
} catch (err) {
|
||||
if (__DEV__) {
|
||||
// tslint:disable-next-line: no-console
|
||||
console.error(
|
||||
"Error calling service",
|
||||
domain,
|
||||
service,
|
||||
serviceData,
|
||||
err
|
||||
);
|
||||
}
|
||||
forwardHaptic("failure");
|
||||
const message =
|
||||
(this as any).hass.localize(
|
||||
"ui.notification_toast.service_call_failed",
|
||||
"service",
|
||||
`${domain}/${service}`
|
||||
) + ` ${err.message}`;
|
||||
fireEvent(this as any, "hass-notification", { message });
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
callApi: async (method, path, parameters) =>
|
||||
hassCallApi(auth, method, path, parameters),
|
||||
fetchWithAuth: (path, init) =>
|
||||
fetchWithAuth(auth, `${auth.data.hassUrl}${path}`, init),
|
||||
// For messages that do not get a response
|
||||
sendWS: (msg) => {
|
||||
if (__DEV__) {
|
||||
// tslint:disable-next-line: no-console
|
||||
console.log("Sending", msg);
|
||||
}
|
||||
conn.sendMessage(msg);
|
||||
},
|
||||
// For messages that expect a response
|
||||
callWS: <T>(msg) => {
|
||||
if (__DEV__) {
|
||||
// tslint:disable-next-line: no-console
|
||||
console.log("Sending", msg);
|
||||
}
|
||||
|
||||
const resp = conn.sendMessagePromise<T>(msg);
|
||||
|
||||
if (__DEV__) {
|
||||
resp.then(
|
||||
// tslint:disable-next-line: no-console
|
||||
(result) => console.log("Received", result),
|
||||
// tslint:disable-next-line: no-console
|
||||
(err) => console.error("Error", err)
|
||||
);
|
||||
}
|
||||
return resp;
|
||||
},
|
||||
...getState(),
|
||||
};
|
||||
|
||||
this.hassConnected();
|
||||
}
|
||||
|
||||
protected hassConnected() {
|
||||
super.hassConnected();
|
||||
|
||||
const conn = this.hass!.connection;
|
||||
|
||||
broadcastConnectionStatus("connected");
|
||||
|
||||
conn.addEventListener("ready", () => this.hassReconnected());
|
||||
conn.addEventListener("disconnected", () => this.hassDisconnected());
|
||||
// If we reconnect after losing connection and auth is no longer valid.
|
||||
conn.addEventListener("reconnect-error", (_conn, err) => {
|
||||
if (err === ERR_INVALID_AUTH) {
|
||||
broadcastConnectionStatus("auth-invalid");
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
subscribeEntities(conn, (states) => this._updateHass({ states }));
|
||||
subscribeConfig(conn, (config) => this._updateHass({ config }));
|
||||
subscribeServices(conn, (services) => this._updateHass({ services }));
|
||||
subscribePanels(conn, (panels) => this._updateHass({ panels }));
|
||||
}
|
||||
|
||||
protected hassReconnected() {
|
||||
super.hassReconnected();
|
||||
this._updateHass({ connected: true });
|
||||
broadcastConnectionStatus("connected");
|
||||
}
|
||||
|
||||
protected hassDisconnected() {
|
||||
super.hassDisconnected();
|
||||
this._updateHass({ connected: false });
|
||||
broadcastConnectionStatus("disconnected");
|
||||
}
|
||||
};
|
@ -1,10 +1,7 @@
|
||||
import { Constructor, LitElement } from "lit-element";
|
||||
import { HASSDomEvent } from "../../common/dom/fire_event";
|
||||
import { HASSDomEvent } from "../common/dom/fire_event";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import {
|
||||
makeDialogManager,
|
||||
showDialog,
|
||||
} from "../../dialogs/make-dialog-manager";
|
||||
import { makeDialogManager, showDialog } from "../dialogs/make-dialog-manager";
|
||||
|
||||
interface RegisterDialogParams {
|
||||
dialogShowEvent: keyof HASSDomEvents;
|
@ -1,7 +1,7 @@
|
||||
import { Constructor, LitElement } from "lit-element";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { HaToast } from "../../components/ha-toast";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import { HaToast } from "../components/ha-toast";
|
||||
import { computeRTL } from "../common/util/compute_rtl";
|
||||
|
||||
export default (superClass: Constructor<LitElement & HassBaseEl>) =>
|
||||
class extends superClass {
|
||||
@ -10,7 +10,7 @@ export default (superClass: Constructor<LitElement & HassBaseEl>) =>
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
// Need to load in advance because when disconnected, can't dynamically load code.
|
||||
import(/* webpackChunkName: "ha-toast" */ "../../components/ha-toast");
|
||||
import(/* webpackChunkName: "ha-toast" */ "../components/ha-toast");
|
||||
}
|
||||
|
||||
protected hassReconnected() {
|
@ -3,12 +3,14 @@ import {
|
||||
// @ts-ignore
|
||||
property,
|
||||
} from "lit-element";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { Auth, Connection } from "home-assistant-js-websocket";
|
||||
import { HomeAssistant } from "../types";
|
||||
|
||||
/* tslint:disable */
|
||||
|
||||
export class HassBaseEl {
|
||||
protected hass?: HomeAssistant;
|
||||
protected initializeHass(_auth: Auth, _conn: Connection) {}
|
||||
protected hassConnected() {}
|
||||
protected hassReconnected() {}
|
||||
protected hassDisconnected() {}
|
28
src/state/hass-element.ts
Normal file
28
src/state/hass-element.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import HassBaseMixin from "./hass-base-mixin";
|
||||
import AuthMixin from "./auth-mixin";
|
||||
import TranslationsMixin from "./translations-mixin";
|
||||
import ThemesMixin from "./themes-mixin";
|
||||
import MoreInfoMixin from "./more-info-mixin";
|
||||
import SidebarMixin from "./sidebar-mixin";
|
||||
import { dialogManagerMixin } from "./dialog-manager-mixin";
|
||||
import { connectionMixin } from "./connection-mixin";
|
||||
import NotificationMixin from "./notification-mixin";
|
||||
import DisconnectToastMixin from "./disconnect-toast-mixin";
|
||||
import { urlSyncMixin } from "./url-sync-mixin";
|
||||
import { LitElement } from "lit-element";
|
||||
|
||||
const ext = <T>(baseClass: T, mixins): T =>
|
||||
mixins.reduceRight((base, mixin) => mixin(base), baseClass);
|
||||
|
||||
export class HassElement extends ext(HassBaseMixin(LitElement), [
|
||||
AuthMixin,
|
||||
ThemesMixin,
|
||||
TranslationsMixin,
|
||||
MoreInfoMixin,
|
||||
SidebarMixin,
|
||||
DisconnectToastMixin,
|
||||
connectionMixin,
|
||||
NotificationMixin,
|
||||
dialogManagerMixin,
|
||||
urlSyncMixin,
|
||||
]) {}
|
@ -20,7 +20,7 @@ export default (superClass: Constructor<LitElement & HassBaseEl>) =>
|
||||
this.addEventListener("hass-more-info", (e) => this._handleMoreInfo(e));
|
||||
|
||||
// Load it once we are having the initial rendering done.
|
||||
import(/* webpackChunkName: "more-info-dialog" */ "../../dialogs/ha-more-info-dialog");
|
||||
import(/* webpackChunkName: "more-info-dialog" */ "../dialogs/ha-more-info-dialog");
|
||||
}
|
||||
|
||||
private async _handleMoreInfo(ev) {
|
@ -6,7 +6,7 @@ export default (superClass) =>
|
||||
dialogShowEvent: "hass-notification",
|
||||
dialogTag: "notification-manager",
|
||||
dialogImport: () =>
|
||||
import(/* webpackChunkName: "notification-manager" */ "../../managers/notification-manager"),
|
||||
import(/* webpackChunkName: "notification-manager" */ "../managers/notification-manager"),
|
||||
});
|
||||
}
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
import { storeState } from "../../util/ha-pref-storage";
|
||||
import { storeState } from "../util/ha-pref-storage";
|
||||
import { Constructor, LitElement } from "lit-element";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { HASSDomEvent } from "../../common/dom/fire_event";
|
||||
import { HASSDomEvent } from "../common/dom/fire_event";
|
||||
|
||||
interface DockSidebarParams {
|
||||
dock: boolean;
|
@ -1,9 +1,9 @@
|
||||
import applyThemesOnElement from "../../common/dom/apply_themes_on_element";
|
||||
import { storeState } from "../../util/ha-pref-storage";
|
||||
import { subscribeThemes } from "../../data/ws-themes";
|
||||
import applyThemesOnElement from "../common/dom/apply_themes_on_element";
|
||||
import { storeState } from "../util/ha-pref-storage";
|
||||
import { subscribeThemes } from "../data/ws-themes";
|
||||
import { Constructor, LitElement } from "lit-element";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { HASSDomEvent } from "../../common/dom/fire_event";
|
||||
import { HASSDomEvent } from "../common/dom/fire_event";
|
||||
|
||||
declare global {
|
||||
// for add event listener
|
@ -1,17 +1,17 @@
|
||||
import { translationMetadata } from "../../resources/translations-metadata";
|
||||
import { translationMetadata } from "../resources/translations-metadata";
|
||||
import {
|
||||
getTranslation,
|
||||
getLocalLanguage,
|
||||
getUserLanguage,
|
||||
} from "../../util/hass-translation";
|
||||
} from "../util/hass-translation";
|
||||
import { Constructor, LitElement } from "lit-element";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { computeLocalize } from "../../common/translations/localize";
|
||||
import { computeRTL } from "../../common/util/compute_rtl";
|
||||
import { HomeAssistant } from "../../types";
|
||||
import { saveFrontendUserData } from "../../data/frontend";
|
||||
import { storeState } from "../../util/ha-pref-storage";
|
||||
import { getHassTranslations } from "../../data/translation";
|
||||
import { computeLocalize } from "../common/translations/localize";
|
||||
import { computeRTL } from "../common/util/compute_rtl";
|
||||
import { HomeAssistant } from "../types";
|
||||
import { saveFrontendUserData } from "../data/frontend";
|
||||
import { storeState } from "../util/ha-pref-storage";
|
||||
import { getHassTranslations } from "../data/translation";
|
||||
|
||||
/*
|
||||
* superClass needs to contain `this.hass` and `this._updateHass`.
|
@ -1,6 +1,6 @@
|
||||
import { Constructor, LitElement } from "lit-element";
|
||||
import { HassBaseEl } from "./hass-base-mixin";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
|
||||
/* tslint:disable:no-console */
|
||||
const DEBUG = false;
|
28
src/types.ts
28
src/types.ts
@ -10,7 +10,6 @@ import {
|
||||
} from "home-assistant-js-websocket";
|
||||
import { LocalizeFunc } from "./common/translations/localize";
|
||||
import { ExternalMessaging } from "./external_app/external_messaging";
|
||||
import { HASSDomEvent } from "./common/dom/fire_event";
|
||||
|
||||
declare global {
|
||||
var __DEV__: boolean;
|
||||
@ -38,16 +37,9 @@ declare global {
|
||||
value: unknown;
|
||||
};
|
||||
change: undefined;
|
||||
"connection-status": ConnectionStatus;
|
||||
}
|
||||
|
||||
interface GlobalEventHandlersEventMap {
|
||||
"connection-status": HASSDomEvent<ConnectionStatus>;
|
||||
}
|
||||
}
|
||||
|
||||
type ConnectionStatus = "connected" | "auth-invalid" | "disconnected";
|
||||
|
||||
export interface WebhookError {
|
||||
code: number;
|
||||
message: string;
|
||||
@ -103,6 +95,13 @@ export interface Translation {
|
||||
fingerprints: { [fragment: string]: string };
|
||||
}
|
||||
|
||||
export interface TranslationMetadata {
|
||||
fragments: string[];
|
||||
translations: {
|
||||
[lang: string]: Translation;
|
||||
};
|
||||
}
|
||||
|
||||
export interface Notification {
|
||||
notification_id: string;
|
||||
message: string;
|
||||
@ -135,18 +134,13 @@ export interface HomeAssistant {
|
||||
// - english (en)
|
||||
language: string;
|
||||
// local stored language, keep that name for backward compability
|
||||
selectedLanguage: string;
|
||||
selectedLanguage: string | null;
|
||||
resources: Resources;
|
||||
localize: LocalizeFunc;
|
||||
translationMetadata: {
|
||||
fragments: string[];
|
||||
translations: {
|
||||
[lang: string]: Translation;
|
||||
};
|
||||
};
|
||||
translationMetadata: TranslationMetadata;
|
||||
|
||||
dockedSidebar: boolean;
|
||||
moreInfoEntityId: string;
|
||||
moreInfoEntityId: string | null;
|
||||
user?: CurrentUser;
|
||||
callService: (
|
||||
domain: string,
|
||||
@ -162,7 +156,7 @@ export interface HomeAssistant {
|
||||
path: string,
|
||||
init?: { [key: string]: any }
|
||||
) => Promise<Response>;
|
||||
sendWS: (msg: MessageBase) => Promise<void>;
|
||||
sendWS: (msg: MessageBase) => void;
|
||||
callWS: <T>(msg: MessageBase) => Promise<T>;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user