Avoid dispatching range changed events if there's nothing to be gained.

This commit is contained in:
Dermot Duffy
2023-01-30 20:21:12 -08:00
parent 93e8a8e71b
commit f9f2a494c6
4 changed files with 47 additions and 7 deletions
+14 -5
View File
@@ -595,13 +595,22 @@ export class FrigateCardTimelineCore extends LitElement {
this.view &&
!MediaQueriesClassifier.areRecordingQueries(this.view.query)
) {
(
await this._createViewWithEventMediaQuery(
const newView = await this._createViewWithEventMediaQuery(
this._createEventMediaQuerys({ window: this._timeline.getWindow() }),
)
)
?.mergeInContext(this._setWindowInContext())
?.dispatchChangeEvent(this);
// Specifically avoid dispatching new results on range change unless there
// is something to be gained by doing so. Example usecase: On initial view
// load in mini timeline mode, the first 50 events are fetched -- the
// first drag of the timeline should not dispatch new results unless
// something is actually useful (as otherwise it creates a visible
// 'flicker' for the user as the viewer reloads all the media).
const newResults = newView?.queryResults;
if (newView && newResults && !this.view.queryResults?.isSupersetOf(newResults)) {
newView
?.mergeInContext(this._setWindowInContext())
?.dispatchChangeEvent(this);
}
}
}
+10 -1
View File
@@ -181,4 +181,13 @@ export const dayToDate = (day: string): Date => {
// Must provide the hour:minute:second on parsing or Javascript will assume
// *UTC* midnight.
return new Date(`${day}T00:00:00`);
}
};
export const isSuperset = (superset: Set<unknown>, subset: Set<unknown>) => {
for (const item of subset) {
if (!superset.has(item)) {
return false;
}
}
return true;
};
+23
View File
@@ -1,4 +1,5 @@
import clone from 'lodash-es/clone.js';
import { isSuperset } from '../utils/basic.js';
import { ViewMedia } from './media.js';
export class MediaQueriesResults {
@@ -21,6 +22,28 @@ export class MediaQueriesResults {
return clone(this);
}
public isSupersetOf(that: MediaQueriesResults): boolean {
if (!this._results || !that._results) {
return false;
}
const thisMediaIDs = new Set(this._results.map((media) => media.getID()));
const thatMediaIDs = new Set(that._results.map((media) => media.getID()));
if (
!thisMediaIDs ||
!thatMediaIDs ||
// If either media sets contain a null identifier (i.e. a media item with
// no ID) we must assume this is not a subset as multiple media items may
// reduce to the same null identifier above.
thisMediaIDs.has(null) ||
thatMediaIDs.has(null)
) {
return false;
}
return isSuperset(thisMediaIDs, thatMediaIDs);
}
public getResults(): ViewMedia[] | null {
return this._results;
}
-1
View File
@@ -1,7 +1,6 @@
// Minor / later:
// - TODO: ts-prune https://camchenry.com/blog/deleting-dead-code-in-typescript
// - TODO: Changing camera in live view, timeline stays the same.
// - TODO: Timeline initial load, then drag, appears to reset?
// Gallery:
// - TODO: Filter panel expands from right can occasionally 'stick' open.