Restore initial draft of video seeking.
This commit is contained in:
@@ -197,6 +197,7 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine {
|
|||||||
engine: Engine.Frigate,
|
engine: Engine.Frigate,
|
||||||
events: await getEvents(hass, nativeQuery),
|
events: await getEvents(hass, nativeQuery),
|
||||||
expiry: add(new Date(), { seconds: EVENT_REQUEST_CACHE_MAX_AGE_SECONDS }),
|
expiry: add(new Date(), { seconds: EVENT_REQUEST_CACHE_MAX_AGE_SECONDS }),
|
||||||
|
cached: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,6 +258,7 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine {
|
|||||||
expiry: add(new Date(), {
|
expiry: add(new Date(), {
|
||||||
seconds: RECORDING_SUMMARY_REQUEST_CACHE_MAX_AGE_SECONDS,
|
seconds: RECORDING_SUMMARY_REQUEST_CACHE_MAX_AGE_SECONDS,
|
||||||
}),
|
}),
|
||||||
|
cached: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +287,7 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine {
|
|||||||
type: QueryResultsType.RecordingSegments,
|
type: QueryResultsType.RecordingSegments,
|
||||||
engine: Engine.Frigate,
|
engine: Engine.Frigate,
|
||||||
segments: cachedSegments,
|
segments: cachedSegments,
|
||||||
|
cached: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,6 +307,7 @@ export class FrigateCameraManagerEngine implements CameraManagerEngine {
|
|||||||
type: QueryResultsType.RecordingSegments,
|
type: QueryResultsType.RecordingSegments,
|
||||||
engine: Engine.Frigate,
|
engine: Engine.Frigate,
|
||||||
segments: segments,
|
segments: segments,
|
||||||
|
cached: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -210,10 +210,7 @@ export class CameraManager {
|
|||||||
orderBy(
|
orderBy(
|
||||||
// Ensure uniqueness by the ID (if specified), otherwise all elements
|
// Ensure uniqueness by the ID (if specified), otherwise all elements
|
||||||
// are assumed to be unique.
|
// are assumed to be unique.
|
||||||
uniqBy(
|
uniqBy(mediaArray, (media) => media.getID() ?? media),
|
||||||
mediaArray,
|
|
||||||
(media) => media.getID() ?? media,
|
|
||||||
),
|
|
||||||
|
|
||||||
// Sort all items leading with the most recent.
|
// Sort all items leading with the most recent.
|
||||||
(media) => media.getStartTime(),
|
(media) => media.getStartTime(),
|
||||||
@@ -315,9 +312,15 @@ export class CameraManager {
|
|||||||
result = await engine.getRecordingSegments(hass, this._cameras, query);
|
result = await engine.getRecordingSegments(hass, this._cameras, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The engine may independently cached the results. Respect that in our
|
||||||
|
// debug logging.
|
||||||
|
if (result?.cached) {
|
||||||
|
queryCachedCount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
if (result.expiry) {
|
if (result.expiry) {
|
||||||
this._requestCache.set(query, result, result.expiry);
|
this._requestCache.set(query, { ...result, cached: true }, result.expiry);
|
||||||
}
|
}
|
||||||
results.set(query, result as QueryReturnType<QT>);
|
results.set(query, result as QueryReturnType<QT>);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export interface QueryResults {
|
|||||||
type: QueryResultsType;
|
type: QueryResultsType;
|
||||||
engine: Engine;
|
engine: Engine;
|
||||||
expiry?: Date;
|
expiry?: Date;
|
||||||
|
cached?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type QueryReturnType<QT> = QT extends EventQuery
|
export type QueryReturnType<QT> = QT extends EventQuery
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import { getAllDependentCameras, getCameraTitle } from '../utils/camera.js';
|
|||||||
import {
|
import {
|
||||||
createViewForEvents,
|
createViewForEvents,
|
||||||
createViewForRecordings,
|
createViewForRecordings,
|
||||||
|
findClosestMediaIndex,
|
||||||
generateMediaViewerContext,
|
generateMediaViewerContext,
|
||||||
} from '../utils/media-to-view';
|
} from '../utils/media-to-view';
|
||||||
import { CameraManager } from '../camera/manager';
|
import { CameraManager } from '../camera/manager';
|
||||||
@@ -387,51 +388,66 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
* @param properties The range change properties.
|
* @param properties The range change properties.
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
protected _setViewDuringRangeChange(
|
protected async _setViewDuringRangeChange(
|
||||||
_targetTime: Date,
|
targetTime: Date,
|
||||||
_properties: TimelineRangeChange,
|
properties: TimelineRangeChange,
|
||||||
): void {
|
): Promise<void> {
|
||||||
|
const results = this.view?.queryResults;
|
||||||
|
const media = results?.getResults();
|
||||||
if (
|
if (
|
||||||
|
!media ||
|
||||||
|
!results ||
|
||||||
!this._timeline ||
|
!this._timeline ||
|
||||||
!this.view ||
|
!this.view ||
|
||||||
// !this.view.target?.length ||
|
!this.hass ||
|
||||||
|
!this.cameraManager ||
|
||||||
!this.cameraManager
|
!this.cameraManager
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
|
const canSeek = !!this.view?.isViewerView();
|
||||||
// const canSeek = !!this.view?.isViewerView();
|
|
||||||
// const context = canSeek
|
|
||||||
// ? generateMediaViewerContextForChildren(
|
|
||||||
// this.cameraManager,
|
|
||||||
// this.view.target,
|
|
||||||
// targetTime,
|
|
||||||
// )
|
|
||||||
// : null;
|
|
||||||
|
|
||||||
// const childIndex = this._locked
|
const context = canSeek
|
||||||
// ? null
|
? await generateMediaViewerContext(
|
||||||
// : findChildIndex(
|
this.hass,
|
||||||
// this.view.target.children,
|
this.cameraManager,
|
||||||
// targetTime,
|
media,
|
||||||
// this._getTimelineCameraIDs(),
|
targetTime,
|
||||||
// properties.event.additionalEvent === 'panright' ? 'end' : 'start',
|
)
|
||||||
// );
|
: null;
|
||||||
|
|
||||||
// if (canSeek || (childIndex !== null && childIndex !== this.view.childIndex)) {
|
const newResults = this._locked
|
||||||
// this.view
|
? null
|
||||||
// .evolve({
|
: results
|
||||||
// ...(childIndex !== null && {
|
.clone()
|
||||||
// childIndex: childIndex,
|
.resetSelectedResult()
|
||||||
// }),
|
.selectBestResult((media) =>
|
||||||
// }) // Whether or not to set the timeline window.
|
findClosestMediaIndex(
|
||||||
// .mergeInContext({
|
media,
|
||||||
// ...this._generateTimelineContext({ noSetWindow: true }),
|
targetTime,
|
||||||
// ...context,
|
this._getTimelineCameraIDs(),
|
||||||
// })
|
properties.event.additionalEvent === 'panright' ? 'end' : 'start',
|
||||||
// .dispatchChangeEvent(this);
|
),
|
||||||
// }
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
canSeek ||
|
||||||
|
(newResults &&
|
||||||
|
newResults.hasSelectedResult() &&
|
||||||
|
newResults.getResult() !== results.getResult())
|
||||||
|
) {
|
||||||
|
this.view
|
||||||
|
.evolve({
|
||||||
|
...(newResults &&
|
||||||
|
newResults.hasSelectedResult() && { queryResults: newResults }),
|
||||||
|
}) // Whether or not to set the timeline window.
|
||||||
|
.mergeInContext({
|
||||||
|
...this._generateTimelineContext({ noSetWindow: true }),
|
||||||
|
...context,
|
||||||
|
})
|
||||||
|
.dispatchChangeEvent(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -537,9 +553,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
?.clone()
|
?.clone()
|
||||||
.resetSelectedResult()
|
.resetSelectedResult()
|
||||||
.selectResultIfFound(
|
.selectResultIfFound(
|
||||||
(media) =>
|
(media) => !!this.cameras && media.getID() === properties.item,
|
||||||
!!this.cameras &&
|
|
||||||
media.getID(this.cameras.get(media.getCameraID())) === properties.item,
|
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -662,9 +676,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
);
|
);
|
||||||
if (options?.selectedItem) {
|
if (options?.selectedItem) {
|
||||||
view.queryResults?.selectResultIfFound(
|
view.queryResults?.selectResultIfFound(
|
||||||
(media) =>
|
(media) => !!this.cameras && media.getID() === options.selectedItem,
|
||||||
!!this.cameras &&
|
|
||||||
media.getID(this.cameras.get(media.getCameraID())) === options.selectedItem,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return view;
|
return view;
|
||||||
@@ -799,7 +811,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const media = this.view?.queryResults?.getSelectedResult();
|
const media = this.view?.queryResults?.getSelectedResult();
|
||||||
const selectedId = media?.getID(this.cameras.get(media.getCameraID()));
|
const selectedId = media?.getID();
|
||||||
const firstMedia = (<FrigateCardTimelineItem>first).media;
|
const firstMedia = (<FrigateCardTimelineItem>first).media;
|
||||||
const secondMedia = (<FrigateCardTimelineItem>second).media;
|
const secondMedia = (<FrigateCardTimelineItem>second).media;
|
||||||
|
|
||||||
@@ -810,7 +822,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
|||||||
first.type !== 'background' &&
|
first.type !== 'background' &&
|
||||||
first.type === second.type &&
|
first.type === second.type &&
|
||||||
first.id !== selectedId &&
|
first.id !== selectedId &&
|
||||||
second.id != selectedId &&
|
second.id !== selectedId &&
|
||||||
!!firstMedia &&
|
!!firstMedia &&
|
||||||
!!secondMedia &&
|
!!secondMedia &&
|
||||||
ViewMediaClassifier.isEvent(firstMedia) &&
|
ViewMediaClassifier.isEvent(firstMedia) &&
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
// Medium:
|
// Minor / later:
|
||||||
// - TODO: ts-prune https://camchenry.com/blog/deleting-dead-code-in-typescript
|
// - TODO: ts-prune https://camchenry.com/blog/deleting-dead-code-in-typescript
|
||||||
// - TODO: getRecordingTitle should use getCameraTitle but need hass.
|
// - TODO: getRecordingTitle should use getCameraTitle but need hass.
|
||||||
|
// - TODO: Pass timezone to recordings & event summary endpoint.
|
||||||
|
|
||||||
// Hard:
|
// Hard:
|
||||||
// - TODO: Implement dragging the timeline seeking forward in both Frigate recordings & events.
|
// - TODO: Implement dragging the timeline seeking forward in both Frigate recordings & events.
|
||||||
|
|||||||
Reference in New Issue
Block a user