Fixes for record button.
This commit is contained in:
+14
-12
@@ -22,9 +22,7 @@ import {
|
||||
fetchLatestMediaAndDispatchViewChange,
|
||||
getFullDependentBrowseMediaQueryParametersOrDispatchError,
|
||||
} from '../utils/ha/browse-media';
|
||||
import {
|
||||
changeViewToRecentRecording,
|
||||
} from '../utils/media-to-view.js';
|
||||
import { changeViewToRecentRecordingForCameraAndDependents } from '../utils/media-to-view.js';
|
||||
import { TimelineDataManager } from '../utils/timeline-data-manager';
|
||||
import { View } from '../view.js';
|
||||
import { renderProgressIndicator } from './message.js';
|
||||
@@ -67,7 +65,7 @@ export class FrigateCardGallery extends LitElement {
|
||||
|
||||
if (!this.view.target) {
|
||||
if (mediaType === 'recordings') {
|
||||
changeViewToRecentRecording(
|
||||
changeViewToRecentRecordingForCameraAndDependents(
|
||||
this,
|
||||
this.hass,
|
||||
this.dataManager,
|
||||
@@ -237,7 +235,6 @@ export class FrigateCardGalleryCore extends LitElement {
|
||||
return html``;
|
||||
}
|
||||
|
||||
const cameraConfig = this.cameras.get(this.view.camera);
|
||||
return html`
|
||||
${this._showBackArrow()
|
||||
? html` <ha-card
|
||||
@@ -279,7 +276,9 @@ export class FrigateCardGalleryCore extends LitElement {
|
||||
.target=${this.view?.target ?? null}
|
||||
.childIndex=${index}
|
||||
.hass=${this.hass}
|
||||
.clientID=${cameraConfig?.frigate.client_id}
|
||||
.cameraConfig=${child.frigate?.cameraID
|
||||
? this.cameras?.get(child.frigate.cameraID)
|
||||
: undefined}
|
||||
?details=${!!this.galleryConfig?.controls.thumbnails.show_details}
|
||||
?show_favorite_control=${!!this.galleryConfig?.controls.thumbnails
|
||||
.show_favorite_control}
|
||||
@@ -287,12 +286,15 @@ export class FrigateCardGalleryCore extends LitElement {
|
||||
.show_timeline_control}
|
||||
@click=${(ev: Event) => {
|
||||
if (this.view) {
|
||||
this.view
|
||||
.evolve({
|
||||
view: this.view.is('clips') ? 'clip' : 'snapshot',
|
||||
childIndex: index,
|
||||
})
|
||||
.dispatchChangeEvent(this);
|
||||
const targetView = this.view.getViewerViewForGalleryView();
|
||||
if (targetView) {
|
||||
this.view
|
||||
.evolve({
|
||||
view: targetView,
|
||||
childIndex: index,
|
||||
})
|
||||
.dispatchChangeEvent(this);
|
||||
}
|
||||
}
|
||||
stopEventFromActivatingCardWideActions(ev);
|
||||
}}
|
||||
|
||||
@@ -208,7 +208,7 @@ export class FrigateCardThumbnailCarousel extends LitElement {
|
||||
.target=${parent}
|
||||
.childIndex=${childIndex}
|
||||
.mediaSeek=${this.view?.context?.mediaViewer?.seek.get(childIndex)}
|
||||
.clientID=${cameraConfig?.frigate.client_id}
|
||||
.cameraConfig=${cameraConfig ?? undefined}
|
||||
?details=${this.config?.show_details}
|
||||
?show_favorite_control=${this.config?.show_favorite_control}
|
||||
?show_timeline_control=${this.config?.show_timeline_control}
|
||||
|
||||
@@ -10,6 +10,7 @@ import thumbnailFeatureRecordingStyle from '../scss/thumbnail-feature-recording.
|
||||
import thumbnailStyle from '../scss/thumbnail.scss';
|
||||
import { stopEventFromActivatingCardWideActions } from '../utils/action.js';
|
||||
import { errorToConsole, prettifyTitle } from '../utils/basic.js';
|
||||
import { getCameraTitle } from '../utils/camera.js';
|
||||
import { retainEvent } from '../utils/frigate.js';
|
||||
import { getEventDurationString } from '../utils/frigate.js';
|
||||
import { renderTask } from '../utils/task.js';
|
||||
@@ -19,6 +20,7 @@ import { MediaSeek } from './viewer.js';
|
||||
import { TaskStatus } from '@lit-labs/task';
|
||||
|
||||
import type {
|
||||
CameraConfig,
|
||||
ExtendedHomeAssistant,
|
||||
FrigateBrowseMediaSource,
|
||||
FrigateEvent,
|
||||
@@ -108,6 +110,9 @@ export class FrigateCardThumbnailFeatureRecording extends LitElement {
|
||||
@property({ attribute: false })
|
||||
public date?: Date;
|
||||
|
||||
@property({ attribute: false })
|
||||
public cameraTitle?: string;
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this.date) {
|
||||
return;
|
||||
@@ -115,6 +120,7 @@ export class FrigateCardThumbnailFeatureRecording extends LitElement {
|
||||
return html`
|
||||
<div class="title">${format(this.date, 'HH:mm')}</div>
|
||||
<div class="subtitle">${format(this.date, 'MMM do')}</div>
|
||||
${this.cameraTitle ? html`<div class="camera">${this.cameraTitle}</div>` : html``}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -240,7 +246,7 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
public hass?: ExtendedHomeAssistant;
|
||||
|
||||
@property({ attribute: false })
|
||||
public clientID?: string;
|
||||
public cameraConfig?: CameraConfig;
|
||||
|
||||
/**
|
||||
* Render the element.
|
||||
@@ -277,6 +283,7 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
starred: !!event?.retain_indefinitely,
|
||||
};
|
||||
|
||||
const clientID = this.cameraConfig?.frigate.client_id;
|
||||
return html` ${event
|
||||
? html`<frigate-card-thumbnail-feature-event
|
||||
aria-label="${label ?? ''}"
|
||||
@@ -285,22 +292,25 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
.thumbnail=${thumbnail ?? undefined}
|
||||
.label=${label ?? undefined}
|
||||
></frigate-card-thumbnail-feature-event>`
|
||||
: html`<frigate-card-thumbnail-feature-recording
|
||||
: recording
|
||||
? html`<frigate-card-thumbnail-feature-recording
|
||||
aria-label="${label ?? ''}"
|
||||
title="${label ?? ''}"
|
||||
.cameraTitle=${this.details || !this.cameraConfig || !this.hass ? undefined : getCameraTitle(this.hass, this.cameraConfig)}
|
||||
.date=${recording ? fromUnixTime(recording.start_time) : undefined}
|
||||
></frigate-card-thumbnail-feature-recording>`}
|
||||
${this.show_favorite_control && event && this.hass && this.clientID
|
||||
></frigate-card-thumbnail-feature-recording>`
|
||||
: html``}
|
||||
${this.show_favorite_control && event && this.hass && clientID
|
||||
? html` <ha-icon
|
||||
class="${classMap(starClasses)}"
|
||||
icon=${event?.retain_indefinitely ? 'mdi:star' : 'mdi:star-outline'}
|
||||
title=${localize('thumbnail.retain_indefinitely')}
|
||||
@click=${(ev: Event) => {
|
||||
stopEventFromActivatingCardWideActions(ev);
|
||||
if (event && this.hass && this.clientID) {
|
||||
if (event && this.hass && clientID) {
|
||||
retainEvent(
|
||||
this.hass,
|
||||
this.clientID,
|
||||
clientID,
|
||||
event.id,
|
||||
!event.retain_indefinitely,
|
||||
)
|
||||
|
||||
@@ -1024,6 +1024,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
||||
}
|
||||
|
||||
const options = this._getOptions();
|
||||
let createdTimeline = false;
|
||||
|
||||
if (
|
||||
this.timelineDataManager &&
|
||||
@@ -1056,6 +1057,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
||||
this.timelineConfig.media,
|
||||
);
|
||||
|
||||
createdTimeline = true;
|
||||
if (this.mini && groups.length === 1) {
|
||||
// In a mini timeline, if there's only one group don't bother grouping
|
||||
// at all.
|
||||
@@ -1097,7 +1099,15 @@ export class FrigateCardTimelineCore extends LitElement {
|
||||
}
|
||||
|
||||
if (changedProperties.has('view')) {
|
||||
this._updateTimelineFromView();
|
||||
if (createdTimeline) {
|
||||
// If the timeline was just created, give it one frame to draw itself.
|
||||
// Failure to do so may result in subsequent calls to
|
||||
// `this._timeline.setwindow()` being entirely ignored. Example case:
|
||||
// Clicking the timeline control on a recording thumbnail.
|
||||
window.requestAnimationFrame(this._updateTimelineFromView.bind(this));
|
||||
} else {
|
||||
this._updateTimelineFromView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ import { EmblaCarouselPlugins } from './carousel.js';
|
||||
import { renderTask } from '../utils/task.js';
|
||||
import { updateElementStyleFromMediaLayoutConfig } from '../utils/media-layout.js';
|
||||
import { TimelineDataManager } from '../utils/timeline-data-manager.js';
|
||||
import { changeViewToRecentRecording } from '../utils/media-to-view.js';
|
||||
import { changeViewToRecentRecordingForCameraAndDependents } from '../utils/media-to-view.js';
|
||||
|
||||
export interface MediaSeek {
|
||||
// Specifies the point at which this recording should be played, the
|
||||
@@ -131,7 +131,7 @@ export class FrigateCardViewer extends LitElement {
|
||||
}
|
||||
|
||||
if (mediaType === 'recordings') {
|
||||
changeViewToRecentRecording(
|
||||
changeViewToRecentRecordingForCameraAndDependents(
|
||||
this,
|
||||
this.hass,
|
||||
this.timelineDataManager,
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
div {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
div.camera {
|
||||
font-size: 0.7em;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
sortSegmentsOldestToYoungest,
|
||||
TimelineDataManager,
|
||||
} from './timeline-data-manager';
|
||||
import { getAllDependentCameras } from './camera.js';
|
||||
|
||||
/**
|
||||
* Change the view to a recent recording.
|
||||
@@ -20,17 +21,15 @@ import {
|
||||
* @param dataManager The datamanager to use for data access.
|
||||
* @param cameras The camera configurations.
|
||||
* @param view The current view.
|
||||
* @param cameraIDs The camera IDs to include recordings for.
|
||||
* @param options A specific window (start and end) to fetch recordings for, and a targetTime to seek to.
|
||||
* @param options A set of cameraIDs to fetch recordings for, and a targetView to dispatch to.
|
||||
*/
|
||||
export const changeViewToRecentRecording = async (
|
||||
export const changeViewToRecentRecordingForCameraAndDependents = async (
|
||||
element: HTMLElement,
|
||||
hass: ExtendedHomeAssistant,
|
||||
dataManager: TimelineDataManager,
|
||||
cameras: Map<string, CameraConfig>,
|
||||
view: View,
|
||||
options?: {
|
||||
cameraIDs?: Set<string>;
|
||||
targetView?: 'recording' | 'recordings';
|
||||
},
|
||||
): Promise<void> => {
|
||||
@@ -46,6 +45,7 @@ import {
|
||||
...options,
|
||||
|
||||
// Fetch 1 days worth of recordings (including recordings that are for the current hour).
|
||||
cameraIDs: getAllDependentCameras(cameras, view.camera),
|
||||
start: sub(now, { days: 1 }),
|
||||
end: add(now, { hours: 1 }),
|
||||
}
|
||||
@@ -59,8 +59,9 @@ import {
|
||||
* @param dataManager The datamanager to use for data access.
|
||||
* @param cameras The camera configurations.
|
||||
* @param view The current view.
|
||||
* @param cameraIDs The camera IDs to include recordings for.
|
||||
* @param options A specific window (start and end) to fetch recordings for, and a targetTime to seek to.
|
||||
* @param options A specific window (start and end) to fetch recordings for, a
|
||||
* targetTime to seek to, a targetView to dispatch to and a set of cameraIDs to
|
||||
* restrict to.
|
||||
*/
|
||||
export const changeViewToRecording = async (
|
||||
element: HTMLElement,
|
||||
|
||||
+14
@@ -150,6 +150,20 @@ export class View {
|
||||
return ['clips', 'snapshots', 'recordings'].includes(this.view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the viewer view given a gallery view.
|
||||
*/
|
||||
public getViewerViewForGalleryView(): 'clip' | 'snapshot' | 'recording' | null {
|
||||
if (this.is('clips')) {
|
||||
return 'clip';
|
||||
} else if (this.is('snapshots')) {
|
||||
return 'snapshot';
|
||||
} else if (this.is('recordings')) {
|
||||
return 'recording';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a view is of a piece of media (including the media viewer,
|
||||
* live view, image view -- anything that can create a MediaLoadedInfo event).
|
||||
|
||||
Reference in New Issue
Block a user