Do a fresh media query on snapshot->clip conversion.

This commit is contained in:
Dermot Duffy
2023-01-24 19:36:54 -08:00
parent eefe665f25
commit 191c901952
4 changed files with 30 additions and 42 deletions
+26 -40
View File
@@ -153,6 +153,7 @@ export class FrigateCardViewer extends LitElement {
this.view, this.view,
{ {
targetView: 'media', targetView: 'media',
mediaType: mediaType,
}, },
); );
} }
@@ -173,6 +174,7 @@ export class FrigateCardViewer extends LitElement {
.cameras=${this.cameras} .cameras=${this.cameras}
.viewerConfig=${this.viewerConfig} .viewerConfig=${this.viewerConfig}
.resolvedMediaCache=${this.resolvedMediaCache} .resolvedMediaCache=${this.resolvedMediaCache}
.cameraManager=${this.cameraManager}
.cardWideConfig=${this.cardWideConfig} .cardWideConfig=${this.cardWideConfig}
> >
</frigate-card-viewer-carousel> </frigate-card-viewer-carousel>
@@ -214,6 +216,9 @@ export class FrigateCardViewerCarousel extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public cameras?: Map<string, CameraConfig>; public cameras?: Map<string, CameraConfig>;
@property({ attribute: false })
public cameraManager?: CameraManager;
protected _refMediaCarousel: Ref<FrigateCardMediaCarousel> = createRef(); protected _refMediaCarousel: Ref<FrigateCardMediaCarousel> = createRef();
protected _carouselOptions?: EmblaOptionsType; protected _carouselOptions?: EmblaOptionsType;
@@ -359,17 +364,16 @@ export class FrigateCardViewerCarousel extends LitElement {
} }
/** /**
* Get a clip view that matches a given snapshot. Includes clips within the * Dispatch a clip view that matches the current (snapshot) query.
* same range as the current view. * @param index The index of the selected media.
* @param snapshot The snapshot to find a matching clip for.
* @returns The view that would show the matching clip.
*/ */
protected async _createRelatedClipView(targetIndex: number): Promise<View | null> { protected async _dispatchRelatedClipView(index: number): Promise<void> {
const media = this.view?.queryResults?.getResult(targetIndex); const media = this.view?.queryResults?.getResult(index);
if ( if (
!this.hass || !this.hass ||
!this.view || !this.view ||
!this.cameraManager ||
!media || !media ||
// If this specific media item has no clip, then do nothing (even if all // If this specific media item has no clip, then do nothing (even if all
// the other media items do). // the other media items do).
@@ -377,42 +381,28 @@ export class FrigateCardViewerCarousel extends LitElement {
!media.hasClip() || !media.hasClip() ||
!MediaQueriesClassifier.areEventQueries(this.view.query) !MediaQueriesClassifier.areEventQueries(this.view.query)
) { ) {
return null; return;
} }
const newResults: ViewMedia[] = [];
let newSelectedIndex: number | null = null;
// Convert the query to a clips equivalent. // Convert the query to a clips equivalent.
const newQuery = this.view.query.clone(); const clipQuery = this.view.query.clone();
newQuery.convertToClipsQueries(); clipQuery.convertToClipsQueries();
// Regenerate the whole results stack. const results = await this.cameraManager.executeMediaQuery(this.hass, clipQuery);
for (let i = 0; i < (this.view.queryResults?.getResultsCount() ?? 0); ++i) { if (!results) {
const media = this.view.queryResults?.getResult(i); return;
if (!media || !ViewMediaClassifier.isFrigateEvent(media)) {
continue;
}
const clipMedia = media.getClipEquivalent();
if (clipMedia) {
newResults.push(clipMedia);
if (i === targetIndex) {
newSelectedIndex = i;
}
}
}
if (newSelectedIndex === null) {
return null;
} }
const newQueryResults = new MediaQueriesResults(newResults); results.selectResultIfFound((clipMedia) => clipMedia.getID() === media.getID());
newQueryResults.selectResult(newSelectedIndex); if (!results.hasSelectedResult()) {
return;
}
return this.view.evolve({ this.view.evolve({
view: 'clip', view: 'media',
query: newQuery, query: clipQuery,
queryResults: newQueryResults, queryResults: results,
}); }).dispatchChangeEvent(this);
} }
/** /**
@@ -708,11 +698,7 @@ export class FrigateCardViewerCarousel extends LitElement {
?.carouselClickAllowed() && ?.carouselClickAllowed() &&
this.viewerConfig?.snapshot_click_plays_clip this.viewerConfig?.snapshot_click_plays_clip
) { ) {
this._createRelatedClipView(index).then((view) => { this._dispatchRelatedClipView(index);
if (view) {
view.dispatchChangeEvent(this);
}
});
} }
}} }}
@load="${(e: Event) => { @load="${(e: Event) => {
+2
View File
@@ -5,6 +5,8 @@ import format from 'date-fns/format';
import isEqual from 'lodash-es/isEqual'; import isEqual from 'lodash-es/isEqual';
import { FrigateCardError } from '../types'; import { FrigateCardError } from '../types';
export type ModifyInterface<T, R> = Omit<T, keyof R> & R;
/** /**
* Dispatch a Frigate Card event. * Dispatch a Frigate Card event.
* @param target The target from which send the event. * @param target The target from which send the event.
+1 -1
View File
@@ -10,7 +10,7 @@ import { capEndDate, convertRangeToCacheFriendlyTimes } from '../camera/util';
import { EventMediaQueries } from "../view/media-queries"; import { EventMediaQueries } from "../view/media-queries";
import { ViewMedia } from '../view/media'; import { ViewMedia } from '../view/media';
import { compressRanges, ExpiringMemoryRangeSet, MemoryRangeSet } from '../camera/range'; import { compressRanges, ExpiringMemoryRangeSet, MemoryRangeSet } from '../camera/range';
import { ModifyInterface } from './basic'; import { ModifyInterface } from './basic.js';
// Allow timeline freshness to be at least this number of seconds out of date // Allow timeline freshness to be at least this number of seconds out of date
// (caching times in the data-engine may increase the effective delay). // (caching times in the data-engine may increase the effective delay).
+1 -1
View File
@@ -2,11 +2,11 @@
// - TODO: Callers of all async methods of data-engine need to catch errors. // - TODO: Callers of all async methods of data-engine need to catch errors.
// - TODO: Add garbage collecting of segments not present in the recording summaries anymore. // - TODO: Add garbage collecting of segments not present in the recording summaries anymore.
// - TODO: Do I need to dedup recordings? (i.e. multiple zones on same camera may need to be dedup'd somewhere before returning the view). The media getID() call may be useful for this. // - TODO: Do I need to dedup recordings? (i.e. multiple zones on same camera may need to be dedup'd somewhere before returning the view). The media getID() call may be useful for this.
// - TODO: Do a fresh media query in the viewer on snapshot click, since the first query may (e.g.) only have requested events with snapshots (which would miss an event with just a clip).
// - TODO: Move frigate specific view-media under the camera manager. // - TODO: Move frigate specific view-media under the camera manager.
// - TODO: ts-prune https://camchenry.com/blog/deleting-dead-code-in-typescript // - TODO: ts-prune https://camchenry.com/blog/deleting-dead-code-in-typescript
// Hard: // Hard:
// - TODO: There are circumstances when lazy load doesn't work (e.g. snapshot -> clips re-query)
// - TODO: Implement dragging the timeline seeking forward in both Frigate recordings & events. // - TODO: Implement dragging the timeline seeking forward in both Frigate recordings & events.
// - TODO: Implement gallery. // - TODO: Implement gallery.
// - TODO: Remove FrigateBrowseMediaSource if not necessary (post-gallery). // - TODO: Remove FrigateBrowseMediaSource if not necessary (post-gallery).