Limit re-rendering to improve user experience.
This commit is contained in:
@@ -35,7 +35,6 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
import type {
|
import type {
|
||||||
BrowseMediaSource,
|
BrowseMediaSource,
|
||||||
ControlVideosParameters,
|
|
||||||
FrigateCardView,
|
FrigateCardView,
|
||||||
FrigateCardConfig,
|
FrigateCardConfig,
|
||||||
FrigateMenuMode,
|
FrigateMenuMode,
|
||||||
@@ -340,9 +339,13 @@ export class FrigateCard extends LitElement {
|
|||||||
|
|
||||||
const oldHass = changedProps.get('_hass') as HomeAssistant | undefined;
|
const oldHass = changedProps.get('_hass') as HomeAssistant | undefined;
|
||||||
if (oldHass) {
|
if (oldHass) {
|
||||||
// A re-render will interrupt a clip that is playing. Do not allow this
|
// Home Assistant pumps a lot of updates through. Re-rendering the card is
|
||||||
// for hass state updates.
|
// necessary at times (e.g. to update the 'clip' view as new clips
|
||||||
if (this._clipPlaying) {
|
// arrive), but also is a jarring experience for the user (e.g. if they
|
||||||
|
// are browsing the mini-gallery). Do not allow re-rendering from a Home
|
||||||
|
// Assistant update if there's been recent interaction (e.g. clicks on the
|
||||||
|
// card) or if there is a clip active playing.
|
||||||
|
if (this._interactionTimerID || this._clipPlaying) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return shouldUpdateBasedOnHass(this._hass, oldHass, [
|
return shouldUpdateBasedOnHass(this._hass, oldHass, [
|
||||||
@@ -513,85 +516,20 @@ export class FrigateCard extends LitElement {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop/Play video controls.
|
|
||||||
protected _controlVideos({
|
|
||||||
stop,
|
|
||||||
control_live = false,
|
|
||||||
control_clip = false,
|
|
||||||
}: ControlVideosParameters): void {
|
|
||||||
const controlVideo = (stop: boolean, is_live: boolean, video: HTMLVideoElement) => {
|
|
||||||
if (video) {
|
|
||||||
if (stop) {
|
|
||||||
video.pause();
|
|
||||||
video.currentTime = 0;
|
|
||||||
} else if (is_live) {
|
|
||||||
// Duration on webrtc is infinity so cannot fast-forward.
|
|
||||||
if (!this._webrtcElement) {
|
|
||||||
// If it's a live view, 'fast-forward' to most recent content.
|
|
||||||
const duration = video.duration;
|
|
||||||
video.currentTime = duration;
|
|
||||||
}
|
|
||||||
video.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!this.shadowRoot) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (control_clip) {
|
|
||||||
controlVideo(
|
|
||||||
stop,
|
|
||||||
false,
|
|
||||||
this.shadowRoot?.querySelector('video.frigate-card-viewer') as HTMLVideoElement,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (control_live) {
|
|
||||||
// Don't have direct access to the live video player as it is buried in
|
|
||||||
// multiple components/shadow-roots, so need to navigate the path to get to <video>.
|
|
||||||
if (this._webrtcElement) {
|
|
||||||
controlVideo(
|
|
||||||
stop,
|
|
||||||
true,
|
|
||||||
this.shadowRoot?.querySelector('webrtc-camera video') as HTMLVideoElement,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
controlVideo(
|
|
||||||
stop,
|
|
||||||
true,
|
|
||||||
this.shadowRoot
|
|
||||||
?.querySelector('ha-camera-stream')
|
|
||||||
?.shadowRoot?.querySelector('ha-hls-player')
|
|
||||||
?.shadowRoot?.querySelector('video') as HTMLVideoElement,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected _menuActionHandler(name: string): void {
|
protected _menuActionHandler(name: string): void {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'frigate':
|
case 'frigate':
|
||||||
this._controlVideos({ stop: true, control_clip: true });
|
|
||||||
this._controlVideos({ stop: true, control_live: true });
|
|
||||||
this._changeView();
|
this._changeView();
|
||||||
break;
|
break;
|
||||||
case 'live':
|
case 'live':
|
||||||
this._controlVideos({ stop: true, control_clip: true });
|
|
||||||
this._controlVideos({ stop: false, control_live: true });
|
|
||||||
this._changeView(name);
|
|
||||||
break;
|
|
||||||
case 'clips':
|
case 'clips':
|
||||||
this._controlVideos({ stop: true, control_live: true });
|
|
||||||
this._changeView(name);
|
|
||||||
break;
|
|
||||||
case 'snapshots':
|
case 'snapshots':
|
||||||
this._controlVideos({ stop: true, control_clip: true, control_live: true });
|
|
||||||
this._changeView(name);
|
this._changeView(name);
|
||||||
break;
|
break;
|
||||||
case 'frigate_ui':
|
case 'frigate_ui':
|
||||||
const frigate_url = this._getFrigateURLFromContext();
|
const frigate_url = this._getFrigateURLFromContext();
|
||||||
if (frigate_url) {
|
if (frigate_url) {
|
||||||
window.open(frigate_url);
|
window.open(frigate_url);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'motion':
|
case 'motion':
|
||||||
|
|||||||
+1
-8
@@ -41,7 +41,6 @@ export const frigateCardConfigSchema = z.object({
|
|||||||
frigate_client_id: z.string().optional().default("frigate"),
|
frigate_client_id: z.string().optional().default("frigate"),
|
||||||
frigate_camera_name: z.string().optional(),
|
frigate_camera_name: z.string().optional(),
|
||||||
view_default: z.enum(FRIGATE_CARD_VIEWS).optional().default('live'),
|
view_default: z.enum(FRIGATE_CARD_VIEWS).optional().default('live'),
|
||||||
|
|
||||||
view_timeout: z
|
view_timeout: z
|
||||||
.number()
|
.number()
|
||||||
.or(
|
.or(
|
||||||
@@ -50,7 +49,7 @@ export const frigateCardConfigSchema = z.object({
|
|||||||
.regex(/^\d+$/)
|
.regex(/^\d+$/)
|
||||||
.transform((val) => Number(val)),
|
.transform((val) => Number(val)),
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional().default(180),
|
||||||
live_provider: z.enum(['frigate', 'webrtc']).default('frigate'),
|
live_provider: z.enum(['frigate', 'webrtc']).default('frigate'),
|
||||||
webrtc: z.object({}).passthrough().optional(),
|
webrtc: z.object({}).passthrough().optional(),
|
||||||
label: z.string().optional(),
|
label: z.string().optional(),
|
||||||
@@ -66,12 +65,6 @@ export const frigateCardConfigSchema = z.object({
|
|||||||
});
|
});
|
||||||
export type FrigateCardConfig = z.infer<typeof frigateCardConfigSchema>;
|
export type FrigateCardConfig = z.infer<typeof frigateCardConfigSchema>;
|
||||||
|
|
||||||
export interface ControlVideosParameters {
|
|
||||||
stop: boolean;
|
|
||||||
control_live?: boolean;
|
|
||||||
control_clip?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MediaBeingShown {
|
export interface MediaBeingShown {
|
||||||
browseMedia: BrowseMediaSource;
|
browseMedia: BrowseMediaSource;
|
||||||
resolvedMedia: ResolvedMedia;
|
resolvedMedia: ResolvedMedia;
|
||||||
|
|||||||
Reference in New Issue
Block a user