From 69b34d7ea1385e1ad4c5a7d755f31eb98d1be186 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sat, 15 Apr 2023 12:19:23 -0700 Subject: [PATCH] Fix clicking on timeline recordings. --- src/card.ts | 2 +- src/components/timeline-core.ts | 15 +++++--- src/view/view.ts | 68 +++++++++++++++++++++------------ 3 files changed, 55 insertions(+), 30 deletions(-) diff --git a/src/card.ts b/src/card.ts index d8e4e049..1b7ace09 100644 --- a/src/card.ts +++ b/src/card.ts @@ -857,7 +857,7 @@ class FrigateCard extends LitElement { this._resetMainScroll(); } - View.adoptQueryIfAppropriate(view, this._view); + View.adoptFromViewIfAppropriate(view, this._view); this._view = view; this._generateConditionState(); diff --git a/src/components/timeline-core.ts b/src/components/timeline-core.ts index 475ec1c9..18eff32e 100644 --- a/src/components/timeline-core.ts +++ b/src/components/timeline-core.ts @@ -545,11 +545,16 @@ export class FrigateCardTimelineCore extends LitElement { this.timelineConfig?.show_recordings && ['background', 'group-label'].includes(properties.what) ) { - const query = createQueriesForRecordingsView( - this.cameraManager, - this.cardWideConfig, - new Set([String(properties.group)]), - ); + const cameraIDs = properties.group + ? new Set([String(properties.group)]) + : this._getTimelineCameraIDs(); + const query = cameraIDs + ? createQueriesForRecordingsView( + this.cameraManager, + this.cardWideConfig, + cameraIDs, + ) + : null; if (query) { view = await executeMediaQueryForView( this, diff --git a/src/view/view.ts b/src/view/view.ts index c31a0640..6f54bb7b 100644 --- a/src/view/view.ts +++ b/src/view/view.ts @@ -61,40 +61,60 @@ export class View { ); } - public static adoptQueryIfAppropriate(next: View, curr?: View): void { - // Special case: If the user is currently using the viewer, and then - // switches to the gallery we make an attempt to keep the query/queryResults - // the same so the gallery can be used to click back and forth to the - // viewer, and the selected media can be centered in the gallery. See the - // matching code in `updated()` in `gallery.ts`. We specifically must ensure - // that the new target media of the gallery (e.g. clips, snapshots or - // recordings) is equal to the queries that are currently used in the - // viewer. - // See: https://github.com/dermotduffy/frigate-hass-card/issues/885 + public static adoptFromViewIfAppropriate(next: View, curr?: View): void { + if (!curr) { + return; + } + + // In certain cases it may make sense to adopt parameters from a prior view. + // + // * Case #1: If the user is currently using the viewer, and then switches + // to the gallery we make an attempt to keep the query/queryResults the + // same so the gallery can be used to click back and forth to the viewer, + // and the selected media can be centered in the gallery. See the matching + // code in `updated()` in `gallery.ts`. We specifically must ensure that + // the new target media of the gallery (e.g. clips, snapshots or + // recordings) is equal to the queries that are currently used in the + // viewer. See: + // https://github.com/dermotduffy/frigate-hass-card/issues/885 + // + // * Case #2: If the user is looking at media in the `media` view and then + // changes camera to the *current* camera (via the menu) it will cause a + // new view to issue without a query and just the 'media' view, which + // means the viewer cannot know what kind of media to fetch. let currentQueriesView: ClipsOrSnapshots | 'recordings' | null = null; - if (MediaQueriesClassifier.areEventQueries(curr?.query)) { - const queries = curr?.query.getQueries(); + if (MediaQueriesClassifier.areEventQueries(curr.query)) { + const queries = curr.query.getQueries(); if (queries?.every((query) => query.hasClip)) { currentQueriesView = 'clips'; } else if (queries?.every((query) => query.hasSnapshot)) { currentQueriesView = 'snapshots'; } - } else if (MediaQueriesClassifier.areRecordingQueries(curr?.query)) { + } else if (MediaQueriesClassifier.areRecordingQueries(curr.query)) { currentQueriesView = 'recordings'; } - if ( - curr?.isViewerView() && - next.isGalleryView() && - (!next.query || !next.queryResults) && - next.view === currentQueriesView - ) { - if (curr.query) { - next.query = curr.query; - } - if (curr.queryResults) { - next.queryResults = curr.queryResults; + const hasNoQueryOrResults = !next.query || !next.queryResults; + const switchingToGalleryFromViewer = + curr.isViewerView() && next.isGalleryView() && next.view === currentQueriesView; + const switchingToMediaFromMedia = curr?.is('media') && next.is('media'); + + if (hasNoQueryOrResults) { + if (switchingToGalleryFromViewer) { + if (curr.query) { + next.query = curr.query; + } + if (curr.queryResults) { + next.queryResults = curr.queryResults; + } + } else if (switchingToMediaFromMedia && currentQueriesView) { + next.view = + currentQueriesView === 'clips' + ? 'clip' + : currentQueriesView === 'snapshots' + ? 'snapshot' + : 'recording'; } } }