feat: Add richer card theme support (#1809)

This commit is contained in:
Dermot Duffy
2025-01-07 19:54:13 -08:00
committed by GitHub
parent f7ecb91578
commit 278560b5ac
65 changed files with 1187 additions and 352 deletions
+1 -2
View File
@@ -97,7 +97,6 @@ export class ConfigManager {
this._api.getViewManager().reset();
this._api.getMessageManager().reset();
this._api.getStyleManager().setPerformance();
this._api.getStatusBarItemManager().removeAllDynamicStatusBarItems();
setKeyboardShortcutsFromConfig(this._api, this);
@@ -134,7 +133,7 @@ export class ConfigManager {
const previousConfig = this._overriddenConfig;
this._overriddenConfig = overriddenConfig;
this._api.getStyleManager().setMinMaxHeight();
this._api.getStyleManager().updateFromConfig();
if (
previousConfig &&
+2 -2
View File
@@ -53,8 +53,8 @@ export class HASSManager {
});
}
// Dark mode may depend on HASS.
this._api.getStyleManager().setLightOrDarkMode();
// Theme may depend on HASS.
this._api.getStyleManager().applyTheme();
this._stateWatcher.setHASS(oldHass, hass);
}
+16 -11
View File
@@ -1,10 +1,12 @@
import throttle from 'lodash-es/throttle';
import { setOrRemoveAttribute } from '../utils/basic';
import { Timer } from '../utils/timer';
import { CardInteractionAPI } from './types';
export class InteractionManager {
protected _timer = new Timer();
protected _api: CardInteractionAPI;
protected _interacted = false;
constructor(api: CardInteractionAPI) {
this._api = api;
@@ -17,29 +19,32 @@ export class InteractionManager {
}, 1 * 1000);
public initialize(): void {
this._api.getConditionsManager().setState({ interaction: false });
this._setInteraction(false);
}
public hasInteraction(): boolean {
return this._timer.isRunning();
return this._interacted;
}
protected _setInteraction(val: boolean): void {
this._interacted = val;
setOrRemoveAttribute(
this._api.getCardElementManager().getElement(),
val,
'interaction',
);
this._api.getConditionsManager().setState({ interaction: val });
}
/**
* Start the user interaction ('screensaver') timer to reset the view to
* default `view.interaction_seconds` after user interaction.
*/
protected _reportInteraction(): void {
this._timer.stop();
this._setInteraction(true);
const timeoutSeconds = this._api.getConfigManager().getConfig()
?.view.interaction_seconds;
if (timeoutSeconds) {
this._api.getConditionsManager().setState({ interaction: true });
this._timer.start(timeoutSeconds, () => {
this._api.getConditionsManager().setState({ interaction: false });
this._api.getStyleManager().setLightOrDarkMode();
this._setInteraction(false);
});
}
}
+48 -18
View File
@@ -1,5 +1,10 @@
import { StyleInfo } from 'lit/directives/style-map';
import { FrigateCardConfig } from '../config/types';
import {
FrigateCardConfig,
frigateCardConfigDefaults,
ThemeConfig,
ThemeName,
} from '../config/types';
import { aspectRatioToStyle, setOrRemoveAttribute } from '../utils/basic';
import { View } from '../view/view';
import { CardStyleAPI } from './types';
@@ -11,21 +16,6 @@ export class StyleManager {
this._api = api;
}
public setLightOrDarkMode = (): void => {
const config = this._api.getConfigManager().getConfig();
const isDarkMode =
config?.view.dark_mode === 'on' ||
(config?.view.dark_mode === 'auto' &&
(!this._api.getInteractionManager().hasInteraction() ||
!!this._api.getHASSManager().getHASS()?.themes.darkMode));
setOrRemoveAttribute(
this._api.getCardElementManager().getElement(),
isDarkMode,
'dark',
);
};
public setExpandedMode(): void {
const card = this._api.getCardElementManager().getElement();
const view = this._api.getViewManager().getView();
@@ -58,7 +48,47 @@ export class StyleManager {
);
}
public setMinMaxHeight(): void {
public updateFromConfig(): void {
this.applyTheme();
this._setMinMaxHeight();
this._setPerformance();
this._setDimmable();
}
public applyTheme() {
const themeConfig = this._api.getConfigManager().getConfig()?.view.theme;
if (!themeConfig) {
return;
}
const element = this._api.getCardElementManager().getElement();
const themes = this._getThemeNames(themeConfig);
setOrRemoveAttribute(element, !!themes, 'themes', themes?.join(' '));
if (themeConfig.overrides) {
for (const [key, value] of Object.entries(themeConfig.overrides)) {
element.style.setProperty(key, value);
}
}
}
protected _getThemeNames(themeConfig: ThemeConfig): ThemeName[] | null {
return themeConfig.themes.length
? themeConfig.themes
: frigateCardConfigDefaults.view.theme.themes;
}
protected _setDimmable(): void {
const config = this._api.getConfigManager().getConfig();
setOrRemoveAttribute(
this._api.getCardElementManager().getElement(),
!!config?.view.dim,
'dimmable',
);
}
protected _setMinMaxHeight(): void {
const config = this._api.getConfigManager().getConfig();
if (config) {
const card = this._api.getCardElementManager().getElement();
@@ -66,7 +96,7 @@ export class StyleManager {
}
}
public setPerformance(): void {
protected _setPerformance(): void {
const STYLE_DISABLE_MAP = {
box_shadow: 'none',
border_radius: '0px',
+1
View File
@@ -180,6 +180,7 @@ export interface CardInitializerAPI {
}
export interface CardInteractionAPI {
getCardElementManager(): CardElementManager;
getConditionsManager(): ConditionsManager;
getConfigManager(): ConfigManager;
getStyleManager(): StyleManager;