From 2dd5cd586b91fce79fa4e97491ee4880d4ac0b29 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 27 Sep 2019 10:23:30 +0200 Subject: [PATCH] Add a setting for vibration (#3813) * Add a setting for vibration * Update en.json --- src/fake_data/provide_hass.ts | 1 + src/panels/profile/ha-force-narrow-row.ts | 4 +- src/panels/profile/ha-panel-profile.ts | 9 ++++ src/panels/profile/ha-set-vibrate-row.ts | 56 +++++++++++++++++++++++ src/state/connection-mixin.ts | 1 + src/state/haptic-mixin.ts | 40 ++++++++++++++-- src/translations/en.json | 4 ++ src/types.ts | 1 + src/util/ha-pref-storage.ts | 8 +++- 9 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 src/panels/profile/ha-set-vibrate-row.ts diff --git a/src/fake_data/provide_hass.ts b/src/fake_data/provide_hass.ts index eb711cc348..bdb58eee00 100644 --- a/src/fake_data/provide_hass.ts +++ b/src/fake_data/provide_hass.ts @@ -178,6 +178,7 @@ export const provideHass = ( translationMetadata: translationMetadata as any, dockedSidebar: "auto", + vibrate: true, moreInfoEntityId: null as any, async callService(domain, service, data) { if (data && "entity_id" in data) { diff --git a/src/panels/profile/ha-force-narrow-row.ts b/src/panels/profile/ha-force-narrow-row.ts index e490d563c9..86afd56681 100644 --- a/src/panels/profile/ha-force-narrow-row.ts +++ b/src/panels/profile/ha-force-narrow-row.ts @@ -15,7 +15,7 @@ import { fireEvent } from "../../common/dom/fire_event"; import { HaSwitch } from "../../components/ha-switch"; @customElement("ha-force-narrow-row") -class HaPushNotificationsRow extends LitElement { +class HaForcedNarrowRow extends LitElement { @property() public hass!: HomeAssistant; @property() public narrow!: boolean; @@ -49,6 +49,6 @@ class HaPushNotificationsRow extends LitElement { declare global { interface HTMLElementTagNameMap { - "ha-force-narrow-row": HaPushNotificationsRow; + "ha-force-narrow-row": HaForcedNarrowRow; } } diff --git a/src/panels/profile/ha-panel-profile.ts b/src/panels/profile/ha-panel-profile.ts index 02b485acc5..1848660140 100644 --- a/src/panels/profile/ha-panel-profile.ts +++ b/src/panels/profile/ha-panel-profile.ts @@ -24,6 +24,7 @@ import "./ha-pick-language-row"; import "./ha-pick-theme-row"; import "./ha-push-notifications-row"; import "./ha-force-narrow-row"; +import "./ha-set-vibrate-row"; import { LitElement, TemplateResult, @@ -105,6 +106,14 @@ class HaPanelProfile extends LitElement { > ` : ""} + ${navigator.vibrate + ? html` + + ` + : ""} + + ${this.hass.localize("ui.panel.profile.vibrate.header")} + + + ${this.hass.localize("ui.panel.profile.vibrate.description")} + + + + `; + } + + private async _checkedChanged(ev: Event) { + const vibrate = (ev.target as HaSwitch).checked; + if (vibrate === this.hass.vibrate) { + return; + } + fireEvent(this, "hass-vibrate", { + vibrate, + }); + forwardHaptic("light"); + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-set-vibrate-row": HaSetVibrateRow; + } +} diff --git a/src/state/connection-mixin.ts b/src/state/connection-mixin.ts index d3ecd7b1e0..eb439c8135 100644 --- a/src/state/connection-mixin.ts +++ b/src/state/connection-mixin.ts @@ -45,6 +45,7 @@ export const connectionMixin = ( translationMetadata, dockedSidebar: "docked", + vibrate: true, moreInfoEntityId: null, hassUrl: (path = "") => new URL(path, auth.data.hassUrl).toString(), callService: async (domain, service, serviceData = {}) => { diff --git a/src/state/haptic-mixin.ts b/src/state/haptic-mixin.ts index 58bd47129a..44c02664c9 100644 --- a/src/state/haptic-mixin.ts +++ b/src/state/haptic-mixin.ts @@ -2,6 +2,24 @@ import { Constructor, LitElement, PropertyValues } from "lit-element"; import { HassBaseEl } from "./hass-base-mixin"; import { HapticType } from "../data/haptics"; +import { HomeAssistant } from "../types"; +import { HASSDomEvent } from "../common/dom/fire_event"; +import { storeState } from "../util/ha-pref-storage"; + +interface VibrateParams { + vibrate: HomeAssistant["vibrate"]; +} + +declare global { + // for fire event + interface HASSDomEvents { + "hass-vibrate": VibrateParams; + } + // for add event listener + interface HTMLElementEventMap { + "hass-vibrate": HASSDomEvent; + } +} const hapticPatterns = { success: [50, 50, 50], @@ -13,16 +31,30 @@ const hapticPatterns = { selection: [20], }; -const handleHaptic = (hapticType: HapticType) => { - navigator.vibrate(hapticPatterns[hapticType]); +const handleHaptic = (hapticTypeEvent: HASSDomEvent) => { + navigator.vibrate(hapticPatterns[hapticTypeEvent.detail]); }; export const hapticMixin = (superClass: Constructor) => class extends superClass { protected firstUpdated(changedProps: PropertyValues) { super.firstUpdated(changedProps); - if (navigator.vibrate) { - window.addEventListener("haptic", (e) => handleHaptic(e.detail)); + this.addEventListener("hass-vibrate", (ev) => { + const vibrate = ev.detail.vibrate; + if (navigator.vibrate && vibrate) { + window.addEventListener("haptic", handleHaptic); + } else { + window.removeEventListener("haptic", handleHaptic); + } + this._updateHass({ vibrate }); + storeState(this.hass!); + }); + } + + protected hassConnected() { + super.hassConnected(); + if (navigator.vibrate && this.hass!.vibrate) { + window.addEventListener("haptic", handleHaptic); } } }; diff --git a/src/translations/en.json b/src/translations/en.json index 5b801f9d2b..bc60381a98 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1214,6 +1214,10 @@ "header": "Always hide the sidebar", "description": "This will hide the sidebar by default, similar to the mobile experience." }, + "vibrate": { + "header": "Vibrate", + "description": "Enable or disable vibration on this device when controlling devices." + }, "push_notifications": { "header": "Push Notifications", "description": "Send notifications to this device.", diff --git a/src/types.ts b/src/types.ts index 81074f14b5..d67d460285 100644 --- a/src/types.ts +++ b/src/types.ts @@ -139,6 +139,7 @@ export interface HomeAssistant { localize: LocalizeFunc; translationMetadata: TranslationMetadata; + vibrate: boolean; dockedSidebar: "docked" | "always_hidden" | "auto"; moreInfoEntityId: string | null; user?: CurrentUser; diff --git a/src/util/ha-pref-storage.ts b/src/util/ha-pref-storage.ts index 6d9c681725..0b2ed29f0f 100644 --- a/src/util/ha-pref-storage.ts +++ b/src/util/ha-pref-storage.ts @@ -1,6 +1,11 @@ import { HomeAssistant } from "../types"; -const STORED_STATE = ["dockedSidebar", "selectedTheme", "selectedLanguage"]; +const STORED_STATE = [ + "dockedSidebar", + "selectedTheme", + "selectedLanguage", + "vibrate", +]; const STORAGE = window.localStorage || {}; export function storeState(hass: HomeAssistant) { @@ -27,7 +32,6 @@ export function getState() { state[key] = value; } } - return state; }