Performance: Store the last fetch time in the view context.
This commit is contained in:
+67
-24
@@ -1,4 +1,3 @@
|
|||||||
// TODO: Save memory usage by saving thumbnails once.
|
|
||||||
// TODO: Search for TODOs and logging statements.
|
// TODO: Search for TODOs and logging statements.
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -62,7 +61,11 @@ interface FrigateCardTimelineItem extends TimelineItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface TimelineViewContext extends ViewContext {
|
interface TimelineViewContext extends ViewContext {
|
||||||
window: TimelineWindow;
|
// The selected timeline window.
|
||||||
|
window?: TimelineWindow;
|
||||||
|
|
||||||
|
// The date of the last event fetch.
|
||||||
|
dateFetch?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
type TimelineMediaType = 'all' | 'clips' | 'snapshots';
|
type TimelineMediaType = 'all' | 'clips' | 'snapshots';
|
||||||
@@ -99,6 +102,11 @@ class TimelineEventManager {
|
|||||||
this._tooltipCallback = params?.tooltipCallback;
|
this._tooltipCallback = params?.tooltipCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the last event fetch date.
|
||||||
|
get lastFetchDate(): Date | null {
|
||||||
|
return this._dateFetch ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the underlying dataset.
|
* Retrieve the underlying dataset.
|
||||||
*/
|
*/
|
||||||
@@ -478,20 +486,21 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
properties.end,
|
properties.end,
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this._generateThumbnails();
|
if (this._timeline) {
|
||||||
});
|
const thumbnails = this._generateThumbnails();
|
||||||
|
// Update the view to reflect the new thumbnails and manually set
|
||||||
// Update the view to ensure that future view changes do not cause a
|
// timeline window.
|
||||||
// scroll.
|
|
||||||
console.info('=========> Evolve view from Range');
|
console.info('=========> Evolve view from Range');
|
||||||
this.view
|
this.view
|
||||||
?.evolve({
|
?.evolve({
|
||||||
context: {
|
target: thumbnails?.target ?? null,
|
||||||
window: this._timeline.getWindow(),
|
childIndex: thumbnails?.childIndex ?? null,
|
||||||
},
|
context: this._generateViewContext(true),
|
||||||
})
|
})
|
||||||
.dispatchChangeEvent(this);
|
.dispatchChangeEvent(this);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -526,11 +535,16 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Regenerate the thumbnails from the timeline events.
|
* Regenerate the thumbnails from the timeline events.
|
||||||
* @returns
|
* @returns An object with two keys, or null on error. The keys are `target`
|
||||||
|
* containing all the thumbnails, and `childIndex` to refer to the currently
|
||||||
|
* selected thumbnail.
|
||||||
*/
|
*/
|
||||||
protected _generateThumbnails(): void {
|
protected _generateThumbnails(): {
|
||||||
|
target: FrigateBrowseMediaSource;
|
||||||
|
childIndex: number | null;
|
||||||
|
} | null {
|
||||||
if (!this._timeline) {
|
if (!this._timeline) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -564,7 +578,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!children.length) {
|
if (!children.length) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const target = {
|
const target = {
|
||||||
@@ -579,16 +593,10 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
children: children,
|
children: children,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isEqual(target, this.view?.target)) {
|
return {
|
||||||
// Update the thumbnail carousel with the regenerated thumbnails.
|
|
||||||
console.info('=========> Evolve view from thumbnails');
|
|
||||||
this.view
|
|
||||||
?.evolve({
|
|
||||||
target: target,
|
target: target,
|
||||||
childIndex: childIndex < 0 ? null : childIndex,
|
childIndex: childIndex < 0 ? null : childIndex,
|
||||||
})
|
};
|
||||||
.dispatchChangeEvent(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -794,8 +802,6 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
|
|
||||||
// Regenerate the thumbnails after the selection, to allow the new selection
|
// Regenerate the thumbnails after the selection, to allow the new selection
|
||||||
// to be in the generated view.
|
// to be in the generated view.
|
||||||
this._generateThumbnails();
|
|
||||||
|
|
||||||
const context = this.view.context as TimelineViewContext | null;
|
const context = this.view.context as TimelineViewContext | null;
|
||||||
const timelineWindow = this._timeline.getWindow();
|
const timelineWindow = this._timeline.getWindow();
|
||||||
|
|
||||||
@@ -832,6 +838,43 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
console.info(`Setting window from live ${windowStart} -> ${windowEnd}`);
|
console.info(`Setting window from live ${windowStart} -> ${windowEnd}`);
|
||||||
this._timeline.setWindow(windowStart, windowEnd);
|
this._timeline.setWindow(windowStart, windowEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare last date of fetch with that of inbound view to avoid a loop.
|
||||||
|
// Without this comparison it would be:
|
||||||
|
//
|
||||||
|
// Timeline receives a new `view`
|
||||||
|
// -> Events fetched
|
||||||
|
// -> Thumbnails generated
|
||||||
|
// -> New view dispatched (to load thumbnails into outer carousel).
|
||||||
|
// -> New view received ... [loop]
|
||||||
|
const currentContext = this.view.context as TimelineViewContext | null;
|
||||||
|
if (currentContext?.dateFetch !== this._events.lastFetchDate) {
|
||||||
|
const thumbnails = this._generateThumbnails();
|
||||||
|
console.info('=========> Evolve view from thumbnails');
|
||||||
|
|
||||||
|
this.view
|
||||||
|
?.evolve({
|
||||||
|
target: thumbnails?.target ?? null,
|
||||||
|
childIndex: thumbnails?.childIndex ?? null,
|
||||||
|
context: this._generateViewContext(false),
|
||||||
|
})
|
||||||
|
.dispatchChangeEvent(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _generateViewContext(addWindow: boolean): TimelineViewContext {
|
||||||
|
const currentContext = this.view?.context as TimelineViewContext | undefined;
|
||||||
|
const newContext: TimelineViewContext = {};
|
||||||
|
if (addWindow && this._timeline) {
|
||||||
|
newContext.window = this._timeline.getWindow();
|
||||||
|
} else if (currentContext?.window) {
|
||||||
|
newContext.window = currentContext.window;
|
||||||
|
}
|
||||||
|
if (this._events.lastFetchDate) {
|
||||||
|
newContext.dateFetch = this._events.lastFetchDate;
|
||||||
|
}
|
||||||
|
console.info(`returning ${JSON.stringify(newContext)}`);
|
||||||
|
return newContext || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user