diff --git a/src/components/timeline.ts b/src/components/timeline.ts index b660cabf..55281053 100644 --- a/src/components/timeline.ts +++ b/src/components/timeline.ts @@ -1,10 +1,8 @@ // TODO: When a media viewer is first loaded the selected child won't work (because the underlying carousel has not yet rendered) -// TODO: unselect in mini timeline should not cause media viewer to render nothing // TODO: delete segments if not in summary? is this actually necessary? could it create gaps in data? better off stopping access via summary? // TODO: support filtering created dataviews by recordings or mediatype (so storage ) // TODO: Make minitimeline configurable in the editor -// TODO: Make performance okay for 2+ days of events import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit'; import { customElement, property } from 'lit/decorators.js'; diff --git a/src/types.ts b/src/types.ts index ed213d7c..d8625026 100644 --- a/src/types.ts +++ b/src/types.ts @@ -569,10 +569,12 @@ export type PictureElements = z.infer; */ const mediaLayoutConfigSchema = z.object({ fit: z.enum(['contain', 'cover', 'fill']).optional(), - position: z.object({ - x: z.number().min(0).max(100).optional(), - y: z.number().min(0).max(100).optional(), - }).optional(), + position: z + .object({ + x: z.number().min(0).max(100).optional(), + y: z.number().min(0).max(100).optional(), + }) + .optional(), }); export type MediaLayoutConfig = z.infer; @@ -667,27 +669,26 @@ const timelineCoreConfigDefault = { show_recordings: true, }; -const timelineCoreConfigSchema = z - .object({ - clustering_threshold: z - .number() - .optional() - .default(timelineCoreConfigDefault.clustering_threshold), - media: z - .enum(['all', 'clips', 'snapshots']) - .optional() - .default(timelineCoreConfigDefault.media), - window_seconds: z - .number() - .min(1 * 60) - .max(24 * 60 * 60) - .optional() - .default(timelineCoreConfigDefault.window_seconds), - show_recordings: z - .boolean() - .optional() - .default(timelineCoreConfigDefault.show_recordings), - }); +const timelineMediaSchema = z.enum(['all', 'clips', 'snapshots']); +export type TimelineMedia = z.infer; + +const timelineCoreConfigSchema = z.object({ + clustering_threshold: z + .number() + .optional() + .default(timelineCoreConfigDefault.clustering_threshold), + media: timelineMediaSchema.optional().default(timelineCoreConfigDefault.media), + window_seconds: z + .number() + .min(1 * 60) + .max(24 * 60 * 60) + .optional() + .default(timelineCoreConfigDefault.window_seconds), + show_recordings: z + .boolean() + .optional() + .default(timelineCoreConfigDefault.show_recordings), +}); export type TimelineCoreConfig = z.infer; const miniTimelineConfigSchema = timelineCoreConfigSchema.extend({ @@ -1136,7 +1137,8 @@ const timelineConfigDefault = { }, }; -const timelineConfigSchema = timelineCoreConfigSchema.extend({ +const timelineConfigSchema = timelineCoreConfigSchema + .extend({ controls: z .object({ thumbnails: thumbnailsControlSchema @@ -1417,7 +1419,7 @@ export const frigateBrowseMediaSourceSchema: z.ZodSchema = z. children: z.array(frigateBrowseMediaSourceSchema).nullable().optional(), frigate: z .object({ - event: frigateEventSchema + event: frigateEventSchema, }) .optional(), }), diff --git a/src/utils/timeline-data-manager.ts b/src/utils/timeline-data-manager.ts index 2e6fdcde..af6deb44 100644 --- a/src/utils/timeline-data-manager.ts +++ b/src/utils/timeline-data-manager.ts @@ -122,6 +122,12 @@ export class TimelineDataManager { return this._recordingSummary.get(cameraID) ?? null; } + /** + * Create a dataview for a given set of camera. + * @param cameraIDs The cameraIDs to include. + * @param showRecordings Whether or not to show recordings. + * @returns + */ public createDataView( cameraIDs: Set, showRecordings: boolean, @@ -134,10 +140,17 @@ export class TimelineDataManager { }); } + /** + * Create a dataview for segments. + * @returns + */ public createSegmentDataView(): DataView { return new DataView(this._recordingSegments); } + /** + * Get the underlying recording segments dataset. + */ get recordingSegments(): DataSet { return this._recordingSegments; }