mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-26 22:37:21 +00:00
Add a setting for vibration (#3813)
* Add a setting for vibration * Update en.json
This commit is contained in:
parent
05a258c886
commit
2dd5cd586b
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}
|
||||||
|
56
src/panels/profile/ha-set-vibrate-row.ts
Normal file
56
src/panels/profile/ha-set-vibrate-row.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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 = {}) => {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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.",
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user