Add editor support for performance profile.

This commit is contained in:
Dermot Duffy
2022-10-08 10:13:32 -07:00
parent 3aadfd2252
commit b663772a52
7 changed files with 158 additions and 46 deletions
-3
View File
@@ -103,9 +103,6 @@ export class FrigateCardSurround extends LitElement {
?.evolve({ ?.evolve({
target: parent, target: parent,
childIndex: null, childIndex: null,
// Don't carry over history of this 'empty' view.
previous: null,
}) })
.dispatchChangeEvent(this); .dispatchChangeEvent(this);
} }
+1
View File
@@ -206,6 +206,7 @@ export const CONF_OVERRIDES = 'overrides' as const;
export const CONF_PERFORMANCE = 'performance' as const; export const CONF_PERFORMANCE = 'performance' as const;
export const CONF_PERFORMANCE_FEATURES_ANIMATED_PROGRESS_INDICATOR = `${CONF_PERFORMANCE}.features.animated_progress_indicator`; export const CONF_PERFORMANCE_FEATURES_ANIMATED_PROGRESS_INDICATOR = `${CONF_PERFORMANCE}.features.animated_progress_indicator`;
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_BOX_SHADOW = `${CONF_PERFORMANCE}.style.box_shadow`;
export const CONF_PERFORMANCE_STYLE_BORDER_RADIUS = `${CONF_PERFORMANCE}.style.border_radius`; export const CONF_PERFORMANCE_STYLE_BORDER_RADIUS = `${CONF_PERFORMANCE}.style.border_radius`;
+114 -25
View File
@@ -99,6 +99,10 @@ import {
CONF_MENU_BUTTON_SIZE, CONF_MENU_BUTTON_SIZE,
CONF_MENU_POSITION, CONF_MENU_POSITION,
CONF_MENU_STYLE, CONF_MENU_STYLE,
CONF_PERFORMANCE_FEATURES_ANIMATED_PROGRESS_INDICATOR,
CONF_PERFORMANCE_PROFILE,
CONF_PERFORMANCE_STYLE_BORDER_RADIUS,
CONF_PERFORMANCE_STYLE_BOX_SHADOW,
CONF_TIMELINE_CLUSTERING_THRESHOLD, CONF_TIMELINE_CLUSTERING_THRESHOLD,
CONF_TIMELINE_CONTROLS_THUMBNAILS_MODE, CONF_TIMELINE_CONTROLS_THUMBNAILS_MODE,
CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_DETAILS, CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_DETAILS,
@@ -125,6 +129,7 @@ import { localize } from './localize/localize.js';
import frigate_card_editor_style from './scss/editor.scss'; import frigate_card_editor_style from './scss/editor.scss';
import { import {
BUTTON_SIZE_MIN, BUTTON_SIZE_MIN,
FrigateCardConfig,
frigateCardConfigDefaults, frigateCardConfigDefaults,
FRIGATE_MENU_PRIORITY_MAX, FRIGATE_MENU_PRIORITY_MAX,
RawFrigateCardConfig, RawFrigateCardConfig,
@@ -136,6 +141,7 @@ import { arrayMove } from './utils/basic.js';
import { getCameraID, getCameraTitle } from './utils/camera.js'; import { getCameraID, getCameraTitle } from './utils/camera.js';
import { FRIGATE_ICON_SVG_PATH } from './utils/frigate.js'; import { FRIGATE_ICON_SVG_PATH } from './utils/frigate.js';
import { getEntitiesFromHASS, sideLoadHomeAssistantElements } from './utils/ha'; import { getEntitiesFromHASS, sideLoadHomeAssistantElements } from './utils/ha';
import { setLowPerformanceProfile } from './performance.js';
const MENU_BUTTONS = 'buttons'; const MENU_BUTTONS = 'buttons';
const MENU_CAMERAS = 'cameras'; const MENU_CAMERAS = 'cameras';
@@ -159,6 +165,8 @@ const MENU_MEDIA_VIEWER_CONTROLS_TITLE = 'media_viewer.controls.title';
const MENU_MEDIA_VIEWER_LAYOUT = 'media_viewer.layout'; const MENU_MEDIA_VIEWER_LAYOUT = 'media_viewer.layout';
const MENU_TIMELINE_CONTROLS_THUMBNAILS = 'timeline.controls.thumbnails'; const MENU_TIMELINE_CONTROLS_THUMBNAILS = 'timeline.controls.thumbnails';
const MENU_OPTIONS = 'options'; const MENU_OPTIONS = 'options';
const MENU_PERFORMANCE_FEATURES = 'performance.features';
const MENU_PERFORMANCE_STYLE = 'performance.style';
const MENU_VIEW_SCAN = 'scan'; const MENU_VIEW_SCAN = 'scan';
interface EditorOptionsSet { interface EditorOptionsSet {
@@ -226,6 +234,11 @@ const options: EditorOptions = {
name: localize('editor.dimensions'), name: localize('editor.dimensions'),
secondary: localize('editor.dimensions_secondary'), secondary: localize('editor.dimensions_secondary'),
}, },
performance: {
icon: 'speedometer',
name: localize('editor.performance'),
secondary: localize('editor.performance_secondary'),
},
overrides: { overrides: {
icon: 'file-replace', icon: 'file-replace',
name: localize('editor.overrides'), name: localize('editor.overrides'),
@@ -237,6 +250,8 @@ const options: EditorOptions = {
export class FrigateCardEditor extends LitElement implements LovelaceCardEditor { export class FrigateCardEditor extends LitElement implements LovelaceCardEditor {
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@state() protected _config?: RawFrigateCardConfig; @state() protected _config?: RawFrigateCardConfig;
@state() protected _defaults = structuredClone(frigateCardConfigDefaults);
protected _initialized = false; protected _initialized = false;
protected _configUpgradeable = false; protected _configUpgradeable = false;
@@ -442,6 +457,12 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
{ value: 'below', label: localize('config.common.controls.timeline.modes.below') }, { value: 'below', label: localize('config.common.controls.timeline.modes.below') },
]; ];
protected _performanceProfiles: EditorSelectOption[] = [
{ value: '', label: '' },
{ value: 'low', label: localize('config.performance.profiles.low') },
{ value: 'high', label: localize('config.performance.profiles.high') },
];
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
@@ -449,6 +470,21 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
// such, RawFrigateCardConfig is used as the type. // such, RawFrigateCardConfig is used as the type.
this._config = config; this._config = config;
this._configUpgradeable = isConfigUpgradeable(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 (_) {}
if (unvalidatedProfile === 'high' || unvalidatedProfile === 'low') {
const defaults = structuredClone(frigateCardConfigDefaults);
if (unvalidatedProfile === 'low') {
setLowPerformanceProfile(this._config, defaults);
}
this._defaults = defaults;
}
} }
/** /**
@@ -469,7 +505,10 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
* @param optionSetName The name of the EditorOptionsSet. * @param optionSetName The name of the EditorOptionsSet.
* @returns A rendered template. * @returns A rendered template.
*/ */
protected _renderOptionSetHeader(optionSetName: string): TemplateResult { protected _renderOptionSetHeader(
optionSetName: string,
titleClass?: string,
): TemplateResult {
const optionSet = options[optionSetName]; const optionSet = options[optionSetName];
return html` return html`
@@ -481,7 +520,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
> >
<div class="row"> <div class="row">
<ha-icon .icon=${`mdi:${optionSet.icon}`}></ha-icon> <ha-icon .icon=${`mdi:${optionSet.icon}`}></ha-icon>
<div class="title">${optionSet.name}</div> <div class="title ${titleClass ?? ''}">${optionSet.name}</div>
</div> </div>
<div class="secondary">${optionSet.secondary}</div> <div class="secondary">${optionSet.secondary}</div>
</div> </div>
@@ -673,24 +712,24 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
? html` <div class="values"> ? html` <div class="values">
${this._renderSwitch( ${this._renderSwitch(
CONF_VIEW_SCAN_ENABLED, CONF_VIEW_SCAN_ENABLED,
frigateCardConfigDefaults.view.scan.enabled, this._defaults.view.scan.enabled,
{ {
label: localize(`config.${CONF_VIEW_SCAN_ENABLED}`), label: localize(`config.${CONF_VIEW_SCAN_ENABLED}`),
}, },
)} )}
${this._renderSwitch( ${this._renderSwitch(
CONF_VIEW_SCAN_SHOW_TRIGGER_STATUS, CONF_VIEW_SCAN_SHOW_TRIGGER_STATUS,
frigateCardConfigDefaults.view.scan.show_trigger_status, this._defaults.view.scan.show_trigger_status,
{ {
label: localize(`config.${CONF_VIEW_SCAN_SHOW_TRIGGER_STATUS}`), label: localize(`config.${CONF_VIEW_SCAN_SHOW_TRIGGER_STATUS}`),
}, },
)} )}
${this._renderSwitch( ${this._renderSwitch(
CONF_VIEW_SCAN_UNTRIGGER_RESET, CONF_VIEW_SCAN_UNTRIGGER_RESET,
frigateCardConfigDefaults.view.scan.untrigger_reset, this._defaults.view.scan.untrigger_reset,
)} )}
${this._renderNumberInput(CONF_VIEW_SCAN_UNTRIGGER_SECONDS, { ${this._renderNumberInput(CONF_VIEW_SCAN_UNTRIGGER_SECONDS, {
default: frigateCardConfigDefaults.view.scan.untrigger_seconds, default: this._defaults.view.scan.untrigger_seconds,
})} })}
</div>` </div>`
: ''} : ''}
@@ -734,7 +773,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
? html` <div class="values"> ? html` <div class="values">
${this._renderSwitch( ${this._renderSwitch(
`${CONF_MENU_BUTTONS}.${button}.enabled`, `${CONF_MENU_BUTTONS}.${button}.enabled`,
frigateCardConfigDefaults.menu.buttons[button]?.enabled ?? true, this._defaults.menu.buttons[button]?.enabled ?? true,
{ {
label: localize('config.menu.buttons.enabled'), label: localize('config.menu.buttons.enabled'),
}, },
@@ -748,7 +787,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
)} )}
${this._renderNumberInput(`${CONF_MENU_BUTTONS}.${button}.priority`, { ${this._renderNumberInput(`${CONF_MENU_BUTTONS}.${button}.priority`, {
max: FRIGATE_MENU_PRIORITY_MAX, max: FRIGATE_MENU_PRIORITY_MAX,
default: frigateCardConfigDefaults.menu.buttons[button]?.priority, default: this._defaults.menu.buttons[button]?.priority,
label: localize('config.menu.buttons.priority'), label: localize('config.menu.buttons.priority'),
})} })}
${this._renderIconSelector(`${CONF_MENU_BUTTONS}.${button}.icon`, { ${this._renderIconSelector(`${CONF_MENU_BUTTONS}.${button}.icon`, {
@@ -886,6 +925,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
configPathClusteringThreshold: string, configPathClusteringThreshold: string,
configPathTimelineMedia: string, configPathTimelineMedia: string,
configPathShowRecordings: string, configPathShowRecordings: string,
showRecordingsDefault: boolean,
): TemplateResult | void { ): TemplateResult | void {
return this._putInSubmenu( return this._putInSubmenu(
domain, domain,
@@ -900,7 +940,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
configPathClusteringThreshold, configPathClusteringThreshold,
configPathTimelineMedia, configPathTimelineMedia,
configPathShowRecordings, configPathShowRecordings,
frigateCardConfigDefaults.mini_timeline.show_recordings, showRecordingsDefault,
)}`, )}`,
); );
} }
@@ -999,21 +1039,21 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
})} })}
${this._renderSwitch( ${this._renderSwitch(
configPathShowDetails, configPathShowDetails,
frigateCardConfigDefaults.live.controls.thumbnails.show_details, this._defaults.live.controls.thumbnails.show_details,
{ {
label: localize('config.common.controls.thumbnails.show_details'), label: localize('config.common.controls.thumbnails.show_details'),
}, },
)} )}
${this._renderSwitch( ${this._renderSwitch(
configPathShowFavoriteControl, configPathShowFavoriteControl,
frigateCardConfigDefaults.live.controls.thumbnails.show_favorite_control, this._defaults.live.controls.thumbnails.show_favorite_control,
{ {
label: localize('config.common.controls.thumbnails.show_favorite_control'), label: localize('config.common.controls.thumbnails.show_favorite_control'),
}, },
)} )}
${this._renderSwitch( ${this._renderSwitch(
configPathShowTimelineControl, configPathShowTimelineControl,
frigateCardConfigDefaults.live.controls.thumbnails.show_timeline_control, this._defaults.live.controls.thumbnails.show_timeline_control,
{ {
label: localize('config.common.controls.thumbnails.show_timeline_control'), label: localize('config.common.controls.thumbnails.show_timeline_control'),
}, },
@@ -1247,7 +1287,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_CAMERAS_ARRAY_DEPENDENCIES_ALL_CAMERAS, CONF_CAMERAS_ARRAY_DEPENDENCIES_ALL_CAMERAS,
cameraIndex, cameraIndex,
), ),
frigateCardConfigDefaults.cameras.dependencies.all_cameras, this._defaults.cameras.dependencies.all_cameras,
)} )}
${this._renderOptionSelector( ${this._renderOptionSelector(
getArrayConfigPath( getArrayConfigPath(
@@ -1267,11 +1307,11 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
{ name: 'mdi:magnify-scan' }, { name: 'mdi:magnify-scan' },
html` ${this._renderSwitch( html` ${this._renderSwitch(
getArrayConfigPath(CONF_CAMERAS_ARRAY_TRIGGERS_OCCUPANCY, cameraIndex), getArrayConfigPath(CONF_CAMERAS_ARRAY_TRIGGERS_OCCUPANCY, cameraIndex),
frigateCardConfigDefaults.cameras.triggers.occupancy, this._defaults.cameras.triggers.occupancy,
)} )}
${this._renderSwitch( ${this._renderSwitch(
getArrayConfigPath(CONF_CAMERAS_ARRAY_TRIGGERS_MOTION, cameraIndex), getArrayConfigPath(CONF_CAMERAS_ARRAY_TRIGGERS_MOTION, cameraIndex),
frigateCardConfigDefaults.cameras.triggers.motion, this._defaults.cameras.triggers.motion,
)} )}
${this._renderOptionSelector( ${this._renderOptionSelector(
getArrayConfigPath(CONF_CAMERAS_ARRAY_TRIGGERS_ENTITIES, cameraIndex), getArrayConfigPath(CONF_CAMERAS_ARRAY_TRIGGERS_ENTITIES, cameraIndex),
@@ -1381,7 +1421,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
return html``; return html``;
} }
const defaults = frigateCardConfigDefaults;
const entities = getEntitiesFromHASS(this.hass); const entities = getEntitiesFromHASS(this.hass);
const cameras = (getConfigValue(this._config, CONF_CAMERAS) || const cameras = (getConfigValue(this._config, CONF_CAMERAS) ||
[]) as RawFrigateCardConfigArray; []) as RawFrigateCardConfigArray;
@@ -1431,10 +1470,13 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
${this._renderOptionSelector(CONF_VIEW_DARK_MODE, this._darkModes)} ${this._renderOptionSelector(CONF_VIEW_DARK_MODE, this._darkModes)}
${this._renderNumberInput(CONF_VIEW_TIMEOUT_SECONDS)} ${this._renderNumberInput(CONF_VIEW_TIMEOUT_SECONDS)}
${this._renderNumberInput(CONF_VIEW_UPDATE_SECONDS)} ${this._renderNumberInput(CONF_VIEW_UPDATE_SECONDS)}
${this._renderSwitch(CONF_VIEW_UPDATE_FORCE, defaults.view.update_force)} ${this._renderSwitch(
CONF_VIEW_UPDATE_FORCE,
this._defaults.view.update_force,
)}
${this._renderSwitch( ${this._renderSwitch(
CONF_VIEW_UPDATE_CYCLE_CAMERA, CONF_VIEW_UPDATE_CYCLE_CAMERA,
defaults.view.update_cycle_camera, this._defaults.view.update_cycle_camera,
)} )}
${this._renderViewScanMenu()} ${this._renderViewScanMenu()}
</div> </div>
@@ -1469,9 +1511,9 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
${this._expandedMenus[MENU_OPTIONS] === 'live' ${this._expandedMenus[MENU_OPTIONS] === 'live'
? html` ? html`
<div class="values"> <div class="values">
${this._renderSwitch(CONF_LIVE_PRELOAD, defaults.live.preload)} ${this._renderSwitch(CONF_LIVE_PRELOAD, this._defaults.live.preload)}
${this._renderSwitch(CONF_LIVE_DRAGGABLE, defaults.live.draggable)} ${this._renderSwitch(CONF_LIVE_DRAGGABLE, this._defaults.live.draggable)}
${this._renderSwitch(CONF_LIVE_LAZY_LOAD, defaults.live.lazy_load)} ${this._renderSwitch(CONF_LIVE_LAZY_LOAD, this._defaults.live.lazy_load)}
${this._renderOptionSelector( ${this._renderOptionSelector(
CONF_LIVE_LAZY_UNLOAD, CONF_LIVE_LAZY_UNLOAD,
this._mediaActionNegativeConditions, this._mediaActionNegativeConditions,
@@ -1498,7 +1540,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
)} )}
${this._renderSwitch( ${this._renderSwitch(
CONF_LIVE_SHOW_IMAGE_DURING_LOAD, CONF_LIVE_SHOW_IMAGE_DURING_LOAD,
defaults.live.show_image_during_load, this._defaults.live.show_image_during_load,
)} )}
${this._putInSubmenu( ${this._putInSubmenu(
MENU_LIVE_CONTROLS, MENU_LIVE_CONTROLS,
@@ -1537,6 +1579,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_LIVE_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD, CONF_LIVE_CONTROLS_TIMELINE_CLUSTERING_THRESHOLD,
CONF_LIVE_CONTROLS_TIMELINE_MEDIA, CONF_LIVE_CONTROLS_TIMELINE_MEDIA,
CONF_LIVE_CONTROLS_TIMELINE_SHOW_RECORDINGS, CONF_LIVE_CONTROLS_TIMELINE_SHOW_RECORDINGS,
this._defaults.live.controls.timeline.show_recordings,
)} )}
`, `,
)} )}
@@ -1583,11 +1626,11 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
)} )}
${this._renderSwitch( ${this._renderSwitch(
CONF_MEDIA_VIEWER_DRAGGABLE, CONF_MEDIA_VIEWER_DRAGGABLE,
defaults.media_viewer.draggable, this._defaults.media_viewer.draggable,
)} )}
${this._renderSwitch( ${this._renderSwitch(
CONF_MEDIA_VIEWER_LAZY_LOAD, CONF_MEDIA_VIEWER_LAZY_LOAD,
defaults.media_viewer.lazy_load, this._defaults.media_viewer.lazy_load,
)} )}
${this._renderOptionSelector( ${this._renderOptionSelector(
CONF_MEDIA_VIEWER_TRANSITION_EFFECT, CONF_MEDIA_VIEWER_TRANSITION_EFFECT,
@@ -1629,6 +1672,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
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_MEDIA,
CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_SHOW_RECORDINGS, CONF_MEDIA_VIEWER_CONTROLS_TIMELINE_SHOW_RECORDINGS,
this._defaults.media_viewer.controls.timeline.show_recordings,
)} )}
`, `,
)} )}
@@ -1664,7 +1708,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
CONF_TIMELINE_CLUSTERING_THRESHOLD, CONF_TIMELINE_CLUSTERING_THRESHOLD,
CONF_TIMELINE_MEDIA, CONF_TIMELINE_MEDIA,
CONF_TIMELINE_SHOW_RECORDINGS, CONF_TIMELINE_SHOW_RECORDINGS,
defaults.timeline.show_recordings, this._defaults.timeline.show_recordings,
)} )}
${this._renderThumbnailsControls( ${this._renderThumbnailsControls(
MENU_TIMELINE_CONTROLS_THUMBNAILS, MENU_TIMELINE_CONTROLS_THUMBNAILS,
@@ -1688,6 +1732,51 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
${this._renderStringInput(CONF_DIMENSIONS_ASPECT_RATIO)} ${this._renderStringInput(CONF_DIMENSIONS_ASPECT_RATIO)}
</div>` </div>`
: ''} : ''}
${this._renderOptionSetHeader(
'performance',
getConfigValue(this._config, CONF_PERFORMANCE_PROFILE) === 'low'
? 'warning'
: undefined,
)}
${this._expandedMenus[MENU_OPTIONS] === 'performance'
? html` <div class="values">
${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,
'config.performance.features.editor_label',
{ name: 'mdi:feature-search' },
html`
${this._renderSwitch(
CONF_PERFORMANCE_FEATURES_ANIMATED_PROGRESS_INDICATOR,
this._defaults.performance.features.animated_progress_indicator,
)}
`,
)}
${this._putInSubmenu(
MENU_PERFORMANCE_STYLE,
true,
'config.performance.style.editor_label',
{ name: 'mdi:palette-swatch-variant' },
html`
${this._renderSwitch(
CONF_PERFORMANCE_STYLE_BORDER_RADIUS,
this._defaults.performance.style.border_radius,
)}
${this._renderSwitch(
CONF_PERFORMANCE_STYLE_BOX_SHADOW,
this._defaults.performance.style.box_shadow,
)}
`,
)}
</div>`
: ''}
${this._config['overrides'] !== undefined ${this._config['overrides'] !== undefined
? html` ${this._renderOptionSetHeader('overrides')} ? html` ${this._renderOptionSetHeader('overrides')}
${this._expandedMenus[MENU_OPTIONS] === 'overrides' ${this._expandedMenus[MENU_OPTIONS] === 'overrides'
+19
View File
@@ -239,6 +239,23 @@
"overrides": { "overrides": {
"info": "This card configuration has manually specified overrides configured which may override values shown in the visual editor, please consult the code editor to view/modify these overrides" "info": "This card configuration has manually specified overrides configured which may override values shown in the visual editor, please consult the code editor to view/modify these overrides"
}, },
"performance": {
"warning": "This card is in low profile mode so many defaults have changed to optimize performance",
"features": {
"editor_label": "Feature Options",
"animated_progress_indicator": "Animated Progress Indicator"
},
"profile": "Performance profile",
"profiles": {
"low": "Low performance",
"high": "High/full performance"
},
"style": {
"editor_label": "Style Options",
"box_shadow": "Shadows",
"border_radius": "Curves"
}
},
"view": { "view": {
"camera_select": "View for newly selected cameras", "camera_select": "View for newly selected cameras",
"dark_mode": "Dark mode", "dark_mode": "Dark mode",
@@ -296,6 +313,8 @@
"move_up": "Move up", "move_up": "Move up",
"overrides": "Overrides are active", "overrides": "Overrides are active",
"overrides_secondary": "Dynamic configuration overrides detected", "overrides_secondary": "Dynamic configuration overrides detected",
"performance": "Performance",
"performance_secondary": "Card performance options",
"timeline": "Timeline", "timeline": "Timeline",
"timeline_secondary": "Event timeline options", "timeline_secondary": "Event timeline options",
"upgrade": "Upgrade", "upgrade": "Upgrade",
+9 -11
View File
@@ -1,6 +1,4 @@
// TODO: Change defaults themselves?
// TODO: Don't pump out conditionStates based on state? // TODO: Don't pump out conditionStates based on state?
// TODO: view history
import { deepRemoveDefaults } from './utils/zod.js'; import { deepRemoveDefaults } from './utils/zod.js';
import { import {
@@ -132,21 +130,21 @@ const LOW_PROFILE_CAMERA_DEFAULTS = {
* LOW_PROFILE_DEFAULTS unless they are explicitly overriden in the * LOW_PROFILE_DEFAULTS unless they are explicitly overriden in the
* configuration. * configuration.
* @param inputConfig The raw unparsed input configuration. * @param inputConfig The raw unparsed input configuration.
* @param parsedConfig The parsed input configuration. * @param outputConfig The output config to write to.
* @returns A changed (in-place) parsed input configuration. * @returns A changed (in-place) parsed input configuration.
*/ */
export const setLowPerformanceProfile = ( export const setLowPerformanceProfile = <T extends RawFrigateCardConfig>(
inputConfig: RawFrigateCardConfig, inputConfig: RawFrigateCardConfig,
parsedConfig: FrigateCardConfig, outputConfig: T,
): FrigateCardConfig => { ): T => {
const setIfNotSpecified = ( const setIfNotSpecified = (
defaultLessConfig: RawFrigateCardConfig, defaultLessConfig: RawFrigateCardConfig,
parsedConfig: FrigateCardConfig, outputConfig: T,
key: string, key: string,
value: unknown, value: unknown,
) => { ) => {
if (getConfigValue(defaultLessConfig, key) === undefined) { if (getConfigValue(defaultLessConfig, key) === undefined) {
setConfigValue(parsedConfig, key, value); setConfigValue(outputConfig, key, value);
} }
}; };
@@ -156,19 +154,19 @@ export const setLowPerformanceProfile = (
if (defaultLessParseResult.success) { if (defaultLessParseResult.success) {
const defaultLessConfig = defaultLessParseResult.data; const defaultLessConfig = defaultLessParseResult.data;
Object.entries(LOW_PROFILE_DEFAULTS).forEach(([k, v]: [string, unknown]) => Object.entries(LOW_PROFILE_DEFAULTS).forEach(([k, v]: [string, unknown]) =>
setIfNotSpecified(defaultLessConfig, parsedConfig, k, v), setIfNotSpecified(defaultLessConfig, outputConfig, k, v),
); );
Object.entries(LOW_PROFILE_CAMERA_DEFAULTS).forEach( Object.entries(LOW_PROFILE_CAMERA_DEFAULTS).forEach(
([rawKey, v]: [string, unknown]) => { ([rawKey, v]: [string, unknown]) => {
defaultLessConfig.cameras.forEach((_, index: number) => { defaultLessConfig.cameras.forEach((_, index: number) => {
const indexedKey = getArrayConfigPath(rawKey, index); const indexedKey = getArrayConfigPath(rawKey, index);
setIfNotSpecified(defaultLessConfig, parsedConfig, indexedKey, v); setIfNotSpecified(defaultLessConfig, outputConfig, indexedKey, v);
}); });
}, },
); );
} }
return parsedConfig; return outputConfig;
}; };
const STYLE_DISABLE_MAP = { const STYLE_DISABLE_MAP = {
+4 -1
View File
@@ -17,6 +17,9 @@
margin-top: -6px; margin-top: -6px;
pointer-events: none; pointer-events: none;
} }
.title.warning {
color: var(--warning-color);
}
.secondary { .secondary {
padding-left: 40px; padding-left: 40px;
color: var(--secondary-text-color); color: var(--secondary-text-color);
@@ -101,7 +104,7 @@ div.upgrade span {
--mdc-icon-size: calc(var(--mdc-icon-button-size) / 2); --mdc-icon-size: calc(var(--mdc-icon-button-size) / 2);
} }
span.info { span.info {
padding: 4px; padding: 10px;
} }
ha-selector { ha-selector {
+11 -6
View File
@@ -696,8 +696,12 @@ const timelineCoreConfigSchema = z.object({
}); });
export type TimelineCoreConfig = z.infer<typeof timelineCoreConfigSchema>; export type TimelineCoreConfig = z.infer<typeof timelineCoreConfigSchema>;
const miniTimelineConfigDefault = {
...timelineCoreConfigDefault,
mode: 'none' as const,
}
const miniTimelineConfigSchema = timelineCoreConfigSchema.extend({ const miniTimelineConfigSchema = timelineCoreConfigSchema.extend({
mode: z.enum(['none', 'above', 'below']), mode: z.enum(['none', 'above', 'below']).default(miniTimelineConfigDefault.mode),
}); });
export type MiniTimelineControlConfig = z.infer<typeof miniTimelineConfigSchema>; export type MiniTimelineControlConfig = z.infer<typeof miniTimelineConfigSchema>;
@@ -759,6 +763,7 @@ const liveConfigDefault = {
show_timeline_control: true, show_timeline_control: true,
mode: 'left' as const, mode: 'left' as const,
}, },
timeline: miniTimelineConfigDefault,
title: { title: {
mode: 'popup-bottom-right' as const, mode: 'popup-bottom-right' as const,
duration_seconds: 2, duration_seconds: 2,
@@ -833,7 +838,7 @@ const liveOverridableConfigSchema = z
.default(liveConfigDefault.controls.thumbnails.media), .default(liveConfigDefault.controls.thumbnails.media),
}) })
.default(liveConfigDefault.controls.thumbnails), .default(liveConfigDefault.controls.thumbnails),
timeline: miniTimelineConfigSchema.optional(), timeline: miniTimelineConfigSchema.default(liveConfigDefault.controls.timeline),
title: titleControlConfigSchema title: titleControlConfigSchema
.extend({ .extend({
mode: titleControlConfigSchema.shape.mode.default( mode: titleControlConfigSchema.shape.mode.default(
@@ -975,6 +980,7 @@ const viewerConfigDefault = {
show_timeline_control: true, show_timeline_control: true,
mode: 'left' as const, mode: 'left' as const,
}, },
timeline: miniTimelineConfigDefault,
title: { title: {
mode: 'popup-bottom-right' as const, mode: 'popup-bottom-right' as const,
duration_seconds: 2, duration_seconds: 2,
@@ -1038,7 +1044,7 @@ const viewerConfigSchema = z
), ),
}) })
.default(viewerConfigDefault.controls.thumbnails), .default(viewerConfigDefault.controls.thumbnails),
timeline: miniTimelineConfigSchema.optional(), timeline: miniTimelineConfigSchema.default(viewerConfigDefault.controls.timeline),
title: titleControlConfigSchema title: titleControlConfigSchema
.extend({ .extend({
mode: titleControlConfigSchema.shape.mode.default( mode: titleControlConfigSchema.shape.mode.default(
@@ -1212,14 +1218,14 @@ const performanceConfigDefault = {
animated_progress_indicator: true, animated_progress_indicator: true,
}, },
style: { style: {
border_radius: false, border_radius: true,
box_shadow: true, box_shadow: true,
}, },
}; };
const performanceConfigSchema = z const performanceConfigSchema = z
.object({ .object({
profile: z.enum(['low', 'high']), profile: z.enum(['low', 'high']).default(performanceConfigDefault.profile),
features: z features: z
.object({ .object({
animated_progress_indicator: z animated_progress_indicator: z
@@ -1281,7 +1287,6 @@ export const frigateCardConfigDefaults = {
event_gallery: galleryConfigDefault, event_gallery: galleryConfigDefault,
image: imageConfigDefault, image: imageConfigDefault,
timeline: timelineConfigDefault, timeline: timelineConfigDefault,
mini_timeline: timelineCoreConfigDefault,
performance: performanceConfigDefault, performance: performanceConfigDefault,
}; };