Merge pull request #1418 from dermotduffy/profiles
Add support for configuration profiles
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { CurrentUser } from '@dermotduffy/custom-card-helpers';
|
||||
import { HassEntities } from 'home-assistant-js-websocket';
|
||||
import merge from 'lodash-es/merge';
|
||||
import { copyConfig } from '../config-mgmt';
|
||||
import { copyConfig } from '../config/management';
|
||||
import {
|
||||
FrigateCardCondition,
|
||||
frigateConditionalSchema,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import isEqual from 'lodash-es/isEqual';
|
||||
import { isConfigUpgradeable } from '../config-mgmt';
|
||||
import { isConfigUpgradeable } from '../config/management';
|
||||
import {
|
||||
CardWideConfig,
|
||||
FrigateCardConfig,
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
RawFrigateCardConfig
|
||||
} from '../config/types';
|
||||
import { localize } from '../localize/localize';
|
||||
import { setLowPerformanceProfile } from '../performance.js';
|
||||
import { setProfiles } from '../config/profiles';
|
||||
import { getParseErrorPaths } from '../utils/zod.js';
|
||||
import { getOverriddenConfig } from './conditions-manager';
|
||||
import { InitializationAspect } from './initialization-manager';
|
||||
@@ -70,10 +70,7 @@ export class ConfigManager {
|
||||
: localize('error.invalid_configuration_no_hint')),
|
||||
);
|
||||
}
|
||||
const config =
|
||||
parseResult.data.performance.profile !== 'low'
|
||||
? parseResult.data
|
||||
: setLowPerformanceProfile(inputConfig, parseResult.data);
|
||||
const config = setProfiles(inputConfig, parseResult.data, parseResult.data.profiles);
|
||||
|
||||
this._rawConfig = inputConfig;
|
||||
if (isEqual(this._config, config)) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { StyleInfo } from 'lit/directives/style-map';
|
||||
import { FrigateCardConfig } from '../config/types';
|
||||
import { setPerformanceCSSStyles } from '../performance';
|
||||
import { aspectRatioToStyle, setOrRemoveAttribute } from '../utils/basic';
|
||||
import { View } from '../view/view';
|
||||
import { CardStyleAPI } from './types';
|
||||
@@ -69,10 +68,22 @@ export class StyleManager {
|
||||
}
|
||||
|
||||
public setPerformance(): void {
|
||||
setPerformanceCSSStyles(
|
||||
this._api.getCardElementManager().getElement(),
|
||||
this._api.getConfigManager().getCardWideConfig()?.performance,
|
||||
);
|
||||
const STYLE_DISABLE_MAP = {
|
||||
box_shadow: 'none',
|
||||
border_radius: '0px',
|
||||
};
|
||||
const element = this._api.getCardElementManager().getElement();
|
||||
const performance = this._api.getConfigManager().getCardWideConfig()?.performance;
|
||||
|
||||
const styles = performance?.style ?? {};
|
||||
for (const configKey of Object.keys(styles)) {
|
||||
const CSSKey = `--frigate-card-css-${configKey.replaceAll('_', '-')}`;
|
||||
if (styles[configKey] === false) {
|
||||
element.style.setProperty(CSSKey, STYLE_DISABLE_MAP[configKey]);
|
||||
} else {
|
||||
element.style.removeProperty(CSSKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected _isAspectRatioEnforced(
|
||||
|
||||
@@ -855,11 +855,7 @@ export class FrigateCardLiveProvider
|
||||
) {
|
||||
return 'webrtc-card';
|
||||
} else if (this.cameraConfig?.camera_entity) {
|
||||
if (this.cardWideConfig?.performance?.profile === 'low') {
|
||||
return 'image';
|
||||
} else {
|
||||
return 'ha';
|
||||
}
|
||||
} else if (this.cameraConfig?.frigate.camera_name) {
|
||||
return 'jsmpeg';
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
FrigateCardCondition,
|
||||
RawFrigateCardConfig,
|
||||
RawFrigateCardConfigArray,
|
||||
} from './config/types';
|
||||
} from './types';
|
||||
import {
|
||||
CONF_AUTOMATIONS,
|
||||
CONF_CAMERAS,
|
||||
@@ -22,14 +22,15 @@ import {
|
||||
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_EVENTS_MEDIA_TYPE,
|
||||
CONF_MENU_BUTTONS_CAMERA_UI,
|
||||
CONF_OVERRIDES,
|
||||
CONF_PROFILES,
|
||||
CONF_TIMELINE_EVENTS_MEDIA_TYPE,
|
||||
CONF_VIEW_INTERACTION_SECONDS,
|
||||
CONF_VIEW_TRIGGERS,
|
||||
CONF_VIEW_TRIGGERS_ACTIONS_TRIGGER,
|
||||
CONF_VIEW_TRIGGERS_ACTIONS_UNTRIGGER,
|
||||
CONF_VIEW_TRIGGERS_FILTER_SELECTED_CAMERA,
|
||||
} from './const';
|
||||
import { arrayify } from './utils/basic';
|
||||
} from '../const';
|
||||
import { arrayify } from '../utils/basic';
|
||||
|
||||
// *************************************************************************
|
||||
// General Config Management Functions
|
||||
@@ -684,4 +685,8 @@ const UPGRADES = [
|
||||
transform: (val) => (val === true ? { disable_except: 'substream' } : null),
|
||||
}),
|
||||
),
|
||||
upgradeMoveToWithOverrides('performance.profile', CONF_PROFILES, {
|
||||
// Delete the value if it's set to the default.
|
||||
transform: (val) => (val === 'low' ? ['low-performance'] : null),
|
||||
}),
|
||||
];
|
||||
@@ -0,0 +1,51 @@
|
||||
import { getConfigValue, setConfigValue } from '../management.js';
|
||||
import {
|
||||
ProfileType,
|
||||
RawFrigateCardConfig,
|
||||
frigateCardConfigSchema,
|
||||
} from '../types.js';
|
||||
import { deepRemoveDefaults } from '../../utils/zod.js';
|
||||
import { LOW_PERFORMANCE_PROFILE } from './low-performance.js';
|
||||
import { SCRUBBING_PROFILE } from './scrubbing.js';
|
||||
|
||||
const PROFILES = {
|
||||
'low-performance': LOW_PERFORMANCE_PROFILE,
|
||||
'scrubbing': SCRUBBING_PROFILE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a profile. Sets flags as defined in the relevant profile unless they are
|
||||
* explicitly overriden in the configuration.
|
||||
* @param inputConfig The raw unparsed input configuration.
|
||||
* @param outputConfig The output config to write to.
|
||||
* @returns A changed (in-place) parsed input configuration.
|
||||
*/
|
||||
export const setProfiles = <T extends RawFrigateCardConfig>(
|
||||
inputConfig: RawFrigateCardConfig,
|
||||
outputConfig: T,
|
||||
profiles?: ProfileType[],
|
||||
): T => {
|
||||
const defaultLessParseResult = deepRemoveDefaults(frigateCardConfigSchema).safeParse(
|
||||
inputConfig,
|
||||
);
|
||||
if (!defaultLessParseResult.success) {
|
||||
return outputConfig;
|
||||
}
|
||||
const defaultLessConfig = defaultLessParseResult.data;
|
||||
|
||||
const setIfNotSpecified = (key: string, value: unknown) => {
|
||||
if (getConfigValue(defaultLessConfig, key) === undefined) {
|
||||
setConfigValue(outputConfig, key, value);
|
||||
}
|
||||
};
|
||||
|
||||
for (const profile of profiles ?? []) {
|
||||
if (profile in PROFILES) {
|
||||
Object.entries(PROFILES[profile]).forEach(([k, v]: [string, unknown]) =>
|
||||
setIfNotSpecified(k, v),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return outputConfig;
|
||||
};
|
||||
@@ -1,11 +1,6 @@
|
||||
import { getConfigValue, setConfigValue } from './config-mgmt.js';
|
||||
import {
|
||||
PerformanceConfig,
|
||||
RawFrigateCardConfig,
|
||||
frigateCardConfigSchema,
|
||||
} from './config/types.js';
|
||||
import {
|
||||
CONF_CAMERAS_GLOBAL_IMAGE_REFRESH_SECONDS,
|
||||
CONF_CAMERAS_GLOBAL_LIVE_PROVIDER,
|
||||
CONF_CAMERAS_GLOBAL_TRIGGERS_OCCUPANCY,
|
||||
CONF_LIVE_AUTO_MUTE,
|
||||
CONF_LIVE_CONTROLS_THUMBNAILS_MODE,
|
||||
@@ -51,13 +46,9 @@ import {
|
||||
CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_FAVORITE_CONTROL,
|
||||
CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL,
|
||||
CONF_TIMELINE_SHOW_RECORDINGS,
|
||||
} from './const.js';
|
||||
import { deepRemoveDefaults } from './utils/zod.js';
|
||||
} from '../../const.js';
|
||||
|
||||
// Caution: These values are applied after parsing (since we cannot know the
|
||||
// performance profile until afterwards), so there is no validation on these
|
||||
// defaults.
|
||||
const LOW_PROFILE_DEFAULTS = {
|
||||
export const LOW_PERFORMANCE_PROFILE = {
|
||||
// Disable thumbnail carousels.
|
||||
[CONF_LIVE_CONTROLS_THUMBNAILS_MODE]: 'none' as const,
|
||||
[CONF_MEDIA_VIEWER_CONTROLS_THUMBNAILS_MODE]: 'none' as const,
|
||||
@@ -138,68 +129,9 @@ const LOW_PROFILE_DEFAULTS = {
|
||||
[CONF_MEDIA_VIEWER_SNAPSHOT_CLICK_PLAYS_CLIP]: false,
|
||||
|
||||
[CONF_CAMERAS_GLOBAL_TRIGGERS_OCCUPANCY]: false,
|
||||
[CONF_CAMERAS_GLOBAL_LIVE_PROVIDER]: 'image',
|
||||
|
||||
// Refresh the live camera image every 10 seconds (same as stock Home
|
||||
// Assistant Picture Glance).
|
||||
[CONF_CAMERAS_GLOBAL_IMAGE_REFRESH_SECONDS]: 10,
|
||||
};
|
||||
|
||||
/**
|
||||
* Set low performance profile mode. Sets flags as defined in
|
||||
* LOW_PROFILE_DEFAULTS unless they are explicitly overriden in the
|
||||
* configuration.
|
||||
* @param inputConfig The raw unparsed input configuration.
|
||||
* @param outputConfig The output config to write to.
|
||||
* @returns A changed (in-place) parsed input configuration.
|
||||
*/
|
||||
export const setLowPerformanceProfile = <T extends RawFrigateCardConfig>(
|
||||
inputConfig: RawFrigateCardConfig,
|
||||
outputConfig: T,
|
||||
): T => {
|
||||
const setIfNotSpecified = (
|
||||
defaultLessConfig: RawFrigateCardConfig,
|
||||
outputConfig: T,
|
||||
key: string,
|
||||
value: unknown,
|
||||
) => {
|
||||
if (getConfigValue(defaultLessConfig, key) === undefined) {
|
||||
setConfigValue(outputConfig, key, value);
|
||||
}
|
||||
};
|
||||
|
||||
const defaultLessParseResult = deepRemoveDefaults(frigateCardConfigSchema).safeParse(
|
||||
inputConfig,
|
||||
);
|
||||
if (defaultLessParseResult.success) {
|
||||
const defaultLessConfig = defaultLessParseResult.data;
|
||||
Object.entries(LOW_PROFILE_DEFAULTS).forEach(([k, v]: [string, unknown]) =>
|
||||
setIfNotSpecified(defaultLessConfig, outputConfig, k, v),
|
||||
);
|
||||
}
|
||||
return outputConfig;
|
||||
};
|
||||
|
||||
const STYLE_DISABLE_MAP = {
|
||||
box_shadow: 'none',
|
||||
border_radius: '0px',
|
||||
};
|
||||
|
||||
/**
|
||||
* Set card-wide CSS variables for performance.
|
||||
* @param element The element to set the variables on.
|
||||
* @param performance The performance configuration.
|
||||
*/
|
||||
export const setPerformanceCSSStyles = (
|
||||
element: HTMLElement,
|
||||
performance?: PerformanceConfig,
|
||||
): void => {
|
||||
const styles = performance?.style ?? {};
|
||||
for (const configKey of Object.keys(styles)) {
|
||||
const CSSKey = `--frigate-card-css-${configKey.replaceAll('_', '-')}`;
|
||||
if (styles[configKey] === false) {
|
||||
element.style.setProperty(CSSKey, STYLE_DISABLE_MAP[configKey]);
|
||||
} else {
|
||||
element.style.removeProperty(CSSKey);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
import {
|
||||
CONF_LIVE_CONTROLS_TIMELINE_MODE,
|
||||
CONF_LIVE_CONTROLS_TIMELINE_PAN_MODE,
|
||||
CONF_LIVE_CONTROLS_TIMELINE_STYLE,
|
||||
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MODE,
|
||||
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_PAN_MODE,
|
||||
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_STYLE,
|
||||
} from '../../const.js';
|
||||
|
||||
export const SCRUBBING_PROFILE = {
|
||||
[CONF_LIVE_CONTROLS_TIMELINE_MODE]: 'below' as const,
|
||||
[CONF_LIVE_CONTROLS_TIMELINE_STYLE]: 'ribbon' as const,
|
||||
[CONF_LIVE_CONTROLS_TIMELINE_PAN_MODE]: 'seek' as const,
|
||||
|
||||
[CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_MODE]: 'below' as const,
|
||||
[CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_STYLE]: 'ribbon' as const,
|
||||
[CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_PAN_MODE]: 'seek' as const,
|
||||
};
|
||||
+9
-2
@@ -1623,7 +1623,6 @@ export type Automations = z.infer<typeof automationsSchema>;
|
||||
// *************************************************************************
|
||||
|
||||
const performanceConfigDefault = {
|
||||
profile: 'high' as const,
|
||||
features: {
|
||||
animated_progress_indicator: true,
|
||||
media_chunk_size: MEDIA_CHUNK_SIZE_DEFAULT,
|
||||
@@ -1636,7 +1635,6 @@ const performanceConfigDefault = {
|
||||
|
||||
export const performanceConfigSchema = z
|
||||
.object({
|
||||
profile: z.enum(['low', 'high']).default(performanceConfigDefault.profile),
|
||||
features: z
|
||||
.object({
|
||||
animated_progress_indicator: z
|
||||
@@ -1679,6 +1677,13 @@ export interface CardWideConfig {
|
||||
debug?: DebugConfig;
|
||||
}
|
||||
|
||||
// *************************************************************************
|
||||
// *** Profile Configuration ***
|
||||
// *************************************************************************
|
||||
const PROFILES = ['low-performance', 'scrubbing'] as const;
|
||||
export type ProfileType = (typeof PROFILES)[number];
|
||||
export const profilesSchema = z.enum(PROFILES).array().optional();
|
||||
|
||||
// *************************************************************************
|
||||
// *** Card Configuration ***
|
||||
// *************************************************************************
|
||||
@@ -1705,6 +1710,8 @@ export const frigateCardConfigSchema = z.object({
|
||||
debug: debugConfigSchema,
|
||||
automations: automationsSchema,
|
||||
|
||||
profiles: profilesSchema,
|
||||
|
||||
// Configuration overrides.
|
||||
overrides: overridesSchema,
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ export const CONF_CAMERAS_ARRAY_TRIGGERS_EVENTS =
|
||||
|
||||
const CONF_CAMERAS_GLOBAL = 'cameras_global' as const;
|
||||
export const CONF_CAMERAS_GLOBAL_IMAGE = `${CONF_CAMERAS_GLOBAL}.image` as const;
|
||||
export const CONF_CAMERAS_GLOBAL_LIVE_PROVIDER =
|
||||
`${CONF_CAMERAS_GLOBAL}.live_provider` as const;
|
||||
export const CONF_CAMERAS_GLOBAL_JSMPEG = `${CONF_CAMERAS_GLOBAL}.jsmpeg` as const;
|
||||
export const CONF_CAMERAS_GLOBAL_WEBRTC_CARD =
|
||||
`${CONF_CAMERAS_GLOBAL}.webrtc_card` as const;
|
||||
@@ -313,6 +315,8 @@ export const CONF_PERFORMANCE_PROFILE = `${CONF_PERFORMANCE}.profile`;
|
||||
export const CONF_PERFORMANCE_STYLE_BOX_SHADOW = `${CONF_PERFORMANCE}.style.box_shadow`;
|
||||
export const CONF_PERFORMANCE_STYLE_BORDER_RADIUS = `${CONF_PERFORMANCE}.style.border_radius`;
|
||||
|
||||
export const CONF_PROFILES = 'profiles' as const;
|
||||
|
||||
// Taken from https://github.dev/home-assistant/frontend/blob/b5861869e39290fd2e15737e89571dfc543b3ad3/src/data/media-player.ts#L93
|
||||
export const MEDIA_PLAYER_SUPPORT_BROWSE_MEDIA = 131072;
|
||||
|
||||
|
||||
+33
-26
@@ -19,21 +19,24 @@ import {
|
||||
isConfigUpgradeable,
|
||||
setConfigValue,
|
||||
upgradeConfig,
|
||||
} from './config-mgmt.js';
|
||||
} from './config/management.js';
|
||||
import { setProfiles } from './config/profiles/index.js';
|
||||
import {
|
||||
BUTTON_SIZE_MIN,
|
||||
FrigateCardConfig,
|
||||
frigateCardConfigDefaults,
|
||||
FRIGATE_MENU_PRIORITY_MAX,
|
||||
profilesSchema,
|
||||
RawFrigateCardConfig,
|
||||
RawFrigateCardConfigArray,
|
||||
THUMBNAIL_WIDTH_MAX,
|
||||
THUMBNAIL_WIDTH_MIN,
|
||||
} from './config/types.js';
|
||||
import {
|
||||
CONF_CAMERAS,
|
||||
CONF_CAMERAS_ARRAY_CAMERA_ENTITY,
|
||||
CONF_CAMERAS_ARRAY_CAPABILITIES_DISABLE_EXCEPT,
|
||||
CONF_CAMERAS_ARRAY_CAPABILITIES_DISABLE,
|
||||
CONF_CAMERAS_ARRAY_CAPABILITIES_DISABLE_EXCEPT,
|
||||
CONF_CAMERAS_ARRAY_CAST_DASHBOARD_DASHBOARD_PATH,
|
||||
CONF_CAMERAS_ARRAY_CAST_DASHBOARD_VIEW_PATH,
|
||||
CONF_CAMERAS_ARRAY_CAST_METHOD,
|
||||
@@ -67,9 +70,8 @@ import {
|
||||
CONF_CAMERAS_ARRAY_TRIGGERS_OCCUPANCY,
|
||||
CONF_CAMERAS_ARRAY_WEBRTC_CARD_ENTITY,
|
||||
CONF_CAMERAS_ARRAY_WEBRTC_CARD_URL,
|
||||
CONF_CAMERAS,
|
||||
CONF_DIMENSIONS_ASPECT_RATIO_MODE,
|
||||
CONF_DIMENSIONS_ASPECT_RATIO,
|
||||
CONF_DIMENSIONS_ASPECT_RATIO_MODE,
|
||||
CONF_DIMENSIONS_MAX_HEIGHT,
|
||||
CONF_DIMENSIONS_MIN_HEIGHT,
|
||||
CONF_IMAGE_MODE,
|
||||
@@ -158,8 +160,8 @@ import {
|
||||
CONF_MEDIA_VIEWER_TRANSITION_EFFECT,
|
||||
CONF_MEDIA_VIEWER_ZOOMABLE,
|
||||
CONF_MENU_ALIGNMENT,
|
||||
CONF_MENU_BUTTON_SIZE,
|
||||
CONF_MENU_BUTTONS,
|
||||
CONF_MENU_BUTTON_SIZE,
|
||||
CONF_MENU_POSITION,
|
||||
CONF_MENU_STYLE,
|
||||
CONF_PERFORMANCE_FEATURES_ANIMATED_PROGRESS_INDICATOR,
|
||||
@@ -167,6 +169,7 @@ import {
|
||||
CONF_PERFORMANCE_PROFILE,
|
||||
CONF_PERFORMANCE_STYLE_BORDER_RADIUS,
|
||||
CONF_PERFORMANCE_STYLE_BOX_SHADOW,
|
||||
CONF_PROFILES,
|
||||
CONF_TIMELINE_CLUSTERING_THRESHOLD,
|
||||
CONF_TIMELINE_CONTROLS_THUMBNAILS_MODE,
|
||||
CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_DETAILS,
|
||||
@@ -183,21 +186,20 @@ import {
|
||||
CONF_VIEW_DEFAULT,
|
||||
CONF_VIEW_INTERACTION_SECONDS,
|
||||
CONF_VIEW_RESET_AFTER_INTERACTION,
|
||||
CONF_VIEW_TRIGGERS,
|
||||
CONF_VIEW_TRIGGERS_ACTIONS,
|
||||
CONF_VIEW_TRIGGERS_ACTIONS_INTERACTION_MODE,
|
||||
CONF_VIEW_TRIGGERS_ACTIONS_TRIGGER,
|
||||
CONF_VIEW_TRIGGERS_ACTIONS_UNTRIGGER,
|
||||
CONF_VIEW_TRIGGERS_ACTIONS,
|
||||
CONF_VIEW_TRIGGERS_FILTER_SELECTED_CAMERA,
|
||||
CONF_VIEW_TRIGGERS_SHOW_TRIGGER_STATUS,
|
||||
CONF_VIEW_TRIGGERS_UNTRIGGER_SECONDS,
|
||||
CONF_VIEW_TRIGGERS,
|
||||
CONF_VIEW_UPDATE_CYCLE_CAMERA,
|
||||
CONF_VIEW_UPDATE_FORCE,
|
||||
CONF_VIEW_UPDATE_SECONDS,
|
||||
MEDIA_CHUNK_SIZE_MAX,
|
||||
} from './const.js';
|
||||
import { localize } from './localize/localize.js';
|
||||
import { setLowPerformanceProfile } from './performance.js';
|
||||
import frigate_card_editor_style from './scss/editor.scss';
|
||||
import { arrayMove, prettifyTitle } from './utils/basic.js';
|
||||
import { getCameraID } from './utils/camera.js';
|
||||
@@ -315,6 +317,11 @@ const options: EditorOptions = {
|
||||
name: localize('editor.performance'),
|
||||
secondary: localize('editor.performance_secondary'),
|
||||
},
|
||||
profiles: {
|
||||
icon: 'folder-wrench-outline',
|
||||
name: localize('editor.profiles'),
|
||||
secondary: localize('editor.profiles_secondary'),
|
||||
},
|
||||
overrides: {
|
||||
icon: 'file-replace',
|
||||
name: localize('editor.overrides'),
|
||||
@@ -589,10 +596,10 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
{ value: 'below', label: localize('config.common.controls.timeline.modes.below') },
|
||||
];
|
||||
|
||||
protected _performanceProfiles: EditorSelectOption[] = [
|
||||
protected _profiles: EditorSelectOption[] = [
|
||||
{ value: '', label: '' },
|
||||
{ value: 'low', label: localize('config.performance.profiles.low') },
|
||||
{ value: 'high', label: localize('config.performance.profiles.high') },
|
||||
{ value: 'low-performance', label: localize('config.profiles.low-performance') },
|
||||
{ value: 'scrubbing', label: localize('config.profiles.scrubbing') },
|
||||
];
|
||||
|
||||
protected _go2rtcModes: EditorSelectOption[] = [
|
||||
@@ -788,25 +795,20 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
];
|
||||
|
||||
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 full configuration, so it may be
|
||||
// partially or completely invalid. It's more useful to have a partially
|
||||
// valid configuration here, to allow the user to fix the broken parts. As
|
||||
// such, RawFrigateCardConfig is used as the type.
|
||||
this._config = config;
|
||||
this._configUpgradeable = isConfigUpgradeable(config);
|
||||
|
||||
let unvalidatedProfile: string | null = null;
|
||||
try {
|
||||
// this._config may not be a valid FrigateCardConfig as it has not been
|
||||
// parsed. Attempt to pull out the performance profile.
|
||||
unvalidatedProfile = (this._config as FrigateCardConfig).performance?.profile;
|
||||
} catch (_) {}
|
||||
const profiles = profilesSchema.safeParse(
|
||||
(this._config as FrigateCardConfig).profiles,
|
||||
);
|
||||
|
||||
if (unvalidatedProfile === 'high' || unvalidatedProfile === 'low') {
|
||||
if (profiles.success) {
|
||||
const defaults = copyConfig(frigateCardConfigDefaults);
|
||||
if (unvalidatedProfile === 'low') {
|
||||
setLowPerformanceProfile(this._config, defaults);
|
||||
}
|
||||
setProfiles(this._config, defaults, profiles.data);
|
||||
this._defaults = defaults;
|
||||
}
|
||||
}
|
||||
@@ -2130,6 +2132,15 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
${this._renderOptionSetHeader('profiles')}
|
||||
${this._expandedMenus[MENU_OPTIONS] === 'profiles'
|
||||
? html` <div class="values">
|
||||
${this._renderOptionSelector(CONF_PROFILES, this._profiles, {
|
||||
multiple: true,
|
||||
label: localize('config.profiles.editor_label'),
|
||||
})}
|
||||
</div>`
|
||||
: ''}
|
||||
${this._renderOptionSetHeader('view')}
|
||||
${this._expandedMenus[MENU_OPTIONS] === 'view'
|
||||
? html`
|
||||
@@ -2556,10 +2567,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
${getConfigValue(this._config, CONF_PERFORMANCE_PROFILE) === 'low'
|
||||
? this._renderInfo(localize('config.performance.warning'))
|
||||
: html``}
|
||||
${this._renderOptionSelector(
|
||||
CONF_PERFORMANCE_PROFILE,
|
||||
this._performanceProfiles,
|
||||
)}
|
||||
${this._putInSubmenu(
|
||||
MENU_PERFORMANCE_FEATURES,
|
||||
true,
|
||||
|
||||
@@ -401,11 +401,6 @@
|
||||
"editor_label": "Opcions de característiques",
|
||||
"media_chunk_size": "Mida del fragment multimèdia"
|
||||
},
|
||||
"profile": "Perfil de rendiment",
|
||||
"profiles": {
|
||||
"high": "Alt rendiment",
|
||||
"low": "Baix rendiment"
|
||||
},
|
||||
"style": {
|
||||
"border_radius": "Corbes",
|
||||
"box_shadow": "Ombres",
|
||||
@@ -413,6 +408,11 @@
|
||||
},
|
||||
"warning": "Aquesta targeta està en mode de perfil baix, de manera que els valors predeterminats han canviat per optimitzar el rendiment"
|
||||
},
|
||||
"profiles": {
|
||||
"editor_label": "",
|
||||
"low-performance": "",
|
||||
"scrubbing": ""
|
||||
},
|
||||
"view": {
|
||||
"camera_select": "Visualitza les càmeres seleccionades recentment",
|
||||
"dark_mode": "Mode fosc",
|
||||
@@ -497,6 +497,8 @@
|
||||
"overrides_secondary": "S'han detectat substitucions de configuració dinàmica",
|
||||
"performance": "Rendiment",
|
||||
"performance_secondary": "Opcions de rendiment de la targeta",
|
||||
"profiles": "",
|
||||
"profiles_secondary": "",
|
||||
"timeline": "Cronologia",
|
||||
"timeline_secondary": "Opcions de la cronologia d'esdeveniments",
|
||||
"upgrade": "Upgrade",
|
||||
|
||||
@@ -401,11 +401,6 @@
|
||||
"editor_label": "Feature Options",
|
||||
"media_chunk_size": "Media chunk size"
|
||||
},
|
||||
"profile": "Performance profile",
|
||||
"profiles": {
|
||||
"high": "High/full performance",
|
||||
"low": "Low performance"
|
||||
},
|
||||
"style": {
|
||||
"border_radius": "Curves",
|
||||
"box_shadow": "Shadows",
|
||||
@@ -413,6 +408,11 @@
|
||||
},
|
||||
"warning": "This card is in low profile mode so defaults have changed to optimize performance"
|
||||
},
|
||||
"profiles": {
|
||||
"editor_label": "Configuration profiles",
|
||||
"low-performance": "Low performance",
|
||||
"scrubbing": "Video scrubbing"
|
||||
},
|
||||
"view": {
|
||||
"camera_select": "View for newly selected cameras",
|
||||
"dark_mode": "Dark mode",
|
||||
@@ -497,6 +497,8 @@
|
||||
"overrides_secondary": "Dynamic configuration overrides detected",
|
||||
"performance": "Performance",
|
||||
"performance_secondary": "Card performance options",
|
||||
"profiles": "Configuration profiles",
|
||||
"profiles_secondary": "Choose pre-configured sets of defaults",
|
||||
"timeline": "Timeline",
|
||||
"timeline_secondary": "Event timeline options",
|
||||
"upgrade": "Upgrade",
|
||||
|
||||
@@ -401,11 +401,6 @@
|
||||
"editor_label": "Options de fonctionnalités",
|
||||
"media_chunk_size": "Taille du morceau de média"
|
||||
},
|
||||
"profile": "Profil de performances",
|
||||
"profiles": {
|
||||
"high": "Performances élevées",
|
||||
"low": "Performances faibles"
|
||||
},
|
||||
"style": {
|
||||
"border_radius": "Courbes",
|
||||
"box_shadow": "Ombres",
|
||||
@@ -413,6 +408,11 @@
|
||||
},
|
||||
"warning": "Cette carte est en mode profil bas, les paramètres par défaut ont donc été modifiés pour optimiser les performances."
|
||||
},
|
||||
"profiles": {
|
||||
"editor_label": "",
|
||||
"low-performance": "",
|
||||
"scrubbing": ""
|
||||
},
|
||||
"view": {
|
||||
"camera_select": "Afficher les caméras nouvellement sélectionnées",
|
||||
"dark_mode": "Mode sombre",
|
||||
@@ -497,6 +497,8 @@
|
||||
"overrides_secondary": "Remplacements de configuration dynamique détectés",
|
||||
"performance": "Performance",
|
||||
"performance_secondary": "Options de performances de la carte",
|
||||
"profiles": "",
|
||||
"profiles_secondary": "",
|
||||
"timeline": "Chronologie",
|
||||
"timeline_secondary": "Options de chronologie des événements",
|
||||
"upgrade": "Mise à niveau",
|
||||
|
||||
@@ -401,11 +401,6 @@
|
||||
"editor_label": "Opzioni funzionalità",
|
||||
"media_chunk_size": "Dimensione del blocco multimediale"
|
||||
},
|
||||
"profile": "Profilo delle prestazioni",
|
||||
"profiles": {
|
||||
"high": "Prestazioni alte",
|
||||
"low": "Prestazioni basse"
|
||||
},
|
||||
"style": {
|
||||
"border_radius": "Curve",
|
||||
"box_shadow": "Ombre",
|
||||
@@ -413,6 +408,11 @@
|
||||
},
|
||||
"warning": "Questa scheda è in modalità basso profilo, quindi le impostazioni predefinite sono state modificate per ottimizzare le prestazioni"
|
||||
},
|
||||
"profiles": {
|
||||
"editor_label": "",
|
||||
"low-performance": "",
|
||||
"scrubbing": ""
|
||||
},
|
||||
"view": {
|
||||
"camera_select": "Visualizza per le telecamere appena selezionate",
|
||||
"dark_mode": "Tema scuro",
|
||||
@@ -497,6 +497,8 @@
|
||||
"overrides_secondary": "Rilevate sovrascritture della configurazione dinamica",
|
||||
"performance": "",
|
||||
"performance_secondary": "",
|
||||
"profiles": "",
|
||||
"profiles_secondary": "",
|
||||
"timeline": "Timeline",
|
||||
"timeline_secondary": "Opzioni della timeline degli eventi",
|
||||
"upgrade": "Aggiornamento",
|
||||
|
||||
@@ -401,11 +401,6 @@
|
||||
"editor_label": "Opções de recursos",
|
||||
"media_chunk_size": "Tamanho do bloco de mídia"
|
||||
},
|
||||
"profile": "Perfil de desempenho",
|
||||
"profiles": {
|
||||
"high": "Alto desempenho/completo",
|
||||
"low": "Baixo desempenho"
|
||||
},
|
||||
"style": {
|
||||
"border_radius": "Curvas",
|
||||
"box_shadow": "Sombras",
|
||||
@@ -413,6 +408,11 @@
|
||||
},
|
||||
"warning": "Este cartão está no modo de baixo desempenho, então os padrões foram alterados para otimizar o desempenho"
|
||||
},
|
||||
"profiles": {
|
||||
"editor_label": "",
|
||||
"low-performance": "",
|
||||
"scrubbing": ""
|
||||
},
|
||||
"view": {
|
||||
"camera_select": "Visualização de câmeras recém-selecionadas",
|
||||
"dark_mode": "Modo escuro",
|
||||
@@ -497,6 +497,8 @@
|
||||
"overrides_secondary": "Substituições de configuração dinâmica detectadas",
|
||||
"performance": "Desempenho",
|
||||
"performance_secondary": "Opções de desempenho do cartão",
|
||||
"profiles": "",
|
||||
"profiles_secondary": "",
|
||||
"timeline": "Linha do tempo",
|
||||
"timeline_secondary": "Opções do evento da linha do tempo",
|
||||
"upgrade": "Upgrade",
|
||||
|
||||
@@ -401,11 +401,6 @@
|
||||
"editor_label": "Editor de etiquetas",
|
||||
"media_chunk_size": "Tamanho do ficheiro"
|
||||
},
|
||||
"profile": "Perfil",
|
||||
"profiles": {
|
||||
"high": "Alto",
|
||||
"low": "Baixo"
|
||||
},
|
||||
"style": {
|
||||
"border_radius": "Tamanho do bordo",
|
||||
"box_shadow": "Caixa de Fundo",
|
||||
@@ -413,6 +408,11 @@
|
||||
},
|
||||
"warning": "Avisos"
|
||||
},
|
||||
"profiles": {
|
||||
"editor_label": "",
|
||||
"low-performance": "",
|
||||
"scrubbing": ""
|
||||
},
|
||||
"view": {
|
||||
"camera_select": "Visualização de câmeras recém-selecionadas",
|
||||
"dark_mode": "Modo escuro",
|
||||
@@ -497,6 +497,8 @@
|
||||
"overrides_secondary": "Substituições de configuração dinâmica detectadas",
|
||||
"performance": "",
|
||||
"performance_secondary": "",
|
||||
"profiles": "",
|
||||
"profiles_secondary": "",
|
||||
"timeline": "Linha do tempo",
|
||||
"timeline_secondary": "Opções do evento da linha do tempo",
|
||||
"upgrade": "Actualização",
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('ConfigManager', () => {
|
||||
|
||||
manager.setConfig(config);
|
||||
|
||||
expect(manager.hasConfig()).toBeTruthy()
|
||||
expect(manager.hasConfig()).toBeTruthy();
|
||||
expect(manager.getRawConfig()).toBe(config);
|
||||
|
||||
// Verify at least the camera is set.
|
||||
@@ -102,12 +102,12 @@ describe('ConfigManager', () => {
|
||||
expect(api.getCardElementManager().update).toBeCalled();
|
||||
});
|
||||
|
||||
it('should apply low performance defaults', () => {
|
||||
it('should apply profiles', () => {
|
||||
const manager = new ConfigManager(createCardAPI());
|
||||
const config = {
|
||||
type: 'custom:frigate-card',
|
||||
cameras: [{ camera_entity: 'camera.office' }],
|
||||
performance: { profile: 'low' },
|
||||
profiles: ['low-performance'],
|
||||
};
|
||||
|
||||
manager.setConfig(config);
|
||||
@@ -143,7 +143,9 @@ describe('ConfigManager', () => {
|
||||
logging: true,
|
||||
},
|
||||
performance: {
|
||||
profile: 'low',
|
||||
style: {
|
||||
box_shadow: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -155,12 +157,11 @@ describe('ConfigManager', () => {
|
||||
},
|
||||
performance: {
|
||||
features: {
|
||||
animated_progress_indicator: false,
|
||||
media_chunk_size: 10,
|
||||
animated_progress_indicator: true,
|
||||
media_chunk_size: 50,
|
||||
},
|
||||
profile: 'low',
|
||||
style: {
|
||||
border_radius: false,
|
||||
border_radius: true,
|
||||
box_shadow: false,
|
||||
},
|
||||
},
|
||||
@@ -257,8 +258,8 @@ describe('ConfigManager', () => {
|
||||
const config_2 = {
|
||||
...config_1,
|
||||
cameras_global: {
|
||||
live_provider: 'jsmpeg'
|
||||
}
|
||||
live_provider: 'jsmpeg',
|
||||
},
|
||||
};
|
||||
vi.mocked(getOverriddenConfig).mockReturnValue(createConfig(config_2));
|
||||
manager.computeOverrideConfig();
|
||||
@@ -276,9 +277,9 @@ describe('ConfigManager', () => {
|
||||
cameras: [{ camera_entity: 'camera.office' }],
|
||||
live: {
|
||||
microphone: {
|
||||
always_connected: false
|
||||
}
|
||||
}
|
||||
always_connected: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
vi.mocked(getOverriddenConfig).mockReturnValue(createConfig(config_1));
|
||||
|
||||
@@ -289,9 +290,9 @@ describe('ConfigManager', () => {
|
||||
...config_1,
|
||||
live: {
|
||||
microphone: {
|
||||
always_connected: true
|
||||
}
|
||||
}
|
||||
always_connected: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
vi.mocked(getOverriddenConfig).mockReturnValue(createConfig(config_2));
|
||||
manager.computeOverrideConfig();
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { FrigateCardView } from '../../src/config/types';
|
||||
import { setPerformanceCSSStyles } from '../../src/performance';
|
||||
import { StyleManager } from '../../src/card-controller/style-manager';
|
||||
import { createCardAPI, createConfig, createHASS, createView } from '../test-utils';
|
||||
|
||||
vi.mock('../../src/performance');
|
||||
|
||||
// @vitest-environment jsdom
|
||||
describe('StyleManager', () => {
|
||||
beforeEach(() => {
|
||||
@@ -226,19 +223,49 @@ describe('StyleManager', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('setPerformance', () => {
|
||||
describe('setPerformance', () => {
|
||||
it('no styles set', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
const config = createConfig();
|
||||
vi.mocked(api.getConfigManager().getCardWideConfig).mockReturnValue({
|
||||
performance: config.performance,
|
||||
});
|
||||
vi.mocked(api.getConfigManager().getCardWideConfig).mockReturnValue({});
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setPerformance();
|
||||
|
||||
expect(setPerformanceCSSStyles).toBeCalledWith(element, config.performance);
|
||||
expect(
|
||||
element.style.getPropertyValue('--frigate-card-css-box-shadow'),
|
||||
).toBeFalsy();
|
||||
expect(
|
||||
element.style.getPropertyValue('--frigate-card-css-border-radius'),
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('valid styles set', () => {
|
||||
const api = createCardAPI();
|
||||
const element = document.createElement('div');
|
||||
vi.mocked(api.getCardElementManager().getElement).mockReturnValue(element);
|
||||
vi.mocked(api.getConfigManager().getCardWideConfig).mockReturnValue(
|
||||
createConfig({
|
||||
performance: {
|
||||
style: {
|
||||
box_shadow: false,
|
||||
border_radius: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
const manager = new StyleManager(api);
|
||||
|
||||
manager.setPerformance();
|
||||
|
||||
expect(element.style.getPropertyValue('--frigate-card-css-box-shadow')).toEqual(
|
||||
'none',
|
||||
);
|
||||
expect(
|
||||
element.style.getPropertyValue('--frigate-card-css-border-radius'),
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAspectRatioStyle', () => {
|
||||
|
||||
@@ -16,8 +16,8 @@ import {
|
||||
upgradeMoveToWithOverrides,
|
||||
upgradeObjectRecursively,
|
||||
upgradeWithOverrides,
|
||||
} from '../src/config-mgmt';
|
||||
import { RawFrigateCardConfig } from '../src/config/types';
|
||||
} from '../../src/config/management';
|
||||
import { RawFrigateCardConfig } from '../../src/config/types';
|
||||
|
||||
describe('general functions', () => {
|
||||
it('should set value', () => {
|
||||
@@ -2459,6 +2459,43 @@ describe('should handle version specific upgrades', () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
describe('from performance profile to generic profile', () => {
|
||||
it('low performance', () => {
|
||||
const config = {
|
||||
type: 'custom:frigate-card',
|
||||
cameras: [],
|
||||
performance: {
|
||||
profile: 'low',
|
||||
},
|
||||
};
|
||||
|
||||
expect(upgradeConfig(config)).toBeTruthy();
|
||||
expect(config).toEqual({
|
||||
type: 'custom:frigate-card',
|
||||
cameras: [],
|
||||
profiles: ['low-performance'],
|
||||
performance: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('high performance', () => {
|
||||
const config = {
|
||||
type: 'custom:frigate-card',
|
||||
cameras: [],
|
||||
performance: {
|
||||
profile: 'high',
|
||||
},
|
||||
};
|
||||
|
||||
expect(upgradeConfig(config)).toBeTruthy();
|
||||
expect(config).toEqual({
|
||||
type: 'custom:frigate-card',
|
||||
cameras: [],
|
||||
performance: {},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { ProfileType } from '../../../src/config/types';
|
||||
import { setProfiles } from '../../../src/config/profiles';
|
||||
import { createConfig } from '../../test-utils';
|
||||
|
||||
describe('setProfiles', () => {
|
||||
it('should handle failed parse', () => {
|
||||
expect(setProfiles({ cameras: 'not_an_array' }, {})).toEqual({});
|
||||
});
|
||||
|
||||
it('should handle no profiles', () => {
|
||||
const input = createConfig();
|
||||
const output = createConfig();
|
||||
|
||||
expect(setProfiles(input, output)).toEqual(input);
|
||||
});
|
||||
|
||||
it('should handle invalid profiles', () => {
|
||||
const input = createConfig();
|
||||
const output = createConfig();
|
||||
|
||||
expect(setProfiles(input, output, ['bogus' as ProfileType])).toEqual(input);
|
||||
});
|
||||
|
||||
it('should handle profiles', () => {
|
||||
const input = {
|
||||
type: 'frigate-hass-card',
|
||||
cameras: [],
|
||||
live: {
|
||||
controls: {
|
||||
timeline: {
|
||||
// This will not be overridden.
|
||||
style: 'stack',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(setProfiles(input, {}, ['scrubbing'])).toEqual({
|
||||
live: {
|
||||
controls: {
|
||||
timeline: {
|
||||
mode: 'below',
|
||||
pan_mode: 'seek',
|
||||
},
|
||||
},
|
||||
},
|
||||
media_viewer: {
|
||||
controls: {
|
||||
timeline: {
|
||||
mode: 'below',
|
||||
style: 'ribbon',
|
||||
pan_mode: 'seek',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { expect, it } from 'vitest';
|
||||
import { LOW_PERFORMANCE_PROFILE } from '../../../src/config/profiles/low-performance';
|
||||
|
||||
it('low performance profile', () => {
|
||||
expect(LOW_PERFORMANCE_PROFILE).toEqual({
|
||||
'cameras_global.image.refresh_seconds': 10,
|
||||
'cameras_global.live_provider': 'image',
|
||||
'cameras_global.triggers.occupancy': false,
|
||||
'live.auto_mute': 'never',
|
||||
'live.controls.thumbnails.mode': 'none',
|
||||
'live.controls.thumbnails.show_details': false,
|
||||
'live.controls.thumbnails.show_download_control': false,
|
||||
'live.controls.thumbnails.show_favorite_control': false,
|
||||
'live.controls.thumbnails.show_timeline_control': false,
|
||||
'live.controls.timeline.show_recordings': false,
|
||||
'live.controls.title.mode': 'none',
|
||||
'live.draggable': false,
|
||||
'live.lazy_unload': 'all',
|
||||
'live.show_image_during_load': false,
|
||||
'live.transition_effect': 'none',
|
||||
'media_gallery.controls.thumbnails.show_details': false,
|
||||
'media_gallery.controls.thumbnails.show_download_control': false,
|
||||
'media_gallery.controls.thumbnails.show_favorite_control': false,
|
||||
'media_gallery.controls.thumbnails.show_timeline_control': false,
|
||||
'media_viewer.auto_mute': 'never',
|
||||
'media_viewer.auto_pause': 'never',
|
||||
'media_viewer.auto_play': 'never',
|
||||
'media_viewer.controls.next_previous.style': 'chevrons',
|
||||
'media_viewer.controls.thumbnails.mode': 'none',
|
||||
'media_viewer.controls.thumbnails.show_details': false,
|
||||
'media_viewer.controls.thumbnails.show_download_control': false,
|
||||
'media_viewer.controls.thumbnails.show_favorite_control': false,
|
||||
'media_viewer.controls.thumbnails.show_timeline_control': false,
|
||||
'media_viewer.controls.timeline.show_recordings': false,
|
||||
'media_viewer.controls.title.mode': 'none',
|
||||
'media_viewer.draggable': false,
|
||||
'media_viewer.snapshot_click_plays_clip': false,
|
||||
'media_viewer.transition_effect': 'none',
|
||||
'menu.buttons.frigate.enabled': false,
|
||||
'menu.buttons.media_player.enabled': false,
|
||||
'menu.buttons.timeline.enabled': false,
|
||||
'menu.style': 'outside',
|
||||
'performance.features.animated_progress_indicator': false,
|
||||
'performance.features.media_chunk_size': 10,
|
||||
'performance.style.border_radius': false,
|
||||
'performance.style.box_shadow': false,
|
||||
'timeline.controls.thumbnails.mode': 'none',
|
||||
'timeline.controls.thumbnails.show_details': false,
|
||||
'timeline.controls.thumbnails.show_download_control': false,
|
||||
'timeline.controls.thumbnails.show_favorite_control': false,
|
||||
'timeline.controls.thumbnails.show_timeline_control': false,
|
||||
'timeline.show_recordings': false,
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import { expect, it } from 'vitest';
|
||||
import { SCRUBBING_PROFILE } from '../../../src/config/profiles/scrubbing';
|
||||
|
||||
it('scrubbing profile', () => {
|
||||
expect(SCRUBBING_PROFILE).toEqual({
|
||||
'live.controls.timeline.mode': 'below',
|
||||
'live.controls.timeline.style': 'ribbon',
|
||||
'live.controls.timeline.pan_mode': 'seek',
|
||||
'media_viewer.controls.timeline.mode': 'below',
|
||||
'media_viewer.controls.timeline.style': 'ribbon',
|
||||
'media_viewer.controls.timeline.pan_mode': 'seek',
|
||||
});
|
||||
});
|
||||
@@ -253,7 +253,6 @@ describe('config defaults', () => {
|
||||
animated_progress_indicator: true,
|
||||
media_chunk_size: 50,
|
||||
},
|
||||
profile: 'high',
|
||||
style: {
|
||||
border_radius: true,
|
||||
box_shadow: true,
|
||||
|
||||
+1
-2
@@ -18,8 +18,7 @@ const FULL_COVERAGE_FILES_RELATIVE = [
|
||||
'components-lib/menu-controller.ts',
|
||||
'components-lib/ptz-controller.ts',
|
||||
'components-lib/zoom-controller.ts',
|
||||
'config-mgmt.ts',
|
||||
'config/types.ts',
|
||||
'config/**/*.ts',
|
||||
'const.ts',
|
||||
'types.ts',
|
||||
'utils/action.ts',
|
||||
|
||||
Reference in New Issue
Block a user