diff --git a/src/card.ts b/src/card.ts index f73a3937..6c589271 100644 --- a/src/card.ts +++ b/src/card.ts @@ -193,7 +193,7 @@ export class FrigateCard extends LitElement { // Manually set hass in the menu, elements and image. This is to allow these // to update, without necessarily re-rendering the entire card (re-rendering - // interrupts clip playing). + // is expensive). if (this._hass) { if (this._menu) { this._menu.hass = this._hass; @@ -205,6 +205,9 @@ export class FrigateCard extends LitElement { this._image.hass = this._hass; } } + + // Dark mode may depend on HASS. + this._setLightOrDarkMode(); } /** @@ -648,6 +651,7 @@ export class FrigateCard extends LitElement { this._view = undefined; this._message = null; this._generateConditionState(); + this._setLightOrDarkMode(); } /** @@ -685,10 +689,6 @@ export class FrigateCard extends LitElement { }); this._generateConditionState(); - // The default view has been loaded, so can abandon any running - // 'screensaver' timer. - this._clearInteractionTimer(); - // Restart the update timer, so the default view is refreshed at a fixed // interval from now (if so configured). this._startUpdateTimer(); @@ -699,6 +699,22 @@ export class FrigateCard extends LitElement { } } + /** + * Set the light or dark mode. + */ + protected _setLightOrDarkMode(): void { + const needDarkMode = + this._config.view.dark_mode === 'on' || + (this._config.view.dark_mode === 'auto' && + (!this._interactionTimerID || this._hass?.themes.darkMode)); + + if (needDarkMode) { + this.setAttribute('dark', ''); + } else { + this.removeAttribute('dark'); + } + } + /** * Handle a change view event. * @param e The change view event. @@ -965,8 +981,11 @@ export class FrigateCard extends LitElement { if (this._getConfig().view.timeout_seconds) { this._interactionTimerID = window.setTimeout(() => { this._changeView(); + this._clearInteractionTimer(); + this._setLightOrDarkMode(); }, this._getConfig().view.timeout_seconds * 1000); } + this._setLightOrDarkMode(); } /** diff --git a/src/scss/card.scss b/src/scss/card.scss index 34f29ce7..f74a82a0 100644 --- a/src/scss/card.scss +++ b/src/scss/card.scss @@ -5,6 +5,10 @@ position: relative; } +:host([dark]) { + filter: brightness(50%); +} + .container { position: relative; overflow: auto; diff --git a/src/types.ts b/src/types.ts index df87f2cf..ad4a12e4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -7,6 +7,7 @@ import { MoreInfoActionConfig, NavigateActionConfig, NoActionConfig, + Themes, ToggleActionConfig, UrlActionConfig, } from 'custom-card-helpers'; @@ -402,6 +403,7 @@ const viewConfigDefault = { update_seconds: 0, update_force: false, update_cycle_camera: false, + dark_mode: 'off' as const, }; const viewConfigSchema = z .object({ @@ -417,6 +419,7 @@ const viewConfigSchema = z update_cycle_camera: z.boolean().default(viewConfigDefault.update_cycle_camera), update_entities: z.string().array().optional(), render_entities: z.string().array().optional(), + dark_mode: z.enum(['on', 'off', 'auto']).optional(), }) .merge(actionsSchema) .default(viewConfigDefault); @@ -931,6 +934,9 @@ const menuButtonSchema = z.discriminatedUnion('type', [ export type MenuButton = z.infer; export interface ExtendedHomeAssistant { hassUrl(path?): string; + themes: Themes & { + darkMode?: boolean + }; } export interface BrowseMediaQueryParametersBase {