Fix thumbnails for recordings.

This commit is contained in:
Dermot Duffy
2022-09-22 17:44:43 -07:00
parent eb88c6e0e0
commit f11822fc87
4 changed files with 63 additions and 40 deletions
+6 -5
View File
@@ -175,19 +175,20 @@ export class FrigateCardSurround extends LitElement {
) => { ) => {
const child: FrigateBrowseMediaSource | null = const child: FrigateBrowseMediaSource | null =
ev.detail.target?.children?.[ev.detail.childIndex] ?? null; ev.detail.target?.children?.[ev.detail.childIndex] ?? null;
// Send the view change from the source of the tap event, so the
// view change will be caught by the handler above (to close the drawer).
if (child) { if (child) {
this.view this.view
?.evolve({ ?.evolve({
view: this.view.is('recording') ? 'recording' : 'media', view: this.view.is('recording') ? 'recording' : 'media',
target: ev.detail.target, target: ev.detail.target,
childIndex: ev.detail.childIndex, childIndex: ev.detail.childIndex,
context: null, ...(child.frigate?.cameraID && {
...(child?.frigate?.cameraID && { camera: child.frigate?.cameraID,
camera: child?.frigate?.cameraID,
}), }),
}) })
.removeContext('timeline')
// Send the view change from the source of the tap event, so
// the view change will be caught by the handler above (to
// close the drawer).
.dispatchChangeEvent(ev.composedPath()[0]); .dispatchChangeEvent(ev.composedPath()[0]);
} }
}} }}
+3
View File
@@ -303,6 +303,9 @@ export class FrigateCardThumbnail extends LitElement {
.removeContext('timeline') .removeContext('timeline')
.dispatchChangeEvent(this); .dispatchChangeEvent(this);
} else if (recording) { } else if (recording) {
// Specifically reset the media target/childIndex, as we cannot
// 'select' an hour in the timeline rather we set the window to
// matching values.
this.view this.view
?.evolve({ ?.evolve({
view: 'timeline', view: 'timeline',
+46 -27
View File
@@ -40,6 +40,7 @@ import {
FrigateBrowseMediaSource, FrigateBrowseMediaSource,
frigateCardConfigDefaults, frigateCardConfigDefaults,
FrigateEvent, FrigateEvent,
FrigateRecording,
TimelineCoreConfig, TimelineCoreConfig,
} from '../types'; } from '../types';
import { stopEventFromActivatingCardWideActions } from '../utils/action'; import { stopEventFromActivatingCardWideActions } from '../utils/action';
@@ -65,7 +66,7 @@ import {
} from '../utils/timeline-data-manager'; } from '../utils/timeline-data-manager';
import { View } from '../view'; import { View } from '../view';
import { dispatchMessageEvent } from './message.js'; import { dispatchMessageEvent } from './message.js';
import "./thumbnail.js"; import './thumbnail.js';
interface FrigateCardGroupData { interface FrigateCardGroupData {
id: string; id: string;
@@ -557,7 +558,7 @@ export class FrigateCardTimelineCore extends LitElement {
childIndex: childIndex, childIndex: childIndex,
}), }),
}) })
.mergeInContext({ ...this._generateTimelineContext(true), ...context }) .mergeInContext({ ...this._generateTimelineContext(), ...context })
.dispatchChangeEvent(this); .dispatchChangeEvent(this);
} }
} }
@@ -567,7 +568,7 @@ export class FrigateCardTimelineCore extends LitElement {
* seek times into each media item). * seek times into each media item).
* @param children The media children. * @param children The media children.
* @param targetTime The target time. * @param targetTime The target time.
* @returns * @returns The ViewContext.
*/ */
protected _generateMediaViewerContextForChildren( protected _generateMediaViewerContextForChildren(
children: FrigateBrowseMediaSource[], children: FrigateBrowseMediaSource[],
@@ -771,7 +772,7 @@ export class FrigateCardTimelineCore extends LitElement {
target: thumbnails?.target ?? null, target: thumbnails?.target ?? null,
childIndex: thumbnails?.childIndex ?? null, childIndex: thumbnails?.childIndex ?? null,
}) })
.mergeInContext(this._generateTimelineContext(true)) .mergeInContext(this._generateTimelineContext())
.dispatchChangeEvent(this); .dispatchChangeEvent(this);
} }
}); });
@@ -874,6 +875,15 @@ export class FrigateCardTimelineCore extends LitElement {
]; ];
} }
/**
* Given a recording get the start/end window.
* @param recording The FrigateRecording to consider.
* @returns A tuple of start/end date.
*/
protected _getStartEndFromRecording(recording: FrigateRecording): [Date, Date] {
return [fromUnixTime(recording.start_time), fromUnixTime(recording.end_time)];
}
/** /**
* Get the configured window length in seconds. * Get the configured window length in seconds.
*/ */
@@ -1004,8 +1014,12 @@ export class FrigateCardTimelineCore extends LitElement {
} }
const event = this.view?.media?.frigate?.event; const event = this.view?.media?.frigate?.event;
const recording = this.view?.media?.frigate?.recording;
const [windowStart, windowEnd] = event const [windowStart, windowEnd] = event
? this._getStartEndFromEvent(event) ? this._getStartEndFromEvent(event)
: recording
? this._getStartEndFromRecording(recording)
: this._getStartEnd(); : this._getStartEnd();
let fetched = false; let fetched = false;
@@ -1042,33 +1056,40 @@ export class FrigateCardTimelineCore extends LitElement {
this.timelineDataManager?.rewriteItem(event.id); this.timelineDataManager?.rewriteItem(event.id);
} }
let contextWindow: TimelineWindow | null = null;
if (!this._pointerHeld) { if (!this._pointerHeld) {
// 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.
const context = this.view.context?.timeline; const context = this.view.context?.timeline;
const timelineWindow = this._timeline.getWindow(); const timelineWindow = this._timeline.getWindow();
if (context?.window) { // If there's a set context window, always move to it.
if (!isEqual(context.window, timelineWindow)) { if (context?.window && !isEqual(context.window, timelineWindow)) {
this._timeline.setWindow(context.window.start, context.window.end); contextWindow = {start: context.window.start, end: context.window.end};
} } else if (event || recording) {
} else if (event) { const source = event ?? recording as FrigateEvent | FrigateRecording;
const eventStart = new Date(event.start_time * 1000); const start = fromUnixTime(source.start_time);
const eventEnd = event.end_time ? new Date(event.end_time * 1000) : 0; const end = source.end_time ? fromUnixTime(source.end_time) : 0;
// If there's an event or recording outside the current window, move to it.
if ( if (
eventStart < timelineWindow.start || start < timelineWindow.start ||
eventStart > timelineWindow.end || start > timelineWindow.end ||
(eventEnd && (end &&
(eventEnd < timelineWindow.start || eventEnd > timelineWindow.end)) (end < timelineWindow.start || end > timelineWindow.end))
) { ) {
this._timeline.setWindow(windowStart, windowEnd); contextWindow = {start: windowStart, end: windowEnd};
} }
} else { } else {
this._timeline.setWindow(windowStart, windowEnd); // Otherwise just the default window.
contextWindow = {start: windowStart, end: windowEnd};
} }
} }
if (contextWindow) {
this._timeline.setWindow(contextWindow.start, contextWindow.end);
}
// Only generate thumbnails if an actual fetch occurred, to avoid getting // Only generate thumbnails if an actual fetch occurred, to avoid getting
// stuck in a loop (the subsequent fetches will not actually fetch since the // stuck in a loop (the subsequent fetches will not actually fetch since the
// data will have been cached). // data will have been cached).
@@ -1078,15 +1099,17 @@ export class FrigateCardTimelineCore extends LitElement {
// -> Thumbnails generated // -> Thumbnails generated
// -> New view dispatched (to load thumbnails into outer carousel). // -> New view dispatched (to load thumbnails into outer carousel).
// -> New view received ... [loop] // -> New view received ... [loop]
//
if ((fetched || !this.view.context?.timeline?.generatedThumbnails) && !this.mini) { // Also don't generate thumbnails in mini-timelines (they will already have
// been generated), or if the media child is a recording.
if ((fetched || !this.view.context?.timeline?.generatedThumbnails) && !this.mini && !recording) {
const thumbnails = this._generateThumbnails(); const thumbnails = this._generateThumbnails();
this.view this.view
?.evolve({ ?.evolve({
target: thumbnails?.target ?? null, target: thumbnails?.target ?? null,
childIndex: thumbnails?.childIndex ?? null, childIndex: thumbnails?.childIndex ?? null,
}) })
.mergeInContext(this._generateTimelineContext(false)) .mergeInContext(this._generateTimelineContext(contextWindow))
.dispatchChangeEvent(this); .dispatchChangeEvent(this);
} }
} }
@@ -1097,16 +1120,12 @@ export class FrigateCardTimelineCore extends LitElement {
* the window is preserved if it is already in the context. * the window is preserved if it is already in the context.
* @returns The TimelineViewContext object. * @returns The TimelineViewContext object.
*/ */
protected _generateTimelineContext(addWindow: boolean): ViewContext { protected _generateTimelineContext(window?: TimelineWindow | null): ViewContext {
const currentContext = this.view?.context?.timeline;
const newContext: TimelineViewContext = { const newContext: TimelineViewContext = {
generatedThumbnails: true, generatedThumbnails: true,
}; };
if (this._timeline) {
if (addWindow && this._timeline) { newContext.window = window ? window : this._timeline.getWindow();
newContext.window = this._timeline.getWindow();
} else if (currentContext?.window) {
newContext.window = currentContext.window;
} }
if (this.timelineDataManager?.lastFetchDate) { if (this.timelineDataManager?.lastFetchDate) {
newContext.dateFetch = this.timelineDataManager.lastFetchDate; newContext.dateFetch = this.timelineDataManager.lastFetchDate;
+5 -5
View File
@@ -161,11 +161,11 @@
"thumbnails": { "thumbnails": {
"mode": "Media Viewer thumbnails mode", "mode": "Media Viewer thumbnails mode",
"modes": { "modes": {
"above": "Thumbnails above the media", "above": "Thumbnails above",
"below": "Thumbnails below the media", "below": "Thumbnails below",
"left": "Thumbnails in a drawer left of the media", "left": "Thumbnails in a drawer to the left",
"none": "No thumbnails", "none": "No thumbnails",
"right": "Thumbnails in a drawer right of the media" "right": "Thumbnails in a drawer to the right"
}, },
"show_details": "Show details with thumbnails", "show_details": "Show details with thumbnails",
"show_favorite_control": "Show favorite control on thumbnails", "show_favorite_control": "Show favorite control on thumbnails",
@@ -372,7 +372,7 @@
"thumbnail": { "thumbnail": {
"no_thumbnail": "No thumbnail available", "no_thumbnail": "No thumbnail available",
"retain_indefinitely": "Event will be indefinitely retained", "retain_indefinitely": "Event will be indefinitely retained",
"timeline": "See event in timeline" "timeline": "See event/recording in timeline"
}, },
"timeline": { "timeline": {
"lock": "Lock timeline to a single event", "lock": "Lock timeline to a single event",