diff --git a/src/card.ts b/src/card.ts index 4ffa9a4f..f719c6f6 100644 --- a/src/card.ts +++ b/src/card.ts @@ -102,7 +102,7 @@ import { View } from './view.js'; import pkg from '../package.json'; import { ViewContext } from 'view'; import { DataManager } from './utils/data-manager.js'; -import { setLowPerformanceProfile } from './performance.js'; +import { setLowPerformanceProfile, setPerformanceCSSStyles } from './performance.js'; /** A note on media callbacks: * @@ -1097,6 +1097,10 @@ export class FrigateCard extends LitElement { if (this._cameras && (changedProps.has('_config') || changedProps.has('_cameras'))) { this._dataManager = new DataManager(this._cameras); } + + if (changedProps.has('_cardWideConfig')) { + setPerformanceCSSStyles(this, this._cardWideConfig?.performance); + } } /** diff --git a/src/const.ts b/src/const.ts index f29e02ac..03cb5a8d 100644 --- a/src/const.ts +++ b/src/const.ts @@ -206,6 +206,8 @@ export const CONF_OVERRIDES = 'overrides' 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_STYLE_BOX_SHADOW = `${CONF_PERFORMANCE}.style.box_shadow`; +export const CONF_PERFORMANCE_STYLE_BORDER_RADIUS = `${CONF_PERFORMANCE}.style.border_radius`; // Taken from https://github.dev/home-assistant/frontend/blob/b5861869e39290fd2e15737e89571dfc543b3ad3/src/data/media-player.ts#L93 export const MEDIA_PLAYER_SUPPORT_BROWSE_MEDIA = 131072; diff --git a/src/performance.ts b/src/performance.ts index 176cef3c..75af9e34 100644 --- a/src/performance.ts +++ b/src/performance.ts @@ -1,12 +1,13 @@ // TODO: Change defaults themselves? -// TODO: CSS // TODO: Don't pump out conditionStates based on state? +// TODO: view history import { deepRemoveDefaults } from './utils/zod.js'; import { frigateCardConfigSchema, FrigateCardConfig, RawFrigateCardConfig, + PerformanceConfig, } from './types'; import { getArrayConfigPath, getConfigValue, setConfigValue } from './config-mgmt.js'; import { @@ -42,6 +43,8 @@ import { CONF_MENU_BUTTONS_TIMELINE, CONF_MENU_STYLE, CONF_PERFORMANCE_FEATURES_ANIMATED_PROGRESS_INDICATOR, + CONF_PERFORMANCE_STYLE_BORDER_RADIUS, + CONF_PERFORMANCE_STYLE_BOX_SHADOW, CONF_TIMELINE_CONTROLS_THUMBNAILS_MODE, CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_DETAILS, CONF_TIMELINE_CONTROLS_THUMBNAILS_SHOW_FAVORITE_CONTROL, @@ -114,6 +117,10 @@ const LOW_PROFILE_DEFAULTS = { // Disable all optional performance related features. [CONF_PERFORMANCE_FEATURES_ANIMATED_PROGRESS_INDICATOR]: false, + + // Disable all expensive CSS features. + [CONF_PERFORMANCE_STYLE_BORDER_RADIUS]: false, + [CONF_PERFORMANCE_STYLE_BOX_SHADOW]: false, }; const LOW_PROFILE_CAMERA_DEFAULTS = { @@ -163,3 +170,28 @@ export const setLowPerformanceProfile = ( } return parsedConfig; }; + +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); + } + } +}; diff --git a/src/scss/drawer-inject.scss b/src/scss/drawer-inject.scss index 17eaeeef..bdbd8cf7 100644 --- a/src/scss/drawer-inject.scss +++ b/src/scss/drawer-inject.scss @@ -27,16 +27,16 @@ max-width: 90%; } -:host([location=right]) #d { +:host([location='right']) #d { // Position to the right. left: unset; right: 0; transform: translateX(100%); } -:host([location=right][open]) #d { +:host([location='right'][open]) #d { transform: none; - box-shadow: 0px 0px 25px 0px black; + box-shadow: var(--frigate-card-css-box-shadow, 0px 0px 25px 0px black); } #ifs { diff --git a/src/scss/gallery.scss b/src/scss/gallery.scss index 662c0a78..ad22eb9d 100644 --- a/src/scss/gallery.scss +++ b/src/scss/gallery.scss @@ -31,7 +31,7 @@ text-align: center; color: var(--primary-text-color, white); border: 1px solid var(--primary-color); - border-radius: var(--ha-card-border-radius, 4px); + border-radius: var(--frigate-card-css-border-radius, var(--ha-card-border-radius, 4px)); // Folder background color should match the thumbnail element background // color. diff --git a/src/scss/next-previous-control.scss b/src/scss/next-previous-control.scss index 2d9e97b0..178a77a3 100644 --- a/src/scss/next-previous-control.scss +++ b/src/scss/next-previous-control.scss @@ -29,7 +29,7 @@ border-radius: 50%; height: var(--frigate-card-next-prev-size); top: calc(50% - (var(--frigate-card-next-prev-size) / 2)); - box-shadow: 0px 0px 20px 5px black; + box-shadow: var(--frigate-card-css-box-shadow, 0px 0px 20px 5px black); transition: all 0.2s ease-out; opacity: 0.8; aspect-ratio: 1 / 1; diff --git a/src/scss/thumbnail-feature-event.scss b/src/scss/thumbnail-feature-event.scss index f4a1364e..970fb6b9 100644 --- a/src/scss/thumbnail-feature-event.scss +++ b/src/scss/thumbnail-feature-event.scss @@ -12,7 +12,7 @@ ha-icon { // Safari will occasionally not load thumbnails correctly with display block. display: inline-block; - border-radius: var(--ha-card-border-radius, 4px); + border-radius: var(--frigate-card-css-border-radius, var(--ha-card-border-radius, 4px)); max-width: var(--frigate-card-thumbnail-size); max-height: 100%; diff --git a/src/scss/thumbnail-feature-recording.scss b/src/scss/thumbnail-feature-recording.scss index dab70503..459e3e22 100644 --- a/src/scss/thumbnail-feature-recording.scss +++ b/src/scss/thumbnail-feature-recording.scss @@ -12,7 +12,7 @@ border: 1px solid var(--secondary-color); background-color: var(--secondary-background-color); - border-radius: var(--ha-card-border-radius, 4px); + border-radius: var(--frigate-card-css-border-radius, var(--ha-card-border-radius, 4px)); box-sizing: border-box; color: var(--primary-text-color); diff --git a/src/scss/thumbnail.scss b/src/scss/thumbnail.scss index caa64791..9dbf577a 100644 --- a/src/scss/thumbnail.scss +++ b/src/scss/thumbnail.scss @@ -16,7 +16,7 @@ :host([details]) { border: 1px solid var(--primary-color); - border-radius: var(--ha-card-border-radius, 4px); + border-radius: var(--frigate-card-css-border-radius, var(--ha-card-border-radius, 4px)); padding: 2px; // When details are enabled, use a background color so that the details have diff --git a/src/scss/timeline-core.scss b/src/scss/timeline-core.scss index a6851b2a..218d8b5c 100644 --- a/src/scss/timeline-core.scss +++ b/src/scss/timeline-core.scss @@ -49,7 +49,7 @@ div.timeline { .vis-item.vis-selected { border-color: var(--accent-color); background-color: var(--accent-color); - box-shadow: 0px 0px 5px 1px var(--primary-color); + box-shadow: var(--frigate-card-css-box-shadow, 0px 0px 5px 1px var(--primary-color)); } .vis-item.vis-background { background-color: var(--primary-color); @@ -88,7 +88,10 @@ div.timeline { border-style: dotted; color: var(--primary-text-color); background-color: var(--primary-background-color); - box-shadow: 0px 0px 5px 1px var(--primary-color); + box-shadow: var(--frigate-card-css-box-shadow, 0px 0px 5px 1px var(--primary-color)); +} +.vis-item.vis-range { + border-radius: var(--frigate-card-css-border-radius, unset); } .vis-time-axis .vis-grid.vis-minor { @@ -127,7 +130,7 @@ div.vis-tooltip { .target_bar { border-left: 2px solid var(--primary-color); opacity: 0.7; - box-shadow: 0px 0px 3px 1px var(--primary-color); + box-shadow: var(--frigate-card-css-box-shadow, 0px 0px 3px 1px var(--primary-color)); // Prevent the mouse interacting with the custom time. pointer-events: none; diff --git a/src/types.ts b/src/types.ts index 88112481..ee09400d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1211,6 +1211,10 @@ const performanceConfigDefault = { features: { animated_progress_indicator: true, }, + style: { + border_radius: false, + box_shadow: true, + }, }; const performanceConfigSchema = z @@ -1223,6 +1227,12 @@ const performanceConfigSchema = z .default(performanceConfigDefault.features.animated_progress_indicator), }) .default(performanceConfigDefault.features), + style: z + .object({ + border_radius: z.boolean().default(performanceConfigDefault.style.border_radius), + box_shadow: z.boolean().default(performanceConfigDefault.style.box_shadow), + }) + .default(performanceConfigDefault.style), }) .default(performanceConfigDefault); export type PerformanceConfig = z.infer; diff --git a/tsconfig.json b/tsconfig.json index 0b7df973..b5045a7e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,9 @@ { "compilerOptions": { - "target": "es2017", + "target": "es2021", "module": "es2020", "moduleResolution": "node", - "lib": ["es2017", "dom", "dom.iterable"], + "lib": ["es2021", "dom", "dom.iterable"], "noEmit": true, "noUnusedParameters": true, "noImplicitReturns": true,