Add a setting for vibration (#3813)

* Add a setting for vibration

* Update en.json
This commit is contained in:
Bram Kragten 2019-09-27 10:23:30 +02:00 committed by GitHub
parent 05a258c886
commit 2dd5cd586b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 116 additions and 8 deletions

View File

@ -178,6 +178,7 @@ export const provideHass = (
translationMetadata: translationMetadata as any, translationMetadata: translationMetadata as any,
dockedSidebar: "auto", dockedSidebar: "auto",
vibrate: true,
moreInfoEntityId: null as any, moreInfoEntityId: null as any,
async callService(domain, service, data) { async callService(domain, service, data) {
if (data && "entity_id" in data) { if (data && "entity_id" in data) {

View File

@ -15,7 +15,7 @@ import { fireEvent } from "../../common/dom/fire_event";
import { HaSwitch } from "../../components/ha-switch"; import { HaSwitch } from "../../components/ha-switch";
@customElement("ha-force-narrow-row") @customElement("ha-force-narrow-row")
class HaPushNotificationsRow extends LitElement { class HaForcedNarrowRow extends LitElement {
@property() public hass!: HomeAssistant; @property() public hass!: HomeAssistant;
@property() public narrow!: boolean; @property() public narrow!: boolean;
@ -49,6 +49,6 @@ class HaPushNotificationsRow extends LitElement {
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
"ha-force-narrow-row": HaPushNotificationsRow; "ha-force-narrow-row": HaForcedNarrowRow;
} }
} }

View File

@ -24,6 +24,7 @@ import "./ha-pick-language-row";
import "./ha-pick-theme-row"; import "./ha-pick-theme-row";
import "./ha-push-notifications-row"; import "./ha-push-notifications-row";
import "./ha-force-narrow-row"; import "./ha-force-narrow-row";
import "./ha-set-vibrate-row";
import { import {
LitElement, LitElement,
TemplateResult, TemplateResult,
@ -105,6 +106,14 @@ class HaPanelProfile extends LitElement {
></ha-force-narrow-row> ></ha-force-narrow-row>
` `
: ""} : ""}
${navigator.vibrate
? html`
<ha-set-vibrate-row
.narrow=${this.narrow}
.hass=${this.hass}
></ha-set-vibrate-row>
`
: ""}
<ha-push-notifications-row <ha-push-notifications-row
.narrow=${this.narrow} .narrow=${this.narrow}
.hass=${this.hass} .hass=${this.hass}

View File

@ -0,0 +1,56 @@
import {
LitElement,
TemplateResult,
html,
property,
customElement,
} from "lit-element";
import "./ha-settings-row";
import "../../components/ha-switch";
import { HomeAssistant } from "../../types";
import { fireEvent } from "../../common/dom/fire_event";
// tslint:disable-next-line: no-duplicate-imports
import { HaSwitch } from "../../components/ha-switch";
import { forwardHaptic } from "../../data/haptics";
@customElement("ha-set-vibrate-row")
class HaSetVibrateRow extends LitElement {
@property() public hass!: HomeAssistant;
@property() public narrow!: boolean;
protected render(): TemplateResult | void {
return html`
<ha-settings-row .narrow=${this.narrow}>
<span slot="heading">
${this.hass.localize("ui.panel.profile.vibrate.header")}
</span>
<span slot="description">
${this.hass.localize("ui.panel.profile.vibrate.description")}
</span>
<ha-switch
.checked=${this.hass.vibrate}
@change=${this._checkedChanged}
></ha-switch>
</ha-settings-row>
`;
}
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;
}
}

View File

@ -45,6 +45,7 @@ export const connectionMixin = (
translationMetadata, translationMetadata,
dockedSidebar: "docked", dockedSidebar: "docked",
vibrate: true,
moreInfoEntityId: null, moreInfoEntityId: null,
hassUrl: (path = "") => new URL(path, auth.data.hassUrl).toString(), hassUrl: (path = "") => new URL(path, auth.data.hassUrl).toString(),
callService: async (domain, service, serviceData = {}) => { callService: async (domain, service, serviceData = {}) => {

View File

@ -2,6 +2,24 @@ import { Constructor, LitElement, PropertyValues } from "lit-element";
import { HassBaseEl } from "./hass-base-mixin"; import { HassBaseEl } from "./hass-base-mixin";
import { HapticType } from "../data/haptics"; 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<VibrateParams>;
}
}
const hapticPatterns = { const hapticPatterns = {
success: [50, 50, 50], success: [50, 50, 50],
@ -13,16 +31,30 @@ const hapticPatterns = {
selection: [20], selection: [20],
}; };
const handleHaptic = (hapticType: HapticType) => { const handleHaptic = (hapticTypeEvent: HASSDomEvent<HapticType>) => {
navigator.vibrate(hapticPatterns[hapticType]); navigator.vibrate(hapticPatterns[hapticTypeEvent.detail]);
}; };
export const hapticMixin = (superClass: Constructor<LitElement & HassBaseEl>) => export const hapticMixin = (superClass: Constructor<LitElement & HassBaseEl>) =>
class extends superClass { class extends superClass {
protected firstUpdated(changedProps: PropertyValues) { protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps); super.firstUpdated(changedProps);
if (navigator.vibrate) { this.addEventListener("hass-vibrate", (ev) => {
window.addEventListener("haptic", (e) => handleHaptic(e.detail)); 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);
} }
} }
}; };

View File

@ -1214,6 +1214,10 @@
"header": "Always hide the sidebar", "header": "Always hide the sidebar",
"description": "This will hide the sidebar by default, similar to the mobile experience." "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": { "push_notifications": {
"header": "Push Notifications", "header": "Push Notifications",
"description": "Send notifications to this device.", "description": "Send notifications to this device.",

View File

@ -139,6 +139,7 @@ export interface HomeAssistant {
localize: LocalizeFunc; localize: LocalizeFunc;
translationMetadata: TranslationMetadata; translationMetadata: TranslationMetadata;
vibrate: boolean;
dockedSidebar: "docked" | "always_hidden" | "auto"; dockedSidebar: "docked" | "always_hidden" | "auto";
moreInfoEntityId: string | null; moreInfoEntityId: string | null;
user?: CurrentUser; user?: CurrentUser;

View File

@ -1,6 +1,11 @@
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
const STORED_STATE = ["dockedSidebar", "selectedTheme", "selectedLanguage"]; const STORED_STATE = [
"dockedSidebar",
"selectedTheme",
"selectedLanguage",
"vibrate",
];
const STORAGE = window.localStorage || {}; const STORAGE = window.localStorage || {};
export function storeState(hass: HomeAssistant) { export function storeState(hass: HomeAssistant) {
@ -27,7 +32,6 @@ export function getState() {
state[key] = value; state[key] = value;
} }
} }
return state; return state;
} }