Allow live thumbnails to load recordings .

This commit is contained in:
Dermot Duffy
2024-02-03 14:23:49 -08:00
parent 3398670b44
commit 93a475c7f4
18 changed files with 295 additions and 101 deletions
+12 -9
View File
@@ -564,7 +564,8 @@ live:
| `show_download_control` | `true` | :white_check_mark: | Whether to show the download control on each thumbnail.| | `show_download_control` | `true` | :white_check_mark: | Whether to show the download control on each thumbnail.|
| `show_favorite_control` | `true` | :white_check_mark: | Whether to show the favorite ('star') control on each thumbnail.| | `show_favorite_control` | `true` | :white_check_mark: | Whether to show the favorite ('star') control on each thumbnail.|
| `show_timeline_control` | `true` | :white_check_mark: | Whether to show the timeline ('target') control on each thumbnail.| | `show_timeline_control` | `true` | :white_check_mark: | Whether to show the timeline ('target') control on each thumbnail.|
| `media` | `all` | :white_check_mark: | Whether to show `clips`, `snapshots` or `all` in the thumbnail carousel in the `live` view.| | `media_type` | `events` | :white_check_mark: | Whether to load `events` or `recordings` media.|
| `events_media_type` | `all` | :white_check_mark: | Whether to show `clips`, `snapshots` or `all` in the thumbnail carousel in the `live` view. This setting is only relevant when the `media_type` parameter (above) is set to `events`.|
#### Live Controls: Next / Previous #### Live Controls: Next / Previous
@@ -597,7 +598,7 @@ live:
| `style` | `ribbon` | :white_check_mark: | Whether the timeline should show events as a single flat `ribbon` or a `stack` of events that are clustered using the `clustering_threshold` (below). | | `style` | `ribbon` | :white_check_mark: | Whether the timeline should show events as a single flat `ribbon` or a `stack` of events that are clustered using the `clustering_threshold` (below). |
| `window_seconds` | `3600` | :white_check_mark: | The length of the default timeline in seconds. By default, 1 hour (`3600` seconds) is shown in the timeline. | | `window_seconds` | `3600` | :white_check_mark: | The length of the default timeline in seconds. By default, 1 hour (`3600` seconds) is shown in the timeline. |
| `clustering_threshold` | `3` | :white_check_mark: | The minimum number of overlapping events to allow prior to clustering/grouping them. Higher numbers cause clustering to happen less frequently. Depending on the timescale/zoom of the timeline, the underlying timeline library may still allow overlaps for low values of this parameter -- for a fully "flat" timeline use the `ribbon` style. `0` disables clustering entirely. Only used in the `stack` style of timeline. | | `clustering_threshold` | `3` | :white_check_mark: | The minimum number of overlapping events to allow prior to clustering/grouping them. Higher numbers cause clustering to happen less frequently. Depending on the timescale/zoom of the timeline, the underlying timeline library may still allow overlaps for low values of this parameter -- for a fully "flat" timeline use the `ribbon` style. `0` disables clustering entirely. Only used in the `stack` style of timeline. |
| `media` | `all` | :white_check_mark: | Whether to show only events with `clips`, events with `snapshots` or `all` events. When `all` is used, `clips` are favored for events that have both a clip and a snapshot.| | `events_media_type` | `all` | :white_check_mark: | Whether to show only events with `clips`, events with `snapshots` or `all` events. When `all` is used, `clips` are favored for events that have both a clip and a snapshot.|
| `show_recordings` | `true` | :white_check_mark: | Whether to show recordings on the timeline (specifically: which hours have any recorded content).| | `show_recordings` | `true` | :white_check_mark: | Whether to show recordings on the timeline (specifically: which hours have any recorded content).|
**Caution**: 🚩 For optimal UX, keep the settings for the mini-timeline in the `live` and `media_viewer` identical. Dragging the timeline may cause the card to change between the `live` view and `media_viewer` based views as the user pans between the past and present -- if the settings are different the timeline must "reset". **Caution**: 🚩 For optimal UX, keep the settings for the mini-timeline in the `live` and `media_viewer` identical. Dragging the timeline may cause the card to change between the `live` view and `media_viewer` based views as the user pans between the past and present -- if the settings are different the timeline must "reset".
@@ -781,7 +782,7 @@ media_viewer:
| `style` | `ribbon` | :heavy_multiplication_x: | Whether the timeline should show events as a single flat `ribbon` or a `stack` of events that are clustered using the `clustering_threshold` (below). | | `style` | `ribbon` | :heavy_multiplication_x: | Whether the timeline should show events as a single flat `ribbon` or a `stack` of events that are clustered using the `clustering_threshold` (below). |
| `window_seconds` | `3600` | :heavy_multiplication_x: | The length of the default timeline in seconds. By default, 1 hour (`3600` seconds) is shown in the timeline. | | `window_seconds` | `3600` | :heavy_multiplication_x: | The length of the default timeline in seconds. By default, 1 hour (`3600` seconds) is shown in the timeline. |
| `clustering_threshold` | `3` | :heavy_multiplication_x: | The minimum number of overlapping events to allow prior to clustering/grouping them. Higher numbers cause clustering to happen less frequently. Depending on the timescale/zoom of the timeline, the underlying timeline library may still allow overlaps for low values of this parameter -- for a fully "flat" timeline use the `ribbon` style. `0` disables clustering entirely. Only used in the `stack` style of timeline. | | `clustering_threshold` | `3` | :heavy_multiplication_x: | The minimum number of overlapping events to allow prior to clustering/grouping them. Higher numbers cause clustering to happen less frequently. Depending on the timescale/zoom of the timeline, the underlying timeline library may still allow overlaps for low values of this parameter -- for a fully "flat" timeline use the `ribbon` style. `0` disables clustering entirely. Only used in the `stack` style of timeline. |
| `media` | `all` | :heavy_multiplication_x: | Whether to show only events with `clips`, events with `snapshots` or `all` events. When `all` is used, `clips` are favored for events that have both a clip and a snapshot.| | `events_media_type` | `all` | :heavy_multiplication_x: | Whether to show only events with `clips`, events with `snapshots` or `all` events. When `all` is used, `clips` are favored for events that have both a clip and a snapshot. |
| `show_recordings` | `true` | :heavy_multiplication_x: | Whether to show recordings on the timeline (specifically: which hours have any recorded content).| | `show_recordings` | `true` | :heavy_multiplication_x: | Whether to show recordings on the timeline (specifically: which hours have any recorded content).|
**Caution**: 🚩 For optimal UX, keep the settings for the mini-timeline in the `live` and `media_viewer` identical. Dragging the timeline may cause the card to change between the `live` view and `media_viewer` based views as the user pans between the past and present -- if the settings are different the timeline must "reset". **Caution**: 🚩 For optimal UX, keep the settings for the mini-timeline in the `live` and `media_viewer` identical. Dragging the timeline may cause the card to change between the `live` view and `media_viewer` based views as the user pans between the past and present -- if the settings are different the timeline must "reset".
@@ -911,7 +912,7 @@ See the [fully expanded timeline configuration example](#config-expanded-timelin
| `style` | `stack` | :heavy_multiplication_x: | Whether the timeline should show events as a single flat `ribbon` or a `stack` of events that are clustered using the `clustering_threshold` (below). | | `style` | `stack` | :heavy_multiplication_x: | Whether the timeline should show events as a single flat `ribbon` or a `stack` of events that are clustered using the `clustering_threshold` (below). |
| `window_seconds` | `3600` | :heavy_multiplication_x: | The length of the default timeline in seconds. By default, 1 hour (`3600` seconds) is shown in the timeline. | | `window_seconds` | `3600` | :heavy_multiplication_x: | The length of the default timeline in seconds. By default, 1 hour (`3600` seconds) is shown in the timeline. |
| `clustering_threshold` | `3` | :heavy_multiplication_x: | The minimum number of overlapping events to allow prior to clustering/grouping them. Higher numbers cause clustering to happen less frequently. Depending on the timescale/zoom of the timeline, the underlying timeline library may still allow overlaps for low values of this parameter -- for a fully "flat" timeline use the `ribbon` style. `0` disables clustering entirely. Only used in the `stack` style of timeline. | | `clustering_threshold` | `3` | :heavy_multiplication_x: | The minimum number of overlapping events to allow prior to clustering/grouping them. Higher numbers cause clustering to happen less frequently. Depending on the timescale/zoom of the timeline, the underlying timeline library may still allow overlaps for low values of this parameter -- for a fully "flat" timeline use the `ribbon` style. `0` disables clustering entirely. Only used in the `stack` style of timeline. |
| `media` | `all` | :heavy_multiplication_x: | Whether to show only events with `clips`, events with `snapshots` or `all` events. When `all` is used, `clips` are favored for events that have both a clip and a snapshot.| | `events_media_type` | `all` | :heavy_multiplication_x: | Whether to show only events with `clips`, events with `snapshots` or `all` events. When `all` is used, `clips` are favored for events that have both a clip and a snapshot.|
| `show_recordings` | `true` | :heavy_multiplication_x: | Whether to show recordings on the timeline (specifically: which hours have any recorded content).| | `show_recordings` | `true` | :heavy_multiplication_x: | Whether to show recordings on the timeline (specifically: which hours have any recorded content).|
| `controls` | | :heavy_multiplication_x: | Configuration for the timeline controls. See below.| | `controls` | | :heavy_multiplication_x: | Configuration for the timeline controls. See below.|
@@ -2092,7 +2093,8 @@ live:
style: chevrons style: chevrons
size: 48 size: 48
thumbnails: thumbnails:
media: clips media_type: events
events_media_type: all
size: 100 size: 100
show_details: false show_details: false
show_download_control: true show_download_control: true
@@ -2103,7 +2105,7 @@ live:
style: ribbon style: ribbon
mode: none mode: none
clustering_threshold: 3 clustering_threshold: 3
media: all events_media_type: all
show_recordings: true show_recordings: true
window_seconds: 3600 window_seconds: 3600
title: title:
@@ -2201,7 +2203,7 @@ media_viewer:
style: ribbon style: ribbon
mode: none mode: none
clustering_threshold: 3 clustering_threshold: 3
media: all events_media_type: all
show_recordings: true show_recordings: true
window_seconds: 3600 window_seconds: 3600
title: title:
@@ -2663,7 +2665,7 @@ Reference: [Timeline Options](#timeline-options).
timeline: timeline:
style: stack style: stack
clustering_threshold: 3 clustering_threshold: 3
media: all events_media_type: all
show_recordings: true show_recordings: true
window_seconds: 3600 window_seconds: 3600
controls: controls:
@@ -2779,7 +2781,8 @@ overrides:
style: chevrons style: chevrons
size: 48 size: 48
thumbnails: thumbnails:
media: clips media_type: events
events_media_type: all
size: 100 size: 100
show_details: false show_details: false
show_download_control: true show_download_control: true
+5 -5
View File
@@ -47,18 +47,18 @@ export class TimelineDataSource {
protected _eventRanges = new ExpiringMemoryRangeSet(); protected _eventRanges = new ExpiringMemoryRangeSet();
protected _cameraIDs: Set<string>; protected _cameraIDs: Set<string>;
protected _mediaType: ClipsOrSnapshotsOrAll; protected _eventsMediaType: ClipsOrSnapshotsOrAll;
protected _showRecordings: boolean; protected _showRecordings: boolean;
constructor( constructor(
cameraManager: CameraManager, cameraManager: CameraManager,
cameraIDs: Set<string>, cameraIDs: Set<string>,
media: ClipsOrSnapshotsOrAll, eventsMediaType: ClipsOrSnapshotsOrAll,
showRecordings: boolean, showRecordings: boolean,
) { ) {
this._cameraManager = cameraManager; this._cameraManager = cameraManager;
this._cameraIDs = cameraIDs; this._cameraIDs = cameraIDs;
this._mediaType = media; this._eventsMediaType = eventsMediaType;
this._showRecordings = showRecordings; this._showRecordings = showRecordings;
} }
@@ -101,8 +101,8 @@ export class TimelineDataSource {
return this._cameraManager.generateDefaultEventQueries(this._cameraIDs, { return this._cameraManager.generateDefaultEventQueries(this._cameraIDs, {
start: window.start, start: window.start,
end: window.end, end: window.end,
...(this._mediaType === 'clips' && { hasClip: true }), ...(this._eventsMediaType === 'clips' && { hasClip: true }),
...(this._mediaType === 'snapshots' && { hasSnapshot: true }), ...(this._eventsMediaType === 'snapshots' && { hasSnapshot: true }),
}); });
} }
+2 -2
View File
@@ -87,7 +87,7 @@ export class FrigateCardGallery extends LitElement {
this.view, this.view,
); );
} else { } else {
const mediaType = this.view.is('snapshots') const eventsMediaType = this.view.is('snapshots')
? 'snapshots' ? 'snapshots'
: this.view.is('clips') : this.view.is('clips')
? 'clips' ? 'clips'
@@ -98,7 +98,7 @@ export class FrigateCardGallery extends LitElement {
this.cardWideConfig, this.cardWideConfig,
this.view, this.view,
{ {
...(mediaType && { mediaType: mediaType }), ...(eventsMediaType && { eventsMediaType: eventsMediaType }),
}, },
); );
} }
+31 -5
View File
@@ -14,9 +14,16 @@ import {
ThumbnailsControlConfig, ThumbnailsControlConfig,
} from '../config/types.js'; } from '../config/types.js';
import basicBlockStyle from '../scss/basic-block.scss'; import basicBlockStyle from '../scss/basic-block.scss';
import { ClipsOrSnapshotsOrAll, ExtendedHomeAssistant } from '../types.js'; import {
ClipsOrSnapshotsOrAll,
EventsOrRecordings,
ExtendedHomeAssistant,
} from '../types.js';
import { contentsChanged, dispatchFrigateCardEvent } from '../utils/basic.js'; import { contentsChanged, dispatchFrigateCardEvent } from '../utils/basic.js';
import { changeViewToRecentEventsForCameraAndDependents } from '../utils/media-to-view'; import {
changeViewToRecentEventsForCameraAndDependents,
changeViewToRecentRecordingForCameraAndDependents,
} from '../utils/media-to-view';
import { View } from '../view/view.js'; import { View } from '../view/view.js';
import './surround-basic.js'; import './surround-basic.js';
import { ThumbnailCarouselTap } from './thumbnail-carousel.js'; import { ThumbnailCarouselTap } from './thumbnail-carousel.js';
@@ -48,7 +55,10 @@ export class FrigateCardSurround extends LitElement {
// If fetchMedia is not specified, no fetching is done. // If fetchMedia is not specified, no fetching is done.
@property({ attribute: false, hasChanged: contentsChanged }) @property({ attribute: false, hasChanged: contentsChanged })
public fetchMedia?: ClipsOrSnapshotsOrAll; public fetchMediaType?: EventsOrRecordings;
@property({ attribute: false, hasChanged: contentsChanged })
public fetchEventsMediaType?: ClipsOrSnapshotsOrAll;
@property({ attribute: false }) @property({ attribute: false })
public cameraManager?: CameraManager; public cameraManager?: CameraManager;
@@ -68,7 +78,8 @@ export class FrigateCardSurround extends LitElement {
if ( if (
!this.cameraManager || !this.cameraManager ||
!this.cardWideConfig || !this.cardWideConfig ||
!this.fetchMedia || !this.fetchMediaType ||
!this.fetchEventsMediaType ||
!this.hass || !this.hass ||
!this.view || !this.view ||
this.view.query || this.view.query ||
@@ -78,6 +89,8 @@ export class FrigateCardSurround extends LitElement {
) { ) {
return; return;
} }
if (this.fetchMediaType === 'events') {
await changeViewToRecentEventsForCameraAndDependents( await changeViewToRecentEventsForCameraAndDependents(
this, this,
this.cameraManager, this.cameraManager,
@@ -86,10 +99,23 @@ export class FrigateCardSurround extends LitElement {
{ {
allCameras: this.view.isGrid(), allCameras: this.view.isGrid(),
targetView: this.view.view, targetView: this.view.view,
mediaType: this.fetchMedia, eventsMediaType: this.fetchEventsMediaType,
select: 'latest', select: 'latest',
}, },
); );
} else if (this.fetchMediaType === 'recordings') {
await changeViewToRecentRecordingForCameraAndDependents(
this,
this.cameraManager,
this.cardWideConfig,
this.view,
{
allCameras: this.view.isGrid(),
targetView: this.view.view,
select: 'latest',
},
);
}
} }
/** /**
+1 -1
View File
@@ -1161,7 +1161,7 @@ export class FrigateCardTimelineCore extends LitElement {
this._timelineSource = new TimelineDataSource( this._timelineSource = new TimelineDataSource(
this.cameraManager, this.cameraManager,
cameraIDs, cameraIDs,
this.timelineConfig.media, this.timelineConfig.events_media_type,
this.timelineConfig.show_recordings, this.timelineConfig.show_recordings,
); );
} else { } else {
+1 -1
View File
@@ -168,7 +168,7 @@ export class FrigateCardViewer extends LitElement {
{ {
allCameras: this.view.isGrid(), allCameras: this.view.isGrid(),
targetView: 'media', targetView: 'media',
mediaType: mediaType, eventsMediaType: mediaType,
}, },
); );
} }
+5 -2
View File
@@ -163,8 +163,11 @@ export class FrigateCardViews extends LitElement {
class="${classMap(overallClasses)}" class="${classMap(overallClasses)}"
.hass=${this.hass} .hass=${this.hass}
.view=${this.view} .view=${this.view}
.fetchMedia=${this.view?.is('live') .fetchMediaType=${this.view?.is('live')
? this.overriddenConfig.live.controls.thumbnails.media ? this.overriddenConfig.live.controls.thumbnails.media_type
: undefined}
.fetchEventsMediaType=${this.view?.is('live')
? this.overriddenConfig.live.controls.thumbnails.events_media_type
: undefined} : undefined}
.thumbnailConfig=${!this.hide ? thumbnailConfig : undefined} .thumbnailConfig=${!this.hide ? thumbnailConfig : undefined}
.timelineConfig=${!this.hide ? miniTimelineConfig : undefined} .timelineConfig=${!this.hide ? miniTimelineConfig : undefined}
+20
View File
@@ -10,9 +10,13 @@ import {
CONF_CAMERAS_GLOBAL_JSMPEG, CONF_CAMERAS_GLOBAL_JSMPEG,
CONF_CAMERAS_GLOBAL_WEBRTC_CARD, CONF_CAMERAS_GLOBAL_WEBRTC_CARD,
CONF_ELEMENTS, CONF_ELEMENTS,
CONF_LIVE_CONTROLS_THUMBNAILS_EVENTS_MEDIA_TYPE,
CONF_LIVE_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_MEDIA_GALLERY, CONF_MEDIA_GALLERY,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_MENU_BUTTONS_CAMERA_UI, CONF_MENU_BUTTONS_CAMERA_UI,
CONF_OVERRIDES, CONF_OVERRIDES,
CONF_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_VIEW_INTERACTION_SECONDS, CONF_VIEW_INTERACTION_SECONDS,
CONF_VIEW_SCAN_ACTIONS_UNTRIGGER, CONF_VIEW_SCAN_ACTIONS_UNTRIGGER,
} from './const'; } from './const';
@@ -516,4 +520,20 @@ const UPGRADES = [
upgradeWithOverrides('media_viewer.auto_unmute', (data) => upgradeWithOverrides('media_viewer.auto_unmute', (data) =>
data === 'all' ? ['selected', 'visible'] : data === 'never' ? null : arrayify(data), data === 'all' ? ['selected', 'visible'] : data === 'never' ? null : arrayify(data),
), ),
upgradeMoveToWithOverrides(
'live.controls.thumbnails.media',
CONF_LIVE_CONTROLS_THUMBNAILS_EVENTS_MEDIA_TYPE,
),
upgradeMoveToWithOverrides(
'timeline.media',
CONF_TIMELINE_EVENTS_MEDIA_TYPE,
),
upgradeMoveToWithOverrides(
'live.controls.timeline.media',
CONF_LIVE_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
),
upgradeMoveToWithOverrides(
'media_viewer.controls.timeline.media',
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
),
]; ];
+17 -8
View File
@@ -626,26 +626,31 @@ const thumbnailsControlSchema = thumbnailsControlBaseSchema.extend({
}); });
export type ThumbnailsControlConfig = z.infer<typeof thumbnailsControlSchema>; export type ThumbnailsControlConfig = z.infer<typeof thumbnailsControlSchema>;
// *************************************************************************
// Event Media Type Configuration
// *************************************************************************
const eventsMediaTypeSchema = z.enum(['all', 'clips', 'snapshots']);
// ************************************************************************* // *************************************************************************
// Timeline Configuration // Timeline Configuration
// ************************************************************************* // *************************************************************************
const timelineCoreConfigDefault = { const timelineCoreConfigDefault = {
clustering_threshold: 3, clustering_threshold: 3,
media: 'all' as const, events_media_type: 'all' as const,
window_seconds: 60 * 60, window_seconds: 60 * 60,
show_recordings: true, show_recordings: true,
style: 'stack' as const, style: 'stack' as const,
}; };
const timelineMediaSchema = z.enum(['all', 'clips', 'snapshots']);
const timelineCoreConfigSchema = z.object({ const timelineCoreConfigSchema = z.object({
clustering_threshold: z clustering_threshold: z
.number() .number()
.optional() .optional()
.default(timelineCoreConfigDefault.clustering_threshold), .default(timelineCoreConfigDefault.clustering_threshold),
media: timelineMediaSchema.optional().default(timelineCoreConfigDefault.media), events_media_type: eventsMediaTypeSchema
.optional()
.default(timelineCoreConfigDefault.events_media_type),
window_seconds: z window_seconds: z
.number() .number()
.min(1 * 60) .min(1 * 60)
@@ -867,7 +872,8 @@ export type FrigateCardPTZConfig = z.infer<typeof frigateCardPTZSchema>;
const liveThumbnailControlsDefaults = { const liveThumbnailControlsDefaults = {
...thumbnailControlsDefaults, ...thumbnailControlsDefaults,
media: 'all' as const, media_type: 'events' as const,
events_media_type: 'all' as const,
}; };
const liveConfigDefault = { const liveConfigDefault = {
@@ -899,9 +905,12 @@ const liveConfigDefault = {
}; };
const livethumbnailsControlSchema = thumbnailsControlSchema.extend({ const livethumbnailsControlSchema = thumbnailsControlSchema.extend({
media: z media_type: z
.enum(['all', 'clips', 'snapshots']) .enum(['events', 'recordings'])
.default(liveConfigDefault.controls.thumbnails.media), .default(liveConfigDefault.controls.thumbnails.media_type),
events_media_type: eventsMediaTypeSchema.default(
liveConfigDefault.controls.thumbnails.events_media_type,
),
}); });
const liveOverridableConfigSchema = z const liveOverridableConfigSchema = z
+9 -7
View File
@@ -146,8 +146,8 @@ export const CONF_MEDIA_VIEWER_CONTROLS_THUMBNAILS_SIZE =
`${CONF_MEDIA_VIEWER}.controls.thumbnails.size` as const; `${CONF_MEDIA_VIEWER}.controls.thumbnails.size` as const;
export const CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD = export const CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD =
`${CONF_MEDIA_VIEWER}.controls.timeline.clustering_threshold` as const; `${CONF_MEDIA_VIEWER}.controls.timeline.clustering_threshold` as const;
export const CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MEDIA = export const CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE =
`${CONF_MEDIA_VIEWER}.controls.timeline.media` as const; `${CONF_MEDIA_VIEWER}.controls.timeline.events_media_type` as const;
export const CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MODE = export const CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MODE =
`${CONF_MEDIA_VIEWER}.controls.timeline.mode` as const; `${CONF_MEDIA_VIEWER}.controls.timeline.mode` as const;
export const CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_SHOW_RECORDINGS = export const CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_SHOW_RECORDINGS =
@@ -189,8 +189,10 @@ export const CONF_LIVE_CONTROLS_PTZ_ORIENTATION =
`${CONF_LIVE}.controls.ptz.orientation` as const; `${CONF_LIVE}.controls.ptz.orientation` as const;
export const CONF_LIVE_CONTROLS_PTZ_POSITION = export const CONF_LIVE_CONTROLS_PTZ_POSITION =
`${CONF_LIVE}.controls.ptz.position` as const; `${CONF_LIVE}.controls.ptz.position` as const;
export const CONF_LIVE_CONTROLS_THUMBNAILS_MEDIA = export const CONF_LIVE_CONTROLS_THUMBNAILS_MEDIA_TYPE =
`${CONF_LIVE}.controls.thumbnails.media` as const; `${CONF_LIVE}.controls.thumbnails.media_type` as const;
export const CONF_LIVE_CONTROLS_THUMBNAILS_EVENTS_MEDIA_TYPE =
`${CONF_LIVE}.controls.thumbnails.events_media_type` as const;
export const CONF_LIVE_CONTROLS_THUMBNAILS_MODE = export const CONF_LIVE_CONTROLS_THUMBNAILS_MODE =
`${CONF_LIVE}.controls.thumbnails.mode` as const; `${CONF_LIVE}.controls.thumbnails.mode` as const;
export const CONF_LIVE_CONTROLS_THUMBNAILS_SIZE = export const CONF_LIVE_CONTROLS_THUMBNAILS_SIZE =
@@ -205,8 +207,8 @@ export const CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL =
`${CONF_LIVE}.controls.thumbnails.show_timeline_control` as const; `${CONF_LIVE}.controls.thumbnails.show_timeline_control` as const;
export const CONF_LIVE_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD = export const CONF_LIVE_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD =
`${CONF_LIVE}.controls.timeline.clustering_threshold` as const; `${CONF_LIVE}.controls.timeline.clustering_threshold` as const;
export const CONF_LIVE_CONTROLS_TIMELINE_MEDIA = export const CONF_LIVE_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE =
`${CONF_LIVE}.controls.timeline.media` as const; `${CONF_LIVE}.controls.timeline.events_media_type` as const;
export const CONF_LIVE_CONTROLS_TIMELINE_MODE = export const CONF_LIVE_CONTROLS_TIMELINE_MODE =
`${CONF_LIVE}.controls.timeline.mode` as const; `${CONF_LIVE}.controls.timeline.mode` as const;
export const CONF_LIVE_CONTROLS_TIMELINE_SHOW_RECORDINGS = export const CONF_LIVE_CONTROLS_TIMELINE_SHOW_RECORDINGS =
@@ -256,7 +258,7 @@ const CONF_TIMELINE = 'timeline' as const;
export const CONF_TIMELINE_WINDOW_SECONDS = `${CONF_TIMELINE}.window_seconds` as const; export const CONF_TIMELINE_WINDOW_SECONDS = `${CONF_TIMELINE}.window_seconds` as const;
export const CONF_TIMELINE_CLUSTERING_THRESHOLD = export const CONF_TIMELINE_CLUSTERING_THRESHOLD =
`${CONF_TIMELINE}.clustering_threshold` as const; `${CONF_TIMELINE}.clustering_threshold` as const;
export const CONF_TIMELINE_MEDIA = `${CONF_TIMELINE}.media` as const; export const CONF_TIMELINE_EVENTS_MEDIA_TYPE = `${CONF_TIMELINE}.events_media_type` as const;
export const CONF_TIMELINE_SHOW_RECORDINGS = `${CONF_TIMELINE}.show_recordings` as const; export const CONF_TIMELINE_SHOW_RECORDINGS = `${CONF_TIMELINE}.show_recordings` as const;
export const CONF_TIMELINE_STYLE = `${CONF_TIMELINE}.style` as const; export const CONF_TIMELINE_STYLE = `${CONF_TIMELINE}.style` as const;
export const CONF_TIMELINE_CONTROLS_THUMBNAILS_MODE = export const CONF_TIMELINE_CONTROLS_THUMBNAILS_MODE =
+51 -27
View File
@@ -86,7 +86,8 @@ import {
CONF_LIVE_CONTROLS_PTZ_MODE, CONF_LIVE_CONTROLS_PTZ_MODE,
CONF_LIVE_CONTROLS_PTZ_ORIENTATION, CONF_LIVE_CONTROLS_PTZ_ORIENTATION,
CONF_LIVE_CONTROLS_PTZ_POSITION, CONF_LIVE_CONTROLS_PTZ_POSITION,
CONF_LIVE_CONTROLS_THUMBNAILS_MEDIA, CONF_LIVE_CONTROLS_THUMBNAILS_EVENTS_MEDIA_TYPE,
CONF_LIVE_CONTROLS_THUMBNAILS_MEDIA_TYPE,
CONF_LIVE_CONTROLS_THUMBNAILS_MODE, CONF_LIVE_CONTROLS_THUMBNAILS_MODE,
CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_DETAILS, CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_DETAILS,
CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_DOWNLOAD_CONTROL, CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_DOWNLOAD_CONTROL,
@@ -94,7 +95,7 @@ import {
CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL, CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL,
CONF_LIVE_CONTROLS_THUMBNAILS_SIZE, CONF_LIVE_CONTROLS_THUMBNAILS_SIZE,
CONF_LIVE_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD, CONF_LIVE_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD,
CONF_LIVE_CONTROLS_TIMELINE_MEDIA, CONF_LIVE_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_LIVE_CONTROLS_TIMELINE_MODE, CONF_LIVE_CONTROLS_TIMELINE_MODE,
CONF_LIVE_CONTROLS_TIMELINE_SHOW_RECORDINGS, CONF_LIVE_CONTROLS_TIMELINE_SHOW_RECORDINGS,
CONF_LIVE_CONTROLS_TIMELINE_STYLE, CONF_LIVE_CONTROLS_TIMELINE_STYLE,
@@ -138,7 +139,7 @@ import {
CONF_MEDIA_VIEWER_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL, CONF_MEDIA_VIEWER_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL,
CONF_MEDIA_VIEWER_CONTROLS_THUMBNAILS_SIZE, CONF_MEDIA_VIEWER_CONTROLS_THUMBNAILS_SIZE,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MEDIA, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MODE, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MODE,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_SHOW_RECORDINGS, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_SHOW_RECORDINGS,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_STYLE, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_STYLE,
@@ -174,7 +175,7 @@ import {
CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_FAVORITE_CONTROL, CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_FAVORITE_CONTROL,
CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL, CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL,
CONF_TIMELINE_CONTROLS_THUMBNAILS_SIZE, CONF_TIMELINE_CONTROLS_THUMBNAILS_SIZE,
CONF_TIMELINE_MEDIA, CONF_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_TIMELINE_SHOW_RECORDINGS, CONF_TIMELINE_SHOW_RECORDINGS,
CONF_TIMELINE_STYLE, CONF_TIMELINE_STYLE,
CONF_TIMELINE_WINDOW_SECONDS, CONF_TIMELINE_WINDOW_SECONDS,
@@ -452,15 +453,27 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
}, },
]; ];
protected _thumbnailMedias: EditorSelectOption[] = [ protected _thumbnailMediaTypes: EditorSelectOption[] = [
{ value: '', label: '' },
{
value: 'events',
label: localize('config.common.controls.thumbnails.media_types.events'),
},
{
value: 'recordings',
label: localize('config.common.controls.thumbnails.media_types.recordings'),
},
];
protected _thumbnailEventsMediaTypes: EditorSelectOption[] = [
{ value: '', label: '' }, { value: '', label: '' },
{ {
value: 'clips', value: 'clips',
label: localize('config.common.controls.thumbnails.medias.clips'), label: localize('config.common.controls.thumbnails.events_media_types.clips'),
}, },
{ {
value: 'snapshots', value: 'snapshots',
label: localize('config.common.controls.thumbnails.medias.snapshots'), label: localize('config.common.controls.thumbnails.events_media_types.snapshots'),
}, },
]; ];
@@ -498,11 +511,11 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
{ value: 'url', label: localize('config.image.modes.url') }, { value: 'url', label: localize('config.image.modes.url') },
]; ];
protected _timelineMediaTypes: EditorSelectOption[] = [ protected _timelineEventsMediaTypes: EditorSelectOption[] = [
{ value: '', label: '' }, { value: '', label: '' },
{ value: 'all', label: localize('config.common.timeline.medias.all') }, { value: 'all', label: localize('config.common.timeline.events_media_types.all') },
{ value: 'clips', label: localize('config.common.timeline.medias.clips') }, { value: 'clips', label: localize('config.common.timeline.events_media_types.clips') },
{ value: 'snapshots', label: localize('config.common.timeline.medias.snapshots') }, { value: 'snapshots', label: localize('config.common.timeline.events_media_types.snapshots') },
]; ];
protected _timelineStyleTypes: EditorSelectOption[] = [ protected _timelineStyleTypes: EditorSelectOption[] = [
@@ -1149,7 +1162,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
* @param configPathStyle Timeline style config path. * @param configPathStyle Timeline style config path.
* @param configPathWindowSeconds Timeline window config path. * @param configPathWindowSeconds Timeline window config path.
* @param configPathClusteringThreshold Clustering threshold config path. * @param configPathClusteringThreshold Clustering threshold config path.
* @param configPathTimelineMedia Timeline media config path. * @param configPathTimelineEventsMediaType Timeline media config path.
* @param configPathShowRecordings Show recordings config path. * @param configPathShowRecordings Show recordings config path.
* @param defaultShowRecordings Default value of show_recordings. * @param defaultShowRecordings Default value of show_recordings.
* @returns A rendered template. * @returns A rendered template.
@@ -1158,7 +1171,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
configPathStyle: string, configPathStyle: string,
configPathWindowSeconds: string, configPathWindowSeconds: string,
configPathClusteringThreshold: string, configPathClusteringThreshold: string,
configPathTimelineMedia: string, configPathTimelineEventsMediaType: string,
configPathShowRecordings: string, configPathShowRecordings: string,
defaultShowRecordings: boolean, defaultShowRecordings: boolean,
): TemplateResult { ): TemplateResult {
@@ -1175,8 +1188,8 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
${this._renderNumberInput(configPathClusteringThreshold, { ${this._renderNumberInput(configPathClusteringThreshold, {
label: localize(`config.common.${CONF_TIMELINE_CLUSTERING_THRESHOLD}`), label: localize(`config.common.${CONF_TIMELINE_CLUSTERING_THRESHOLD}`),
})} })}
${this._renderOptionSelector(configPathTimelineMedia, this._timelineMediaTypes, { ${this._renderOptionSelector(configPathTimelineEventsMediaType, this._timelineEventsMediaTypes, {
label: localize(`config.common.${CONF_TIMELINE_MEDIA}`), label: localize(`config.common.${CONF_TIMELINE_EVENTS_MEDIA_TYPE}`),
})} })}
${this._renderSwitch(configPathShowRecordings, defaultShowRecordings, { ${this._renderSwitch(configPathShowRecordings, defaultShowRecordings, {
label: localize(`config.common.${CONF_TIMELINE_SHOW_RECORDINGS}`), label: localize(`config.common.${CONF_TIMELINE_SHOW_RECORDINGS}`),
@@ -1188,7 +1201,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
* @param domain The submenu domain. * @param domain The submenu domain.
* @param configPathWindowSeconds Timeline window config path. * @param configPathWindowSeconds Timeline window config path.
* @param configPathClusteringThreshold Clustering threshold config path. * @param configPathClusteringThreshold Clustering threshold config path.
* @param configPathTimelineMedia Timeline media config path. * @param configPathTimelineEventsMediaType Timeline media config path.
* @param configPathShowRecordings Show recordings config path. * @param configPathShowRecordings Show recordings config path.
* @returns A rendered template. * @returns A rendered template.
*/ */
@@ -1198,7 +1211,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
configPathStyle: string, configPathStyle: string,
configPathWindowSeconds: string, configPathWindowSeconds: string,
configPathClusteringThreshold: string, configPathClusteringThreshold: string,
configPathTimelineMedia: string, configPathTimelineEventsMediaType: string,
configPathShowRecordings: string, configPathShowRecordings: string,
showRecordingsDefault: boolean, showRecordingsDefault: boolean,
): TemplateResult | void { ): TemplateResult | void {
@@ -1214,7 +1227,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
configPathStyle, configPathStyle,
configPathWindowSeconds, configPathWindowSeconds,
configPathClusteringThreshold, configPathClusteringThreshold,
configPathTimelineMedia, configPathTimelineEventsMediaType,
configPathShowRecordings, configPathShowRecordings,
showRecordingsDefault, showRecordingsDefault,
)}`, )}`,
@@ -1330,7 +1343,8 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
show_download_control: boolean; show_download_control: boolean;
}, },
options?: { options?: {
configPathMedia?: string; configPathMediaType?: string;
configPathEventsMediaType?: string;
configPathMode?: string; configPathMode?: string;
}, },
): TemplateResult | void { ): TemplateResult | void {
@@ -1349,12 +1363,21 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
}, },
)}` )}`
: html``} : html``}
${options?.configPathMedia ${options?.configPathMediaType
? html`${this._renderOptionSelector( ? html`${this._renderOptionSelector(
options.configPathMedia, options.configPathMediaType,
this._thumbnailMedias, this._thumbnailMediaTypes,
{ {
label: localize('config.common.controls.thumbnails.media'), label: localize('config.common.controls.thumbnails.media_type'),
},
)}`
: html``}
${options?.configPathEventsMediaType
? html`${this._renderOptionSelector(
options.configPathEventsMediaType,
this._thumbnailEventsMediaTypes,
{
label: localize('config.common.controls.thumbnails.events_media_type'),
}, },
)}` )}`
: html``} : html``}
@@ -2101,7 +2124,8 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_DOWNLOAD_CONTROL, CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_DOWNLOAD_CONTROL,
this._defaults.live.controls.thumbnails, this._defaults.live.controls.thumbnails,
{ {
configPathMedia: CONF_LIVE_CONTROLS_THUMBNAILS_MEDIA, configPathMediaType: CONF_LIVE_CONTROLS_THUMBNAILS_MEDIA_TYPE,
configPathEventsMediaType: CONF_LIVE_CONTROLS_THUMBNAILS_EVENTS_MEDIA_TYPE,
configPathMode: CONF_LIVE_CONTROLS_THUMBNAILS_MODE, configPathMode: CONF_LIVE_CONTROLS_THUMBNAILS_MODE,
}, },
)} )}
@@ -2116,7 +2140,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_LIVE_CONTROLS_TIMELINE_STYLE, CONF_LIVE_CONTROLS_TIMELINE_STYLE,
CONF_LIVE_CONTROLS_TIMELINE_WINDOW_SECONDS, CONF_LIVE_CONTROLS_TIMELINE_WINDOW_SECONDS,
CONF_LIVE_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD, CONF_LIVE_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD,
CONF_LIVE_CONTROLS_TIMELINE_MEDIA, CONF_LIVE_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_LIVE_CONTROLS_TIMELINE_SHOW_RECORDINGS, CONF_LIVE_CONTROLS_TIMELINE_SHOW_RECORDINGS,
this._defaults.live.controls.timeline.show_recordings, this._defaults.live.controls.timeline.show_recordings,
)} )}
@@ -2309,7 +2333,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_STYLE, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_STYLE,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_WINDOW_SECONDS, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_WINDOW_SECONDS,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MEDIA, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_SHOW_RECORDINGS, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_SHOW_RECORDINGS,
this._defaults.media_viewer.controls.timeline.show_recordings, this._defaults.media_viewer.controls.timeline.show_recordings,
)} )}
@@ -2347,7 +2371,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_TIMELINE_STYLE, CONF_TIMELINE_STYLE,
CONF_TIMELINE_WINDOW_SECONDS, CONF_TIMELINE_WINDOW_SECONDS,
CONF_TIMELINE_CLUSTERING_THRESHOLD, CONF_TIMELINE_CLUSTERING_THRESHOLD,
CONF_TIMELINE_MEDIA, CONF_TIMELINE_EVENTS_MEDIA_TYPE,
CONF_TIMELINE_SHOW_RECORDINGS, CONF_TIMELINE_SHOW_RECORDINGS,
this._defaults.timeline.show_recordings, this._defaults.timeline.show_recordings,
)} )}
+10 -5
View File
@@ -119,8 +119,13 @@
}, },
"thumbnails": { "thumbnails": {
"editor_label": "Thumbnails", "editor_label": "Thumbnails",
"media": "Whether to show thumbnails of clips or snapshots", "media_type": "Whether to show thumnails of events or recordings",
"medias": { "media_types": {
"events": "Events",
"recordings": "Recordings"
},
"events_media_type": "Whether to show event thumbnails of clips or snapshots",
"events_media_types": {
"clips": "Clip thumbnails", "clips": "Clip thumbnails",
"snapshots": "Snapshot thumbnails" "snapshots": "Snapshot thumbnails"
}, },
@@ -191,9 +196,9 @@
}, },
"timeline": { "timeline": {
"clustering_threshold": "The count of events at which they are clustered (0=no clustering)", "clustering_threshold": "The count of events at which they are clustered (0=no clustering)",
"media": "The media the timeline displays", "events_media_type": "The events media the timeline displays",
"medias": { "events_media_types": {
"all": "All media types", "all": "All event media types",
"clips": "Clips", "clips": "Clips",
"snapshots": "Snapshots" "snapshots": "Snapshots"
}, },
+1
View File
@@ -4,6 +4,7 @@ import { z } from 'zod';
export type ClipsOrSnapshots = 'clips' | 'snapshots'; export type ClipsOrSnapshots = 'clips' | 'snapshots';
export type ClipsOrSnapshotsOrAll = 'clips' | 'snapshots' | 'all'; export type ClipsOrSnapshotsOrAll = 'clips' | 'snapshots' | 'all';
export type EventsOrRecordings = 'events' | 'recordings';
export class FrigateCardError extends Error { export class FrigateCardError extends Error {
context?: unknown; context?: unknown;
+6 -6
View File
@@ -24,7 +24,7 @@ export const changeViewToRecentEventsForCameraAndDependents = async (
view: View, view: View,
options?: { options?: {
allCameras?: boolean; allCameras?: boolean;
mediaType?: ClipsOrSnapshotsOrAll; eventsMediaType?: ClipsOrSnapshotsOrAll;
targetView?: FrigateCardView; targetView?: FrigateCardView;
select?: ResultSelectType; select?: ResultSelectType;
}, },
@@ -37,7 +37,7 @@ export const changeViewToRecentEventsForCameraAndDependents = async (
} }
const queries = createQueriesForEventsView(cameraManager, cardWideConfig, cameraIDs, { const queries = createQueriesForEventsView(cameraManager, cardWideConfig, cameraIDs, {
mediaType: options?.mediaType, eventsMediaType: options?.eventsMediaType,
}); });
if (!queries) { if (!queries) {
return; return;
@@ -62,15 +62,15 @@ const createQueriesForEventsView = (
cardWideConfig: CardWideConfig, cardWideConfig: CardWideConfig,
cameraIDs: Set<string>, cameraIDs: Set<string>,
options?: { options?: {
mediaType?: ClipsOrSnapshotsOrAll; eventsMediaType?: ClipsOrSnapshotsOrAll;
}, },
): EventMediaQueries | null => { ): EventMediaQueries | null => {
const limit = const limit =
cardWideConfig.performance?.features.media_chunk_size ?? MEDIA_CHUNK_SIZE_DEFAULT; cardWideConfig.performance?.features.media_chunk_size ?? MEDIA_CHUNK_SIZE_DEFAULT;
const eventQueries = cameraManager.generateDefaultEventQueries(cameraIDs, { const eventQueries = cameraManager.generateDefaultEventQueries(cameraIDs, {
limit: limit, limit: limit,
...(options?.mediaType === 'clips' && { hasClip: true }), ...(options?.eventsMediaType === 'clips' && { hasClip: true }),
...(options?.mediaType === 'snapshots' && { hasSnapshot: true }), ...(options?.eventsMediaType === 'snapshots' && { hasSnapshot: true }),
}); });
return eventQueries ? new EventMediaQueries(eventQueries) : null; return eventQueries ? new EventMediaQueries(eventQueries) : null;
}; };
@@ -91,7 +91,7 @@ export const changeViewToRecentRecordingForCameraAndDependents = async (
view: View, view: View,
options?: { options?: {
allCameras?: boolean; allCameras?: boolean;
targetView?: 'recording' | 'recordings'; targetView?: FrigateCardView;
select?: ResultSelectType; select?: ResultSelectType;
}, },
): Promise<void> => { ): Promise<void> => {
+100
View File
@@ -1590,5 +1590,105 @@ describe('should handle version specific upgrades', () => {
}); });
}); });
}); });
describe('should rename thumbnails.media to thumbnails.events_media_type', () => {
it.each([['all' as const], ['clips' as const], ['snapshots' as const]])(
'%s',
(mediaEventType: string) => {
const config = {
live: {
controls: {
thumbnails: {
media: mediaEventType,
},
},
},
};
expect(upgradeConfig(config)).toBeTruthy();
expect(config).toEqual({
live: {
controls: {
thumbnails: {
events_media_type: mediaEventType,
},
},
},
});
},
);
});
describe('should rename timeline.media to timeline.events_media_type', () => {
it.each([['all' as const], ['clips' as const], ['snapshots' as const]])(
'%s',
(mediaEventType: string) => {
const config = {
timeline: {
media: mediaEventType,
},
};
expect(upgradeConfig(config)).toBeTruthy();
expect(config).toEqual({
timeline: {
events_media_type: mediaEventType,
},
});
},
);
});
describe('should rename live.controls.timeline.media to live.controls.timeline.events_media_type', () => {
it.each([['all' as const], ['clips' as const], ['snapshots' as const]])(
'%s',
(mediaEventType: string) => {
const config = {
live: {
controls: {
timeline: {
media: mediaEventType,
},
},
},
};
expect(upgradeConfig(config)).toBeTruthy();
expect(config).toEqual({
live: {
controls: {
timeline: {
events_media_type: mediaEventType,
},
},
},
});
},
);
});
describe('should rename media_viewer.controls.timeline.media to media_viewer.controls.timeline.events_media_type', () => {
it.each([['all' as const], ['clips' as const], ['snapshots' as const]])(
'%s',
(mediaEventType: string) => {
const config = {
media_viewer: {
controls: {
timeline: {
media: mediaEventType,
},
},
},
};
expect(upgradeConfig(config)).toBeTruthy();
expect(config).toEqual({
media_viewer: {
controls: {
timeline: {
events_media_type: mediaEventType,
},
},
},
});
},
);
});
}); });
}); });
+5 -4
View File
@@ -77,7 +77,8 @@ describe('config defaults', () => {
position: 'bottom-right', position: 'bottom-right',
}, },
thumbnails: { thumbnails: {
media: 'all', media_type: 'events',
events_media_type: 'all',
mode: 'right', mode: 'right',
show_details: true, show_details: true,
show_download_control: true, show_download_control: true,
@@ -87,7 +88,7 @@ describe('config defaults', () => {
}, },
timeline: { timeline: {
clustering_threshold: 3, clustering_threshold: 3,
media: 'all', events_media_type: 'all',
mode: 'none', mode: 'none',
show_recordings: true, show_recordings: true,
style: 'ribbon', style: 'ribbon',
@@ -143,7 +144,7 @@ describe('config defaults', () => {
}, },
timeline: { timeline: {
clustering_threshold: 3, clustering_threshold: 3,
media: 'all', events_media_type: 'all',
mode: 'none', mode: 'none',
show_recordings: true, show_recordings: true,
style: 'ribbon', style: 'ribbon',
@@ -268,7 +269,7 @@ describe('config defaults', () => {
size: 100, size: 100,
}, },
}, },
media: 'all', events_media_type: 'all',
show_recordings: true, show_recordings: true,
style: 'stack', style: 'stack',
window_seconds: 3600, window_seconds: 3600,
+2 -2
View File
@@ -101,7 +101,7 @@ describe('changeViewToRecentEventsForCameraAndDependents', () => {
{}, {},
createView(), createView(),
{ {
mediaType: 'clips', eventsMediaType: 'clips',
}, },
); );
expect(elementHandler.viewHandler).not.toBeCalled(); expect(elementHandler.viewHandler).not.toBeCalled();
@@ -222,7 +222,7 @@ describe('changeViewToRecentEventsForCameraAndDependents', () => {
{}, {},
createView(), createView(),
{ {
mediaType: mediaType, eventsMediaType: mediaType,
}, },
); );
+3 -3
View File
@@ -10,10 +10,10 @@ export default defineConfig({
// Thresholds will automatically be updated as coverage improves to avoid // Thresholds will automatically be updated as coverage improves to avoid
// back-sliding. // back-sliding.
thresholdAutoUpdate: true, thresholdAutoUpdate: true,
statements: 72.72, statements: 72.73,
branches: 61.97, branches: 61.93,
functions: 74.01, functions: 74.01,
lines: 72.62, lines: 72.63,
}, },
}, },
}); });