Move preload_stream setting to entity settings (#12730)

Co-authored-by: Zack <zackbarett@hey.com>
This commit is contained in:
Bram Kragten 2022-05-23 20:30:57 +02:00 committed by GitHub
parent 1d5cc91a2d
commit 7db6e0b779
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 95 deletions

View File

@ -1,35 +1,14 @@
import {
css,
CSSResultGroup,
html,
LitElement,
PropertyValues,
TemplateResult,
} from "lit";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { property, state } from "lit/decorators";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-camera-stream";
import type { HaCheckbox } from "../../../components/ha-checkbox";
import "../../../components/ha-checkbox";
import {
CameraEntity,
CameraPreferences,
CAMERA_SUPPORT_STREAM,
fetchCameraPrefs,
STREAM_TYPE_HLS,
updateCameraPrefs,
} from "../../../data/camera";
import { CameraEntity } from "../../../data/camera";
import type { HomeAssistant } from "../../../types";
import "../../../components/ha-formfield";
class MoreInfoCamera extends LitElement {
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: CameraEntity;
@state() private _cameraPrefs?: CameraPreferences;
@state() private _attached = false;
public connectedCallback() {
@ -54,83 +33,13 @@ class MoreInfoCamera extends LitElement {
allow-exoplayer
controls
></ha-camera-stream>
${this._cameraPrefs
? html`
<ha-formfield label="Preload stream">
<ha-checkbox
.checked=${this._cameraPrefs.preload_stream}
@change=${this._handleCheckboxChanged}
>
</ha-checkbox>
</ha-formfield>
`
: undefined}
`;
}
protected updated(changedProps: PropertyValues) {
if (!changedProps.has("stateObj")) {
return;
}
const oldState = changedProps.get("stateObj") as this["stateObj"];
const oldEntityId = oldState ? oldState.entity_id : undefined;
const curEntityId = this.stateObj ? this.stateObj.entity_id : undefined;
// Same entity, ignore.
if (curEntityId === oldEntityId) {
return;
}
if (
curEntityId &&
isComponentLoaded(this.hass!, "stream") &&
supportsFeature(this.stateObj!, CAMERA_SUPPORT_STREAM) &&
// The stream component for HLS streams supports a server-side pre-load
// option that client initiated WebRTC streams do not
this.stateObj!.attributes.frontend_stream_type === STREAM_TYPE_HLS
) {
// Fetch in background while we set up the video.
this._fetchCameraPrefs();
}
}
private async _fetchCameraPrefs() {
this._cameraPrefs = await fetchCameraPrefs(
this.hass!,
this.stateObj!.entity_id
);
}
private async _handleCheckboxChanged(ev) {
const checkbox = ev.currentTarget as HaCheckbox;
try {
this._cameraPrefs = await updateCameraPrefs(
this.hass!,
this.stateObj!.entity_id,
{
preload_stream: checkbox.checked!,
}
);
} catch (err: any) {
alert(err.message);
checkbox.checked = !checkbox.checked;
}
}
static get styles(): CSSResultGroup {
return css`
:host {
display: block;
position: relative;
}
ha-formfield {
position: absolute;
top: 0;
right: 0;
background-color: var(--secondary-background-color);
padding-right: 16px;
border-bottom-left-radius: 4px;
}
`;
}

View File

@ -12,10 +12,12 @@ import {
} from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { fireEvent } from "../../../common/dom/fire_event";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { computeDomain } from "../../../common/entity/compute_domain";
import { domainIcon } from "../../../common/entity/domain_icon";
import { supportsFeature } from "../../../common/entity/supports-feature";
import { stringCompare } from "../../../common/string/compare";
import { LocalizeFunc } from "../../../common/translations/localize";
import "../../../components/ha-alert";
@ -24,8 +26,17 @@ import "../../../components/ha-expansion-panel";
import "../../../components/ha-icon-picker";
import "../../../components/ha-radio";
import "../../../components/ha-select";
import "../../../components/ha-settings-row";
import "../../../components/ha-switch";
import type { HaSwitch } from "../../../components/ha-switch";
import "../../../components/ha-textfield";
import {
CameraPreferences,
CAMERA_SUPPORT_STREAM,
fetchCameraPrefs,
STREAM_TYPE_HLS,
updateCameraPrefs,
} from "../../../data/camera";
import {
ConfigEntry,
deleteConfigEntry,
@ -133,6 +144,8 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
@state() private _submitting?: boolean;
@state() private _cameraPrefs?: CameraPreferences;
private _origEntityId!: string;
private _deviceLookup?: Record<string, DeviceRegistryEntry>;
@ -190,6 +203,20 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
const domain = computeDomain(this.entry.entity_id);
if (domain === "camera" && isComponentLoaded(this.hass, "stream")) {
const stateObj: HassEntity | undefined =
this.hass.states[this.entry.entity_id];
if (
stateObj &&
supportsFeature(stateObj, CAMERA_SUPPORT_STREAM) &&
// The stream component for HLS streams supports a server-side pre-load
// option that client initiated WebRTC streams do not
stateObj.attributes.frontend_stream_type === STREAM_TYPE_HLS
) {
this._fetchCameraPrefs();
}
}
if (domain === "sensor") {
const stateObj: HassEntity | undefined =
this.hass.states[this.entry.entity_id];
@ -392,7 +419,27 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
@value-changed=${this._areaPicked}
></ha-area-picker>`
: ""}
${this._cameraPrefs
? html`
<ha-settings-row>
<span slot="heading"
>${this.hass.localize(
"ui.dialogs.entity_registry.editor.preload_stream"
)}</span
>
<span slot="description"
>${this.hass.localize(
"ui.dialogs.entity_registry.editor.preload_stream_description"
)}</span
>
<ha-switch
.checked=${this._cameraPrefs.preload_stream}
@change=${this._handleCameraPrefsChanged}
>
</ha-switch>
</ha-settings-row>
`
: ""}
<ha-expansion-panel
.header=${this.hass.localize(
"ui.dialogs.entity_registry.editor.advanced"
@ -578,6 +625,26 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
this._areaId = ev.detail.value;
}
private async _fetchCameraPrefs() {
this._cameraPrefs = await fetchCameraPrefs(this.hass, this.entry.entity_id);
}
private async _handleCameraPrefsChanged(ev) {
const checkbox = ev.currentTarget as HaSwitch;
try {
this._cameraPrefs = await updateCameraPrefs(
this.hass,
this.entry.entity_id,
{
preload_stream: checkbox.checked!,
}
);
} catch (err: any) {
showAlertDialog(this, { text: err.message });
checkbox.checked = !checkbox.checked;
}
}
private _viewStatusChanged(ev: CustomEvent): void {
switch ((ev.target as any).value) {
case "enabled":
@ -794,6 +861,12 @@ export class EntityRegistrySettings extends SubscribeMixin(LitElement) {
ha-switch {
margin-right: 16px;
}
ha-settings-row {
padding: 0;
}
ha-settings-row ha-switch {
margin-right: 0;
}
ha-textfield {
display: block;
margin: 8px 0;

View File

@ -876,7 +876,9 @@
"area_note": "By default the entities of a device are in the same area as the device. If you change the area of this entity, it will no longer follow the area of the device.",
"follow_device_area": "Follow device area",
"change_device_area": "Change device area",
"configure_state": "{integration} options"
"configure_state": "{integration} options",
"preload_stream": "Preload camera stream",
"preload_stream_description": "This keeps the camera stream open in the background so it shows quicker. Warning! This is device intensive."
}
},
"helper_settings": {