diff --git a/src/components/timeline-core.ts b/src/components/timeline-core.ts index 71acd690..c90cfeb6 100644 --- a/src/components/timeline-core.ts +++ b/src/components/timeline-core.ts @@ -400,7 +400,10 @@ export class FrigateCardTimelineCore extends LitElement { !this.view || !this.hass || !this.cameraManager || - !this.cameraManager + !this.cameraManager || + // Skip range changes that do not have hammerjs pan directions associated + // with them, as these outliers cause media matching issues below. + !properties.event.additionalEvent ) { return; } @@ -433,7 +436,7 @@ export class FrigateCardTimelineCore extends LitElement { }) // Whether or not to set the timeline window. .mergeInContext({ ...this._generateTimelineContext({ noSetWindow: true }), - ...(canSeek && { mediaViewer: { seek: targetTime }}) + ...(canSeek && { mediaViewer: { seek: targetTime } }), }) .dispatchChangeEvent(this); } @@ -521,9 +524,7 @@ export class FrigateCardTimelineCore extends LitElement { // Specifically ensure there are _some_ results before dispatching the // view change. if (eventView && results && results.length) { - eventView.mergeInContext( - {mediaViewer: {seek: properties.time}} - ); + eventView.mergeInContext({ mediaViewer: { seek: properties.time } }); view = eventView; } } else if ( @@ -662,6 +663,15 @@ export class FrigateCardTimelineCore extends LitElement { view.queryResults?.selectResultIfFound( (media) => !!this.cameras && media.getID() === options.selectedItem, ); + } else { + // If not asked to select a new item, persist the currently selected item + // if possible. + const currentlySelectedResult = this.view.queryResults?.getSelectedResult(); + if (currentlySelectedResult) { + view.queryResults?.selectResultIfFound( + (media) => media.getID() === currentlySelectedResult.getID(), + ); + } } return view; } diff --git a/src/utils/media-to-view.ts b/src/utils/media-to-view.ts index 137b54e4..22517e6d 100644 --- a/src/utils/media-to-view.ts +++ b/src/utils/media-to-view.ts @@ -200,16 +200,15 @@ export const findClosestMediaIndex = ( } | undefined; - for (let i = 0; i < mediaArray.length; ++i) { - const media = mediaArray[i]; - const start = media.getStartTime(); - const end = media.getEndTime(); - if (!cameraIDs.has(media.getCameraID()) || !start || !end) { + for (const [i, media] of mediaArray.entries()) { + if (!cameraIDs.has(media.getCameraID())) { continue; } - if (start <= targetTime && end >= targetTime) { - if (!refPoint) { + if (media.includesTime(targetTime)) { + const start = media.getStartTime(); + const end = media.getEndTime(); + if (!refPoint || !start || !end) { return i; } const delta = diff --git a/src/utils/timeline-source.ts b/src/utils/timeline-source.ts index fea859b3..9caf462c 100644 --- a/src/utils/timeline-source.ts +++ b/src/utils/timeline-source.ts @@ -3,7 +3,7 @@ import add from 'date-fns/add'; import sub from 'date-fns/sub'; import { DataSet } from 'vis-data'; import { IdType, TimelineItem, TimelineWindow } from 'vis-timeline/esnext'; -import { CameraConfig, ClipsOrSnapshotsOrAll, RecordingSegment } from '../types'; +import { ClipsOrSnapshotsOrAll, RecordingSegment } from '../types'; import { CameraManager } from '../camera/manager'; import { EventQuery } from '../camera/types'; import { capEndDate, convertRangeToCacheFriendlyTimes } from '../camera/util';