Allow the carousel 'slide' animation to be disabled.

This commit is contained in:
Dermot Duffy
2022-02-08 20:36:07 -08:00
parent ec33a2ddf8
commit 724ca4c843
9 changed files with 67 additions and 3 deletions
+2
View File
@@ -195,6 +195,7 @@ live:
| `lazy_load` | `true` | :heavy_multiplication_x: | Whether or not to lazily load cameras in the camera carousel. Setting this will `false` will cause all cameras to load simultaneously when the `live` carousel is opened (or cause all cameras to load continually if both `lazy_load` and `preload` are `true`). This will result in a smoother carousel experience at a cost of (potentially) a substantial amount of continually streamed data. | | `lazy_load` | `true` | :heavy_multiplication_x: | Whether or not to lazily load cameras in the camera carousel. Setting this will `false` will cause all cameras to load simultaneously when the `live` carousel is opened (or cause all cameras to load continually if both `lazy_load` and `preload` are `true`). This will result in a smoother carousel experience at a cost of (potentially) a substantial amount of continually streamed data. |
| `lazy_unload` | `false` | :heavy_multiplication_x: | Whether or not to lazily **un**load lazyily-loaded cameras in the camera carousel, or just leave the camera paused. Setting this to `true` will cause cameras to be entirely unloaded when they are no longer visible (either because the carousel has scrolled past them, or because the document has been marked hidden/inactive by the browser). This will cause a reloading delay on revisiting that camera in the carousel but will save the streaming network resources that are otherwise consumed. This option has no effect if `lazy_load` is false. | | `lazy_unload` | `false` | :heavy_multiplication_x: | Whether or not to lazily **un**load lazyily-loaded cameras in the camera carousel, or just leave the camera paused. Setting this to `true` will cause cameras to be entirely unloaded when they are no longer visible (either because the carousel has scrolled past them, or because the document has been marked hidden/inactive by the browser). This will cause a reloading delay on revisiting that camera in the carousel but will save the streaming network resources that are otherwise consumed. This option has no effect if `lazy_load` is false. |
| `draggable` | `true` | :heavy_multiplication_x: | Whether or not the live carousel can be dragged left or right, via touch/swipe and mouse dragging. | | `draggable` | `true` | :heavy_multiplication_x: | Whether or not the live carousel can be dragged left or right, via touch/swipe and mouse dragging. |
| `transition_effect` | `slide` | :heavy_multiplication_x: | Effect to apply as a transition between live cameras. Accepted values: `slide` or `none`. |
| `provider` | `frigate` | :white_check_mark: | The means through which the live camera view is displayed. See [Live Provider](#live-provider) below.| | `provider` | `frigate` | :white_check_mark: | The means through which the live camera view is displayed. See [Live Provider](#live-provider) below.|
| `actions` | | :white_check_mark: | Actions to use for the `live` view. See [actions](#actions) below.| | `actions` | | :white_check_mark: | Actions to use for the `live` view. See [actions](#actions) below.|
| `controls` | | :white_check_mark: | Configuration for the `live` view controls. See below. | | `controls` | | :white_check_mark: | Configuration for the `live` view controls. See below. |
@@ -303,6 +304,7 @@ event_viewer:
| `auto_unmute` | `false` | :heavy_multiplication_x: | Whether or not to automatically unmute clips. Note that some browsers will not allow automated unmute until the user has interacted with the page in some way -- if the user has not then the browser may pause the media instead. | | `auto_unmute` | `false` | :heavy_multiplication_x: | Whether or not to automatically unmute clips. Note that some browsers will not allow automated unmute until the user has interacted with the page in some way -- if the user has not then the browser may pause the media instead. |
| `lazy_load` | `true` | :heavy_multiplication_x: | Whether or not to lazily load media in the event viewer carousel. Setting this will false will fetch all media immediately which may make the carousel experience smoother at a cost of (potentially) a substantial number of simultaneous media fetches on load. | | `lazy_load` | `true` | :heavy_multiplication_x: | Whether or not to lazily load media in the event viewer carousel. Setting this will false will fetch all media immediately which may make the carousel experience smoother at a cost of (potentially) a substantial number of simultaneous media fetches on load. |
| `draggable` | `true` | :heavy_multiplication_x: | Whether or not the event viewer carousel can be dragged left or right, via touch/swipe and mouse dragging. | | `draggable` | `true` | :heavy_multiplication_x: | Whether or not the event viewer carousel can be dragged left or right, via touch/swipe and mouse dragging. |
| `transition_effect` | `slide` | :heavy_multiplication_x: | Effect to apply as a transition between event media. Accepted values: `slide` or `none`. |
| `controls` | | :heavy_multiplication_x: | Configuration for the event viewer. See below. | | `controls` | | :heavy_multiplication_x: | Configuration for the event viewer. See below. |
| `actions` | | :heavy_multiplication_x: | Actions to use for all views that use the `event_viewer` (e.g. `clip`, `snapshot`). See [actions](#actions) below.| | `actions` | | :heavy_multiplication_x: | Actions to use for all views that use the `event_viewer` (e.g. `clip`, `snapshot`). See [actions](#actions) below.|
+10 -1
View File
@@ -5,6 +5,7 @@ import EmblaCarousel, {
EmblaPluginType, EmblaPluginType,
} from 'embla-carousel'; } from 'embla-carousel';
import { TransitionEffect } from '../types';
import { dispatchFrigateCardEvent } from '../common'; import { dispatchFrigateCardEvent } from '../common';
import carouselStyle from '../scss/carousel.scss'; import carouselStyle from '../scss/carousel.scss';
@@ -22,7 +23,7 @@ export class FrigateCardCarousel extends LitElement {
* @param index Slide number. * @param index Slide number.
*/ */
carouselScrollTo(index: number): void { carouselScrollTo(index: number): void {
this._carousel?.scrollTo(index); this._carousel?.scrollTo(index, this._getTransitionEffect() === 'none');
} }
/** /**
@@ -50,6 +51,14 @@ export class FrigateCardCarousel extends LitElement {
} }
} }
/**
* Get the transition effect to use.
* @returns An TransitionEffect object.
*/
protected _getTransitionEffect(): TransitionEffect | undefined {
return 'slide';
}
/** /**
* Get the Embla options to use. * Get the Embla options to use.
* @returns An EmblaOptionsType object or undefined for no options. * @returns An EmblaOptionsType object or undefined for no options.
+9
View File
@@ -18,6 +18,7 @@ import {
FrigateCardMediaPlayer, FrigateCardMediaPlayer,
LiveOverrides, LiveOverrides,
LiveProvider, LiveProvider,
TransitionEffect,
frigateCardConfigDefaults, frigateCardConfigDefaults,
} from '../types.js'; } from '../types.js';
import { EmblaOptionsType, EmblaPluginType } from 'embla-carousel'; import { EmblaOptionsType, EmblaPluginType } from 'embla-carousel';
@@ -314,6 +315,14 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
} }
} }
/**
* Get the transition effect to use.
* @returns An TransitionEffect object.
*/
protected _getTransitionEffect(): TransitionEffect | undefined {
return this.liveConfig?.transition_effect;
}
/** /**
* Get the Embla options to use. * Get the Embla options to use.
* @returns An EmblaOptionsType object or undefined for no options. * @returns An EmblaOptionsType object or undefined for no options.
+2 -2
View File
@@ -191,9 +191,9 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
*/ */
protected _nextPreviousHandler(direction: 'previous' | 'next'): void { protected _nextPreviousHandler(direction: 'previous' | 'next'): void {
if (direction == 'previous') { if (direction == 'previous') {
this._carousel?.scrollPrev(); this._carousel?.scrollPrev(this._getTransitionEffect() === 'none');
} else if (direction == 'next') { } else if (direction == 'next') {
this._carousel?.scrollNext(); this._carousel?.scrollNext(this._getTransitionEffect() === 'none');
} }
} }
+9
View File
@@ -22,6 +22,7 @@ import type {
CameraConfig, CameraConfig,
ExtendedHomeAssistant, ExtendedHomeAssistant,
MediaShowInfo, MediaShowInfo,
TransitionEffect,
ViewerConfig, ViewerConfig,
} from '../types.js'; } from '../types.js';
import { FrigateCardMediaCarousel, IMG_EMPTY } from './media-carousel.js'; import { FrigateCardMediaCarousel, IMG_EMPTY } from './media-carousel.js';
@@ -302,6 +303,14 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
return slideIndex !== undefined ? Number(slideIndex) : undefined; return slideIndex !== undefined ? Number(slideIndex) : undefined;
} }
/**
* Get the transition effect to use.
* @returns An TransitionEffect object.
*/
protected _getTransitionEffect(): TransitionEffect | undefined {
return this.viewerConfig?.transition_effect;
}
/** /**
* Get the Embla options to use. * Get the Embla options to use.
* @returns An EmblaOptionsType object or undefined for no options. * @returns An EmblaOptionsType object or undefined for no options.
+3
View File
@@ -37,6 +37,8 @@ export const CONF_EVENT_VIEWER_AUTO_PLAY = `${CONF_EVENT_VIEWER}.auto_play` as c
export const CONF_EVENT_VIEWER_AUTO_UNMUTE = `${CONF_EVENT_VIEWER}.auto_unmute` as const; export const CONF_EVENT_VIEWER_AUTO_UNMUTE = `${CONF_EVENT_VIEWER}.auto_unmute` as const;
export const CONF_EVENT_VIEWER_DRAGGABLE = `${CONF_EVENT_VIEWER}.draggable` as const; export const CONF_EVENT_VIEWER_DRAGGABLE = `${CONF_EVENT_VIEWER}.draggable` as const;
export const CONF_EVENT_VIEWER_LAZY_LOAD = `${CONF_EVENT_VIEWER}.lazy_load` as const; export const CONF_EVENT_VIEWER_LAZY_LOAD = `${CONF_EVENT_VIEWER}.lazy_load` as const;
export const CONF_EVENT_VIEWER_TRANSITION_EFFECT =
`${CONF_EVENT_VIEWER}.transition_effect` as const;
export const CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE = export const CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE =
`${CONF_EVENT_VIEWER}.controls.next_previous.style` as const; `${CONF_EVENT_VIEWER}.controls.next_previous.style` as const;
export const CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE = export const CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_SIZE =
@@ -70,6 +72,7 @@ export const CONF_LIVE_JSMPEG = `${CONF_LIVE}.jsmpeg` as const;
export const CONF_LIVE_LAZY_LOAD = `${CONF_LIVE}.lazy_load` as const; export const CONF_LIVE_LAZY_LOAD = `${CONF_LIVE}.lazy_load` as const;
export const CONF_LIVE_LAZY_UNLOAD = `${CONF_LIVE}.lazy_unload` as const; export const CONF_LIVE_LAZY_UNLOAD = `${CONF_LIVE}.lazy_unload` as const;
export const CONF_LIVE_PRELOAD = `${CONF_LIVE}.preload` as const; export const CONF_LIVE_PRELOAD = `${CONF_LIVE}.preload` as const;
export const CONF_LIVE_TRANSITION_EFFECT = `${CONF_LIVE}.transition_effect` as const;
export const CONF_LIVE_WEBRTC = `${CONF_LIVE}.webrtc` as const; export const CONF_LIVE_WEBRTC = `${CONF_LIVE}.webrtc` as const;
export const CONF_LIVE_WEBRTC_ENTITY = `${CONF_LIVE_WEBRTC}.entity` as const; export const CONF_LIVE_WEBRTC_ENTITY = `${CONF_LIVE_WEBRTC}.entity` as const;
export const CONF_LIVE_WEBRTC_URL = `${CONF_LIVE_WEBRTC}.url` as const; export const CONF_LIVE_WEBRTC_URL = `${CONF_LIVE_WEBRTC}.url` as const;
+16
View File
@@ -38,6 +38,7 @@ import {
CONF_EVENT_VIEWER_CONTROLS_TITLE_MODE, CONF_EVENT_VIEWER_CONTROLS_TITLE_MODE,
CONF_EVENT_VIEWER_DRAGGABLE, CONF_EVENT_VIEWER_DRAGGABLE,
CONF_EVENT_VIEWER_LAZY_LOAD, CONF_EVENT_VIEWER_LAZY_LOAD,
CONF_EVENT_VIEWER_TRANSITION_EFFECT,
CONF_IMAGE_REFRESH_SECONDS, CONF_IMAGE_REFRESH_SECONDS,
CONF_IMAGE_SRC, CONF_IMAGE_SRC,
CONF_LIVE_AUTO_UNMUTE, CONF_LIVE_AUTO_UNMUTE,
@@ -52,6 +53,7 @@ import {
CONF_LIVE_LAZY_LOAD, CONF_LIVE_LAZY_LOAD,
CONF_LIVE_LAZY_UNLOAD, CONF_LIVE_LAZY_UNLOAD,
CONF_LIVE_PRELOAD, CONF_LIVE_PRELOAD,
CONF_LIVE_TRANSITION_EFFECT,
CONF_MENU_BUTTONS_CLIPS, CONF_MENU_BUTTONS_CLIPS,
CONF_MENU_BUTTONS_FRIGATE, CONF_MENU_BUTTONS_FRIGATE,
CONF_MENU_BUTTONS_FRIGATE_DOWNLOAD, CONF_MENU_BUTTONS_FRIGATE_DOWNLOAD,
@@ -266,6 +268,12 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
], ],
]); ]);
protected _transitionEffects = new Map([
['', ''],
['none', localize('config.event_viewer.transition_effects.none')],
['slide', localize('config.event_viewer.transition_effects.slide')],
]);
public setConfig(config: RawFrigateCardConfig): void { public setConfig(config: RawFrigateCardConfig): void {
// Note: This does not use Zod to parse the configuration, so it may be // Note: This does not use Zod to parse the configuration, so it may be
// partially or completely invalid. It's more useful to have a partially // partially or completely invalid. It's more useful to have a partially
@@ -809,6 +817,10 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_LIVE_CONTROLS_TITLE_DURATION_SECONDS, CONF_LIVE_CONTROLS_TITLE_DURATION_SECONDS,
'number', 'number',
)} )}
${this._renderDropdown(
CONF_LIVE_TRANSITION_EFFECT,
this._transitionEffects,
)}
</div> </div>
` `
: ''} : ''}
@@ -861,6 +873,10 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_EVENT_VIEWER_CONTROLS_TITLE_DURATION_SECONDS, CONF_EVENT_VIEWER_CONTROLS_TITLE_DURATION_SECONDS,
'number', 'number',
)} )}
${this._renderDropdown(
CONF_EVENT_VIEWER_TRANSITION_EFFECT,
this._transitionEffects,
)}
</div>` </div>`
: ''} : ''}
${this._renderOptionSetHeader('image')} ${this._renderOptionSetHeader('image')}
+6
View File
@@ -57,6 +57,11 @@
"auto_unmute": "Automatically unmute media", "auto_unmute": "Automatically unmute media",
"draggable": "Event Viewer can be dragged/swiped", "draggable": "Event Viewer can be dragged/swiped",
"lazy_load": "Event Viewer media is lazily loaded in carousel", "lazy_load": "Event Viewer media is lazily loaded in carousel",
"transition_effect": "Event Viewer transition effect",
"transition_effects": {
"none": "No transition",
"slide": "Slide transition"
},
"controls": { "controls": {
"next_previous": { "next_previous": {
"style": "Event Viewer next & previous control style", "style": "Event Viewer next & previous control style",
@@ -95,6 +100,7 @@
"lazy_load": "Live cameras are lazily loaded", "lazy_load": "Live cameras are lazily loaded",
"lazy_unload": "Live cameras are lazily unloaded", "lazy_unload": "Live cameras are lazily unloaded",
"auto_unmute": "Automatically unmute live cameras", "auto_unmute": "Automatically unmute live cameras",
"transition_effect": "Live camera transition effect",
"controls": { "controls": {
"next_previous": { "next_previous": {
"style": "Live view next & previous control style", "style": "Live view next & previous control style",
+10
View File
@@ -436,6 +436,12 @@ const nextPreviousControlConfigSchema = z.object({
}); });
export type NextPreviousControlConfig = z.infer<typeof nextPreviousControlConfigSchema>; export type NextPreviousControlConfig = z.infer<typeof nextPreviousControlConfigSchema>;
/**
* Carousel transition effect configuration.
*/
const transitionEffectConfigSchema = z.enum(['none', 'slide']);
export type TransitionEffect = z.infer<typeof transitionEffectConfigSchema>;
/** /**
* Title Control configuration section. * Title Control configuration section.
*/ */
@@ -460,6 +466,7 @@ const liveConfigDefault = {
lazy_load: true, lazy_load: true,
lazy_unload: false, lazy_unload: false,
draggable: true, draggable: true,
transition_effect: 'slide' as const,
controls: { controls: {
next_previous: { next_previous: {
size: '48px', size: '48px',
@@ -556,6 +563,7 @@ const liveConfigSchema = liveOverridableConfigSchema
lazy_load: z.boolean().default(liveConfigDefault.lazy_load), lazy_load: z.boolean().default(liveConfigDefault.lazy_load),
lazy_unload: z.boolean().default(liveConfigDefault.lazy_unload), lazy_unload: z.boolean().default(liveConfigDefault.lazy_unload),
draggable: z.boolean().default(liveConfigDefault.draggable), draggable: z.boolean().default(liveConfigDefault.draggable),
transition_effect: transitionEffectConfigSchema.default(liveConfigDefault.transition_effect),
}) })
.default(liveConfigDefault); .default(liveConfigDefault);
export type LiveConfig = z.infer<typeof liveConfigSchema>; export type LiveConfig = z.infer<typeof liveConfigSchema>;
@@ -608,6 +616,7 @@ const viewerConfigDefault = {
auto_unmute: false, auto_unmute: false,
lazy_load: true, lazy_load: true,
draggable: true, draggable: true,
transition_effect: 'slide' as const,
controls: { controls: {
next_previous: { next_previous: {
size: '48px', size: '48px',
@@ -639,6 +648,7 @@ const viewerConfigSchema = z
auto_unmute: z.boolean().default(viewerConfigDefault.auto_unmute), auto_unmute: z.boolean().default(viewerConfigDefault.auto_unmute),
lazy_load: z.boolean().default(viewerConfigDefault.lazy_load), lazy_load: z.boolean().default(viewerConfigDefault.lazy_load),
draggable: z.boolean().default(viewerConfigDefault.draggable), draggable: z.boolean().default(viewerConfigDefault.draggable),
transition_effect: transitionEffectConfigSchema.default(viewerConfigDefault.transition_effect),
controls: z controls: z
.object({ .object({
next_previous: viewerNextPreviousControlConfigSchema.default( next_previous: viewerNextPreviousControlConfigSchema.default(