Initial version of more advanced scan mode control.
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import {
|
||||
Actions,
|
||||
ActionsConfig,
|
||||
ActionType,
|
||||
FrigateCardCustomAction,
|
||||
FRIGATE_CARD_VIEW_DEFAULT,
|
||||
} from '../config/types.js';
|
||||
import {
|
||||
convertActionToFrigateCardCustomAction,
|
||||
frigateCardHandleAction,
|
||||
frigateCardHandleActionConfig,
|
||||
getActionConfigGivenAction,
|
||||
} from '../utils/action.js';
|
||||
@@ -81,16 +83,36 @@ export class ActionsManager {
|
||||
|
||||
const frigateCardAction = convertActionToFrigateCardCustomAction(ev.detail);
|
||||
if (frigateCardAction) {
|
||||
this.executeAction(frigateCardAction);
|
||||
this.executeFrigateAction(frigateCardAction);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Small convenience method to call frigateCardHandleAction without the caller
|
||||
* needing hass or the element.
|
||||
*/
|
||||
public executeActions(actions: ActionType | ActionType[]): void {
|
||||
const hass = this._api.getHASSManager().getHASS();
|
||||
if (!hass) {
|
||||
return;
|
||||
}
|
||||
|
||||
frigateCardHandleAction(
|
||||
this._api.getCardElementManager().getElement(),
|
||||
hass,
|
||||
{},
|
||||
actions,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a card action.
|
||||
* @param frigateCardAction
|
||||
* @returns `true` if an action is executed.
|
||||
*/
|
||||
public async executeAction(frigateCardAction: FrigateCardCustomAction): Promise<void> {
|
||||
public async executeFrigateAction(
|
||||
frigateCardAction: FrigateCardCustomAction,
|
||||
): Promise<void> {
|
||||
const config = this._api.getConfigManager().getConfig();
|
||||
const mediaLoadedInfoManager = this._api.getMediaLoadedInfoManager();
|
||||
|
||||
@@ -146,8 +168,12 @@ export class ActionsManager {
|
||||
this._api.getCardElementManager().toggleMenu();
|
||||
break;
|
||||
case 'camera_select':
|
||||
const selectCameraID = frigateCardAction.camera;
|
||||
if (view) {
|
||||
const selectCameraID =
|
||||
frigateCardAction.camera ??
|
||||
(frigateCardAction.triggered
|
||||
? this._api.getTriggersManager().getMostRecentlyTriggeredCameraID()
|
||||
: null);
|
||||
if (selectCameraID && view) {
|
||||
const viewOnCameraSelect = config?.view.camera_select ?? 'current';
|
||||
const targetViewName =
|
||||
viewOnCameraSelect === 'current' ? view.view : viewOnCameraSelect;
|
||||
|
||||
@@ -74,7 +74,7 @@ export class HASSManager {
|
||||
this._api.getCardElementManager().update();
|
||||
}
|
||||
|
||||
this._api.getTriggersManager().updateTriggeredCameras(oldHass);
|
||||
this._api.getTriggersManager().updateTriggerHAState(oldHass);
|
||||
|
||||
if (this._api.getConditionsManager().hasHAStateConditions()) {
|
||||
this._api.getConditionsManager().setState({ state: this._hass.states });
|
||||
|
||||
@@ -27,9 +27,6 @@ export class InteractionManager {
|
||||
protected _reportInteraction(): void {
|
||||
this._timer.stop();
|
||||
|
||||
// Interactions reset the trigger state.
|
||||
this._api.getTriggersManager().untrigger();
|
||||
|
||||
const timeoutSeconds = this._api.getConfigManager().getConfig()
|
||||
?.view.timeout_seconds;
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { FrigateCardCustomAction, FrigateCardViewAction } from '../config/types';
|
||||
import { createFrigateCardCameraAction, createFrigateCardSimpleAction } from '../utils/action.js';
|
||||
import {
|
||||
createFrigateCardCameraAction,
|
||||
createFrigateCardSimpleAction
|
||||
} from '../utils/action.js';
|
||||
import { CardQueryStringAPI } from './types';
|
||||
import { ViewManagerSetViewParameters } from './view-manager';
|
||||
|
||||
@@ -35,43 +38,6 @@ export class QueryStringManager {
|
||||
this._executeNonViewRelated(intent);
|
||||
};
|
||||
|
||||
public generateQueryString(action: FrigateCardCustomAction): string | null {
|
||||
const baseKey =
|
||||
'frigate-card-action.' + (action.card_id ? `${action.card_id}.` : '');
|
||||
|
||||
switch (action.frigate_card_action) {
|
||||
case 'camera_select':
|
||||
case 'live_substream_select':
|
||||
return new URLSearchParams([
|
||||
[baseKey + action.frigate_card_action, action.camera],
|
||||
]).toString();
|
||||
case 'camera_ui':
|
||||
case 'clip':
|
||||
case 'clips':
|
||||
case 'default':
|
||||
case 'diagnostics':
|
||||
case 'download':
|
||||
case 'expand':
|
||||
case 'image':
|
||||
case 'live':
|
||||
case 'menu_toggle':
|
||||
case 'recording':
|
||||
case 'recordings':
|
||||
case 'snapshot':
|
||||
case 'snapshots':
|
||||
case 'timeline':
|
||||
return new URLSearchParams([
|
||||
[baseKey + action.frigate_card_action, ''],
|
||||
]).toString();
|
||||
default:
|
||||
console.warn(
|
||||
`Frigate card cannot convert unsupported action to query string:`,
|
||||
action,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected _executeViewRelated(intent: QueryStringViewIntent): void {
|
||||
if (intent.view) {
|
||||
if (intent.view.default) {
|
||||
@@ -96,7 +62,7 @@ export class QueryStringManager {
|
||||
}
|
||||
|
||||
intent.other?.forEach((action) =>
|
||||
this._api.getActionsManager().executeAction(action),
|
||||
this._api.getActionsManager().executeFrigateAction(action),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,30 +2,44 @@ import { HomeAssistant } from '@dermotduffy/custom-card-helpers';
|
||||
import orderBy from 'lodash-es/orderBy';
|
||||
import { getHassDifferences, isTriggeredState } from '../utils/ha';
|
||||
import { Timer } from '../utils/timer';
|
||||
import { View } from '../view/view';
|
||||
import { CardTriggersAPI } from './types';
|
||||
|
||||
export class TriggersManager {
|
||||
protected _api: CardTriggersAPI;
|
||||
|
||||
protected _triggers: Map<string, Date> = new Map();
|
||||
protected _untriggerTimer = new Timer();
|
||||
protected _triggeredCameras: Map<string, Date> = new Map();
|
||||
protected _triggeredCameraTimers: Map<string, Timer> = new Map();
|
||||
protected _triggeredState: Set<string> = new Set();
|
||||
|
||||
constructor(api: CardTriggersAPI) {
|
||||
this._api = api;
|
||||
}
|
||||
|
||||
public isTriggered(): boolean {
|
||||
return !!this._triggers.size || this._untriggerTimer.isRunning();
|
||||
public getTriggeredCameraIDs(): Set<string> {
|
||||
return new Set(this._triggeredCameras.keys());
|
||||
}
|
||||
|
||||
public updateTriggeredCameras(oldHass?: HomeAssistant | null): boolean {
|
||||
if (!this._shouldTrackTriggers()) {
|
||||
return false;
|
||||
public isTriggered(): boolean {
|
||||
return !!this._triggeredCameras.size;
|
||||
}
|
||||
|
||||
public getMostRecentlyTriggeredCameraID(): string | null {
|
||||
const sorted = orderBy(
|
||||
[...this._triggeredCameras.entries()],
|
||||
(entry) => entry[1].getTime(),
|
||||
'desc',
|
||||
);
|
||||
return sorted.length ? sorted[0][0] : null;
|
||||
}
|
||||
|
||||
public updateTriggerHAState(oldHass?: HomeAssistant | null): void {
|
||||
const scanConfig = this._api.getConfigManager().getConfig()?.view.scan;
|
||||
if (!scanConfig || !scanConfig.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hass = this._api.getHASSManager().getHASS();
|
||||
|
||||
const now = new Date();
|
||||
let triggerChanges = false;
|
||||
|
||||
const visibleCameraIDs = this._api
|
||||
@@ -45,88 +59,108 @@ export class TriggersManager {
|
||||
(entity) => !isTriggeredState(hass?.states[entity]),
|
||||
);
|
||||
if (shouldTrigger) {
|
||||
this._triggers.set(cameraID, now);
|
||||
this._triggeredState.add(cameraID);
|
||||
triggerChanges = true;
|
||||
} else if (shouldUntrigger && this._triggers.has(cameraID)) {
|
||||
this._triggers.delete(cameraID);
|
||||
} else if (shouldUntrigger && this._triggeredState.has(cameraID)) {
|
||||
this._triggeredState.delete(cameraID);
|
||||
triggerChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (triggerChanges) {
|
||||
const targetCameraID = this._getMostRecentTrigger();
|
||||
if (targetCameraID) {
|
||||
this._triggerAction(targetCameraID);
|
||||
return true;
|
||||
} else {
|
||||
this._startUntriggerTimer();
|
||||
this._evaluateTriggers();
|
||||
}
|
||||
}
|
||||
|
||||
public updateView(oldView?: View | null): void {
|
||||
if (oldView?.camera !== this._api.getViewManager().getView()?.camera) {
|
||||
// If the view changes, a new camera may have been selected, which may
|
||||
// mean a trigger is required (in the case that `trigger_filter_camera`
|
||||
// has been set to `selected`).
|
||||
this._evaluateTriggers();
|
||||
}
|
||||
}
|
||||
|
||||
protected _evaluateTriggers(): void {
|
||||
const scanConfig = this._api.getConfigManager().getConfig()?.view.scan;
|
||||
if (!scanConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
for (const cameraID of this._triggeredState.keys()) {
|
||||
if (
|
||||
!this._triggeredCameras.has(cameraID) &&
|
||||
(scanConfig.trigger_filter_camera === 'all' ||
|
||||
(scanConfig.trigger_filter_camera === 'selected' &&
|
||||
cameraID === this._api.getViewManager().getView()?.camera))
|
||||
) {
|
||||
this._triggeredCameras.set(cameraID, now);
|
||||
this._triggerAction();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public untrigger(): void {
|
||||
const wasTriggered = this.isTriggered();
|
||||
this._triggers.clear();
|
||||
this._untriggerTimer.stop();
|
||||
|
||||
if (wasTriggered) {
|
||||
this._untriggerAction();
|
||||
for (const cameraID of this._triggeredCameras.keys()) {
|
||||
if (!this._triggeredState.has(cameraID)) {
|
||||
this._startUntriggerTimer(cameraID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected _triggerAction(cameraID: string): void {
|
||||
const view = this._api.getViewManager().getView();
|
||||
if (
|
||||
this._isAutomatedViewUpdateAllowed() &&
|
||||
(view?.camera !== cameraID || !view?.is('live'))
|
||||
) {
|
||||
this._api.getViewManager().setViewByParameters({
|
||||
viewName: 'live',
|
||||
cameraID: cameraID,
|
||||
});
|
||||
}
|
||||
}
|
||||
protected _hasAllowableInteractionState(): boolean {
|
||||
const scanConfig = this._api.getConfigManager().getConfig()?.view.scan;
|
||||
const hasInteraction = this._api.getInteractionManager().hasInteraction();
|
||||
|
||||
protected _untriggerAction(): void {
|
||||
if (
|
||||
!this.isTriggered() &&
|
||||
this._isAutomatedViewUpdateAllowed() &&
|
||||
this._api.getConfigManager().getConfig()?.view.scan.untrigger_reset
|
||||
) {
|
||||
this._api.getViewManager().setViewDefault();
|
||||
}
|
||||
}
|
||||
|
||||
protected _isAutomatedViewUpdateAllowed(): boolean {
|
||||
return (
|
||||
this._api.getConfigManager().getConfig()?.view.update_force ||
|
||||
!this._api.getInteractionManager().hasInteraction()
|
||||
!!scanConfig &&
|
||||
(scanConfig.interaction_mode === 'all' ||
|
||||
(scanConfig.interaction_mode === 'active' && hasInteraction) ||
|
||||
(scanConfig.interaction_mode === 'inactive' && !hasInteraction))
|
||||
);
|
||||
}
|
||||
|
||||
protected _shouldTrackTriggers(): boolean {
|
||||
return !!this._api.getConfigManager().getConfig()?.view.scan.enabled;
|
||||
protected _triggerAction(): void {
|
||||
const action = this._api.getConfigManager().getConfig()?.view.scan.trigger_action;
|
||||
|
||||
if (action && this._hasAllowableInteractionState()) {
|
||||
this._api.getActionsManager().executeActions(action);
|
||||
}
|
||||
|
||||
// Must update master element to add border pulsing.
|
||||
this._api.getCardElementManager().update();
|
||||
}
|
||||
|
||||
protected _startUntriggerTimer(): void {
|
||||
this._untriggerTimer.start(
|
||||
protected _untriggerAction(cameraID: string): void {
|
||||
const action = this._api.getConfigManager().getConfig()?.view.scan.untrigger_action;
|
||||
|
||||
if (action && this._hasAllowableInteractionState()) {
|
||||
this._api.getActionsManager().executeActions(action);
|
||||
}
|
||||
this._triggeredCameras.delete(cameraID);
|
||||
this._deleteTimer(cameraID);
|
||||
|
||||
// Must update master element to remove border pulsing.
|
||||
this._api.getCardElementManager().update();
|
||||
}
|
||||
|
||||
protected _startUntriggerTimer(cameraID: string): void {
|
||||
this._deleteTimer(cameraID);
|
||||
|
||||
const timer = new Timer();
|
||||
this._triggeredCameraTimers.set(cameraID, timer);
|
||||
timer.start(
|
||||
/* istanbul ignore next: the case of config being null here cannot be
|
||||
reached, as there's no way to have the untrigger call happen without
|
||||
a config. -- @preserve */
|
||||
this._api.getConfigManager().getConfig()?.view.scan.untrigger_seconds ?? 0,
|
||||
() => {
|
||||
this._untriggerAction();
|
||||
this._untriggerAction(cameraID);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
protected _getMostRecentTrigger(): string | null {
|
||||
const sorted = orderBy(
|
||||
[...this._triggers.entries()],
|
||||
(entry) => entry[1].getTime(),
|
||||
'desc',
|
||||
);
|
||||
return sorted.length ? sorted[0][0] : null;
|
||||
protected _deleteTimer(cameraID: string): void {
|
||||
this._triggeredCameraTimers.get(cameraID)?.stop();
|
||||
this._triggeredCameraTimers.delete(cameraID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,9 @@ export interface CardActionsManagerAPI {
|
||||
getMediaLoadedInfoManager(): MediaLoadedInfoManager;
|
||||
getMediaPlayerManager(): MediaPlayerManager;
|
||||
getMessageManager(): MessageManager;
|
||||
getViewManager(): ViewManager;
|
||||
getMicrophoneManager(): MicrophoneManager;
|
||||
getTriggersManager(): TriggersManager;
|
||||
getViewManager(): ViewManager;
|
||||
}
|
||||
|
||||
export interface CardAutomationsAPI {
|
||||
@@ -55,17 +56,17 @@ export interface CardAutomationsAPI {
|
||||
|
||||
export interface CardAutoRefreshAPI {
|
||||
getConfigManager(): ConfigManager;
|
||||
getViewManager(): ViewManager;
|
||||
getTriggersManager(): TriggersManager;
|
||||
getInteractionManager(): InteractionManager;
|
||||
getTriggersManager(): TriggersManager;
|
||||
getViewManager(): ViewManager;
|
||||
}
|
||||
|
||||
export interface CardCameraAPI {
|
||||
getConfigManager(): ConfigManager;
|
||||
getEntityRegistryManager(): EntityRegistryManager;
|
||||
getResolvedMediaCache(): ResolvedMediaCache;
|
||||
getHASSManager(): HASSManager;
|
||||
getMessageManager(): MessageManager;
|
||||
getResolvedMediaCache(): ResolvedMediaCache;
|
||||
}
|
||||
|
||||
export interface CardCameraURLAPI {
|
||||
@@ -106,15 +107,15 @@ export interface CardElementAPI {
|
||||
}
|
||||
|
||||
export interface CardExpandAPI {
|
||||
getFullscreenManager(): FullscreenManager;
|
||||
getConditionsManager(): ConditionsManager;
|
||||
getCardElementManager(): CardElementManager;
|
||||
getConditionsManager(): ConditionsManager;
|
||||
getFullscreenManager(): FullscreenManager;
|
||||
}
|
||||
|
||||
export interface CardFullscreenAPI {
|
||||
getCardElementManager(): CardElementManager;
|
||||
getExpandManager(): ExpandManager;
|
||||
getConditionsManager(): ConditionsManager;
|
||||
getExpandManager(): ExpandManager;
|
||||
getMediaPlayerManager(): MediaPlayerManager;
|
||||
}
|
||||
|
||||
@@ -153,23 +154,23 @@ export interface CardInteractionAPI {
|
||||
}
|
||||
|
||||
export interface CardMediaLoadedAPI {
|
||||
getCardElementManager(): CardElementManager;
|
||||
getConditionsManager(): ConditionsManager;
|
||||
getConfigManager(): ConfigManager;
|
||||
getCardElementManager(): CardElementManager;
|
||||
getStyleManager(): StyleManager;
|
||||
}
|
||||
|
||||
export interface CardMediaPlayerAPI {
|
||||
getHASSManager(): HASSManager;
|
||||
getCameraManager(): CameraManager;
|
||||
getEntityRegistryManager(): EntityRegistryManager;
|
||||
getHASSManager(): HASSManager;
|
||||
getMessageManager(): MessageManager;
|
||||
getQueryStringManager(): QueryStringManager;
|
||||
}
|
||||
|
||||
export interface CardMessageAPI {
|
||||
getConditionsManager(): ConditionsManager;
|
||||
getCardElementManager(): CardElementManager;
|
||||
getConditionsManager(): ConditionsManager;
|
||||
getMediaLoadedInfoManager(): MediaLoadedInfoManager;
|
||||
}
|
||||
|
||||
@@ -179,9 +180,9 @@ export interface CardMicrophoneAPI {
|
||||
}
|
||||
|
||||
export interface CardQueryStringAPI {
|
||||
getActionsManager(): ActionsManager;
|
||||
getCardElementManager(): CardElementManager;
|
||||
getViewManager(): ViewManager;
|
||||
getActionsManager(): ActionsManager;
|
||||
}
|
||||
|
||||
export interface CardStyleAPI {
|
||||
@@ -196,7 +197,9 @@ export interface CardStyleAPI {
|
||||
}
|
||||
|
||||
export interface CardTriggersAPI {
|
||||
getActionsManager(): ActionsManager;
|
||||
getCameraManager(): CameraManager;
|
||||
getCardElementManager(): CardElementManager;
|
||||
getConfigManager(): ConfigManager;
|
||||
getHASSManager(): HASSManager;
|
||||
getInteractionManager(): InteractionManager;
|
||||
@@ -206,11 +209,12 @@ export interface CardTriggersAPI {
|
||||
export interface CardViewAPI {
|
||||
getAutoUpdateManager(): AutoUpdateManager;
|
||||
getCameraManager(): CameraManager;
|
||||
getCardElementManager(): CardElementManager;
|
||||
getConditionsManager(): ConditionsManager;
|
||||
getConfigManager(): ConfigManager;
|
||||
getHASSManager(): HASSManager;
|
||||
getMediaLoadedInfoManager(): MediaLoadedInfoManager;
|
||||
getMessageManager(): MessageManager;
|
||||
getStyleManager(): StyleManager;
|
||||
getConditionsManager(): ConditionsManager;
|
||||
getCardElementManager(): CardElementManager;
|
||||
getTriggersManager(): TriggersManager;
|
||||
}
|
||||
|
||||
@@ -244,6 +244,8 @@ export class ViewManager {
|
||||
camera: view.camera,
|
||||
displayMode: view.displayMode ?? undefined,
|
||||
});
|
||||
|
||||
this._api.getTriggersManager().updateView(oldView);
|
||||
this._api.getCardElementManager().update();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -241,7 +241,7 @@ class FrigateCard extends LitElement {
|
||||
const cardClasses = {
|
||||
triggered:
|
||||
!!this._controller.getTriggersManager().isTriggered() &&
|
||||
!!this._config?.view.scan.show_trigger_status,
|
||||
!!this._config?.view.scan.trigger_show_status,
|
||||
};
|
||||
const mainClasses = {
|
||||
main: true,
|
||||
|
||||
+77
-5
@@ -1,3 +1,43 @@
|
||||
// TODO: Config migration
|
||||
// TODO: Editor support for scan mode changes
|
||||
// TODO: Consider this:
|
||||
|
||||
/*
|
||||
// NOW ===>
|
||||
view:
|
||||
scan:
|
||||
enabled: true
|
||||
trigger_show_status: true,
|
||||
trigger_action:
|
||||
- action: custom:frigate-card-action
|
||||
frigate_card_action: camera_select
|
||||
triggered: true
|
||||
- action: custom:frigate-card-action
|
||||
frigate_card_action: live
|
||||
untrigger_action:
|
||||
- action: custom:frigate-card-action
|
||||
interaction_mode: inactive
|
||||
trigger_filter_camera: all
|
||||
untrigger_seconds: 0
|
||||
|
||||
view:
|
||||
scan:
|
||||
enabled: true
|
||||
|
||||
// TO
|
||||
|
||||
view:
|
||||
scan:
|
||||
enabled: true
|
||||
trigger_show_status: true
|
||||
actions:
|
||||
live | live-reset | none
|
||||
interaction: inactive | active | all
|
||||
trigger_filter_camera: all
|
||||
untrigger_seconds: 0
|
||||
automations:
|
||||
*/
|
||||
|
||||
import {
|
||||
CallServiceActionConfig,
|
||||
ConfirmationRestrictionConfig,
|
||||
@@ -241,7 +281,8 @@ const frigateCardGeneralActionSchema = frigateCardCustomActionsBaseSchema.extend
|
||||
|
||||
const frigateCardCameraSelectActionSchema = frigateCardCustomActionsBaseSchema.extend({
|
||||
frigate_card_action: z.literal('camera_select'),
|
||||
camera: z.string(),
|
||||
camera: z.string().optional(),
|
||||
triggered: z.boolean().optional(),
|
||||
});
|
||||
|
||||
const frigateCardLiveDependencySelectActionSchema =
|
||||
@@ -1119,17 +1160,48 @@ const viewConfigDefault = {
|
||||
dark_mode: 'off' as const,
|
||||
scan: {
|
||||
enabled: false,
|
||||
show_trigger_status: true,
|
||||
trigger_show_status: true,
|
||||
trigger_action: [
|
||||
{
|
||||
action: 'custom:frigate-card-action' as const,
|
||||
frigate_card_action: 'camera_select' as const,
|
||||
triggered: true,
|
||||
},
|
||||
{
|
||||
action: 'custom:frigate-card-action' as const,
|
||||
frigate_card_action: 'live' as const,
|
||||
},
|
||||
],
|
||||
untrigger_action: {
|
||||
action: 'custom:frigate-card-action' as const,
|
||||
frigate_card_action: 'default' as const,
|
||||
},
|
||||
interaction_mode: 'inactive' as const,
|
||||
trigger_filter_camera: 'all' as const,
|
||||
untrigger_seconds: 0,
|
||||
untrigger_reset: true,
|
||||
},
|
||||
};
|
||||
|
||||
const scanSchema = z.object({
|
||||
enabled: z.boolean().default(viewConfigDefault.scan.enabled),
|
||||
show_trigger_status: z.boolean().default(viewConfigDefault.scan.show_trigger_status),
|
||||
|
||||
interaction_mode: z
|
||||
.enum(['all', 'inactive', 'active'])
|
||||
.default(viewConfigDefault.scan.interaction_mode),
|
||||
trigger_filter_camera: z
|
||||
.enum(['all', 'selected'])
|
||||
.default(viewConfigDefault.scan.trigger_filter_camera),
|
||||
trigger_show_status: z.boolean().default(viewConfigDefault.scan.trigger_show_status),
|
||||
trigger_action: actionSchema
|
||||
.or(actionSchema.array())
|
||||
.nullable()
|
||||
.default(viewConfigDefault.scan.trigger_action),
|
||||
|
||||
untrigger_action: actionSchema
|
||||
.or(actionSchema.array())
|
||||
.nullable()
|
||||
.default(viewConfigDefault.scan.untrigger_action),
|
||||
untrigger_seconds: z.number().default(viewConfigDefault.scan.untrigger_seconds),
|
||||
untrigger_reset: z.boolean().default(viewConfigDefault.scan.untrigger_reset),
|
||||
});
|
||||
export type ScanOptions = z.infer<typeof scanSchema>;
|
||||
|
||||
|
||||
+2
-4
@@ -77,10 +77,8 @@ export const CONF_VIEW_UPDATE_FORCE = `${CONF_VIEW}.update_force` as const;
|
||||
export const CONF_VIEW_UPDATE_SECONDS = `${CONF_VIEW}.update_seconds` as const;
|
||||
export const CONF_VIEW_SCAN = `${CONF_VIEW}.scan` as const;
|
||||
export const CONF_VIEW_SCAN_ENABLED = `${CONF_VIEW_SCAN}.enabled` as const;
|
||||
export const CONF_VIEW_SCAN_SHOW_TRIGGER_STATUS =
|
||||
`${CONF_VIEW_SCAN}.show_trigger_status` as const;
|
||||
export const CONF_VIEW_SCAN_UNTRIGGER_RESET =
|
||||
`${CONF_VIEW_SCAN}.untrigger_reset` as const;
|
||||
export const CONF_VIEW_SCAN_TRIGGER_SHOW_STATUS =
|
||||
`${CONF_VIEW_SCAN}.trigger_show_status` as const;
|
||||
export const CONF_VIEW_SCAN_UNTRIGGER_SECONDS =
|
||||
`${CONF_VIEW_SCAN}.untrigger_seconds` as const;
|
||||
|
||||
|
||||
+4
-9
@@ -182,8 +182,7 @@ import {
|
||||
CONF_VIEW_DEFAULT,
|
||||
CONF_VIEW_SCAN,
|
||||
CONF_VIEW_SCAN_ENABLED,
|
||||
CONF_VIEW_SCAN_SHOW_TRIGGER_STATUS,
|
||||
CONF_VIEW_SCAN_UNTRIGGER_RESET,
|
||||
CONF_VIEW_SCAN_TRIGGER_SHOW_STATUS,
|
||||
CONF_VIEW_SCAN_UNTRIGGER_SECONDS,
|
||||
CONF_VIEW_TIMEOUT_SECONDS,
|
||||
CONF_VIEW_UPDATE_CYCLE_CAMERA,
|
||||
@@ -902,16 +901,12 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
||||
},
|
||||
)}
|
||||
${this._renderSwitch(
|
||||
CONF_VIEW_SCAN_SHOW_TRIGGER_STATUS,
|
||||
this._defaults.view.scan.show_trigger_status,
|
||||
CONF_VIEW_SCAN_TRIGGER_SHOW_STATUS,
|
||||
this._defaults.view.scan.trigger_show_status,
|
||||
{
|
||||
label: localize(`config.${CONF_VIEW_SCAN_SHOW_TRIGGER_STATUS}`),
|
||||
label: localize(`config.${CONF_VIEW_SCAN_TRIGGER_SHOW_STATUS}`),
|
||||
},
|
||||
)}
|
||||
${this._renderSwitch(
|
||||
CONF_VIEW_SCAN_UNTRIGGER_RESET,
|
||||
this._defaults.view.scan.untrigger_reset,
|
||||
)}
|
||||
${this._renderNumberInput(CONF_VIEW_SCAN_UNTRIGGER_SECONDS, {
|
||||
default: this._defaults.view.scan.untrigger_seconds,
|
||||
})}
|
||||
|
||||
@@ -387,7 +387,7 @@
|
||||
"scan": {
|
||||
"enabled": "Scan mode enabled",
|
||||
"scan_mode": "Scan mode",
|
||||
"show_trigger_status": "Show pulsing border when triggered",
|
||||
"trigger_show_status": "Show pulsing border when triggered",
|
||||
"untrigger_reset": "Reset the view to default after untrigger",
|
||||
"untrigger_seconds": "Seconds after inactive state change to untrigger"
|
||||
},
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
"scan": {
|
||||
"enabled": "Modalità di scansione abilitata",
|
||||
"scan_mode": "Modalità di scansione",
|
||||
"show_trigger_status": "Mostra bordo pulsante quando attivato",
|
||||
"trigger_show_status": "Mostra bordo pulsante quando attivato",
|
||||
"untrigger_reset": "Reset the view to default after untrigger",
|
||||
"untrigger_seconds": "Reimposta la vista ai valori predefiniti dopo aver annullato l'attivazione"
|
||||
},
|
||||
|
||||
@@ -386,7 +386,7 @@
|
||||
"scan": {
|
||||
"enabled": "Modo scan ativado",
|
||||
"scan_mode": "Modo scan",
|
||||
"show_trigger_status": "Pulsar borda quando acionado",
|
||||
"trigger_show_status": "Pulsar borda quando acionado",
|
||||
"untrigger_reset": "Redefinir a visualização para o padrão após desacionar",
|
||||
"untrigger_seconds": "Segundos após a mudar para o estado inativo para desacionar"
|
||||
},
|
||||
|
||||
@@ -376,7 +376,7 @@
|
||||
"scan": {
|
||||
"enabled": "Modo scan ativado",
|
||||
"scan_mode": "Modo scan",
|
||||
"show_trigger_status": "Exibir estado do gatilho",
|
||||
"trigger_show_status": "Exibir estado do gatilho",
|
||||
"untrigger_reset": "Redefinir a visualização para o padrão após desacionar",
|
||||
"untrigger_seconds": "Segundos após a mudar para o estado inativo para desacionar"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user