fix: Seek to the start of review media (#2353)
This commit is contained in:
@@ -422,11 +422,8 @@ export class AdvancedCameraCardViewerCarousel extends LitElement {
|
|||||||
* Fire a media show event when a slide is selected.
|
* Fire a media show event when a slide is selected.
|
||||||
*/
|
*/
|
||||||
protected async _seekHandler(): Promise<void> {
|
protected async _seekHandler(): Promise<void> {
|
||||||
const view = this.viewManagerEpoch?.manager.getView();
|
|
||||||
const seek = view?.context?.mediaViewer?.seek;
|
|
||||||
if (
|
if (
|
||||||
!this.hass ||
|
!this.hass ||
|
||||||
!seek ||
|
|
||||||
!this._media ||
|
!this._media ||
|
||||||
!this._loadedMediaPlayerController ||
|
!this._loadedMediaPlayerController ||
|
||||||
this._selected === null
|
this._selected === null
|
||||||
@@ -438,6 +435,13 @@ export class AdvancedCameraCardViewerCarousel extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const view = this.viewManagerEpoch?.manager.getView();
|
||||||
|
const seek = view?.context?.mediaViewer?.seek ?? selectedMedia.getStartTime();
|
||||||
|
|
||||||
|
if (!seek) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const seekTimeInMedia = selectedMedia.includesTime(seek);
|
const seekTimeInMedia = selectedMedia.includesTime(seek);
|
||||||
setOrRemoveAttribute(this, !seekTimeInMedia, 'unseekable');
|
setOrRemoveAttribute(this, !seekTimeInMedia, 'unseekable');
|
||||||
if (!seekTimeInMedia && !this._loadedMediaPlayerController.isPaused()) {
|
if (!seekTimeInMedia && !this._loadedMediaPlayerController.isPaused()) {
|
||||||
|
|||||||
@@ -9,11 +9,14 @@ import {
|
|||||||
FrigateEventViewMedia,
|
FrigateEventViewMedia,
|
||||||
FrigateRecordingViewMedia,
|
FrigateRecordingViewMedia,
|
||||||
} from '../../../src/camera-manager/frigate/media';
|
} from '../../../src/camera-manager/frigate/media';
|
||||||
import { getReviews } from '../../../src/camera-manager/frigate/requests';
|
|
||||||
import {
|
import {
|
||||||
|
getRecordingSegments,
|
||||||
|
getReviews,
|
||||||
|
} from '../../../src/camera-manager/frigate/requests';
|
||||||
|
import {
|
||||||
|
eventSchema,
|
||||||
FrigateEvent,
|
FrigateEvent,
|
||||||
FrigateReview,
|
FrigateReview,
|
||||||
eventSchema,
|
|
||||||
} from '../../../src/camera-manager/frigate/types.js';
|
} from '../../../src/camera-manager/frigate/types.js';
|
||||||
import { CameraManagerStore } from '../../../src/camera-manager/store';
|
import { CameraManagerStore } from '../../../src/camera-manager/store';
|
||||||
import { CameraManagerRequestCache, QueryType } from '../../../src/camera-manager/types';
|
import { CameraManagerRequestCache, QueryType } from '../../../src/camera-manager/types';
|
||||||
@@ -24,7 +27,7 @@ import { QuerySource } from '../../../src/query-source';
|
|||||||
import { Severity } from '../../../src/severity';
|
import { Severity } from '../../../src/severity';
|
||||||
import { ViewMedia, ViewMediaType } from '../../../src/view/item';
|
import { ViewMedia, ViewMediaType } from '../../../src/view/item';
|
||||||
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
import { EntityRegistryManagerMock } from '../../ha/registry/entity/mock';
|
||||||
import { createCameraConfig, createHASS } from '../../test-utils';
|
import { createCameraConfig, createHASS, TestViewMedia } from '../../test-utils';
|
||||||
|
|
||||||
vi.mock('../../../src/camera-manager/frigate/requests');
|
vi.mock('../../../src/camera-manager/frigate/requests');
|
||||||
|
|
||||||
@@ -113,6 +116,7 @@ const createFrigateCameraConfig = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @vitest-environment jsdom
|
||||||
describe('getMediaDownloadPath', () => {
|
describe('getMediaDownloadPath', () => {
|
||||||
it('should get event with clip download path', async () => {
|
it('should get event with clip download path', async () => {
|
||||||
const endpoint = await createEngine().getMediaDownloadPath(
|
const endpoint = await createEngine().getMediaDownloadPath(
|
||||||
@@ -331,3 +335,78 @@ describe('getReviews', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getMediaSeekTime', () => {
|
||||||
|
it('should get seek time for review media', async () => {
|
||||||
|
const engine = createEngine();
|
||||||
|
const hass = createHASS();
|
||||||
|
const cameraConfig = createCameraConfig({
|
||||||
|
frigate: { camera_name: 'camera-1', client_id: 'client-1' },
|
||||||
|
});
|
||||||
|
const store = mock<CameraManagerStore>();
|
||||||
|
store.getCameraConfig.mockReturnValue(cameraConfig);
|
||||||
|
|
||||||
|
const startTime = new Date('2023-06-16T20:15:00Z');
|
||||||
|
const endTime = new Date('2023-06-16T20:45:00Z');
|
||||||
|
const media = new TestViewMedia({
|
||||||
|
mediaType: ViewMediaType.Review,
|
||||||
|
cameraID: 'camera-1',
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
const segments = [
|
||||||
|
{
|
||||||
|
start_time: new Date('2023-06-16T20:00:00Z').getTime() / 1000,
|
||||||
|
end_time: new Date('2023-06-16T21:00:00Z').getTime() / 1000,
|
||||||
|
id: 'segment-1',
|
||||||
|
motion: 0,
|
||||||
|
objects: 0,
|
||||||
|
segment_size: 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
vi.mocked(getRecordingSegments).mockResolvedValue(segments);
|
||||||
|
|
||||||
|
const seekTime = await engine.getMediaSeekTime(hass, store, media, startTime);
|
||||||
|
|
||||||
|
// 15 minutes into the hour-long recording.
|
||||||
|
expect(seekTime).toBe(15 * 60);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get zero seek time for clip media when seeking to start', async () => {
|
||||||
|
const engine = createEngine();
|
||||||
|
const hass = createHASS();
|
||||||
|
const cameraConfig = createCameraConfig({
|
||||||
|
frigate: { camera_name: 'camera-1', client_id: 'client-1' },
|
||||||
|
});
|
||||||
|
const store = mock<CameraManagerStore>();
|
||||||
|
store.getCameraConfig.mockReturnValue(cameraConfig);
|
||||||
|
|
||||||
|
const startTime = new Date('2023-06-16T20:15:00Z');
|
||||||
|
const endTime = new Date('2023-06-16T20:15:10Z');
|
||||||
|
const media = new TestViewMedia({
|
||||||
|
mediaType: ViewMediaType.Clip,
|
||||||
|
cameraID: 'camera-1',
|
||||||
|
startTime,
|
||||||
|
endTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
const segments = [
|
||||||
|
{
|
||||||
|
start_time: startTime.getTime() / 1000,
|
||||||
|
end_time: endTime.getTime() / 1000,
|
||||||
|
id: 'segment-1',
|
||||||
|
motion: 0,
|
||||||
|
objects: 0,
|
||||||
|
segment_size: 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
vi.mocked(getRecordingSegments).mockResolvedValue(segments);
|
||||||
|
|
||||||
|
const seekTime = await engine.getMediaSeekTime(hass, store, media, startTime);
|
||||||
|
|
||||||
|
expect(seekTime).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user