Support executing actions from the query string.
This commit is contained in:
1 parent
ad22ee7e00
commit
292a8083d7
6 files changed
+209
-11
No files matched your search
+24
-7
@@ -92,6 +92,7 @@ import merge from 'lodash-es/merge';
|
||||
import { FrigateCardInitializer } from './utils/initializer.js';
|
||||
import 'web-dialog';
|
||||
import { downloadMedia } from './utils/download.js';
|
||||
import { getActionsFromQueryString } from './utils/querystring.js';
|
||||
|
||||
/** A note on media callbacks:
|
||||
*
|
||||
@@ -1398,15 +1399,26 @@ class FrigateCard extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a request for a card action.
|
||||
* @param ev The action requested.
|
||||
*/
|
||||
protected _cardActionHandler(ev: CustomEvent<ActionType>): void {
|
||||
protected _cardActionEventHandler(ev: CustomEvent<ActionType>): void {
|
||||
const frigateCardAction = convertActionToFrigateCardCustomAction(ev.detail);
|
||||
if (!this._view || !frigateCardAction) {
|
||||
if (frigateCardAction) {
|
||||
this._cardActionHandler(frigateCardAction);
|
||||
}
|
||||
}
|
||||
|
||||
protected _cardActionHandler(frigateCardAction: FrigateCardCustomAction): void {
|
||||
if (!this._view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
frigateCardAction.card_id &&
|
||||
this._getConfig().card_id !== frigateCardAction.card_id
|
||||
) {
|
||||
// Command not intended for this card (e.g. query string command).
|
||||
return;
|
||||
}
|
||||
|
||||
const action = frigateCardAction.frigate_card_action;
|
||||
|
||||
switch (action) {
|
||||
@@ -1985,7 +1997,7 @@ class FrigateCard extends LitElement {
|
||||
class="${classMap(cardClasses)}"
|
||||
style="${styleMap(cardStyle)}"
|
||||
@action=${(ev: CustomEvent) => this._actionHandler(ev, actions)}
|
||||
@ll-custom=${this._cardActionHandler.bind(this)}
|
||||
@ll-custom=${this._cardActionEventHandler.bind(this)}
|
||||
@frigate-card:message=${this._messageHandler.bind(this)}
|
||||
@frigate-card:view:change=${this._changeViewHandler.bind(this)}
|
||||
@frigate-card:view:change-context=${this._addViewContextHandler.bind(this)}
|
||||
@@ -2116,6 +2128,11 @@ class FrigateCard extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
protected firstUpdated(): void {
|
||||
// Execute query string actions after first render is complete.
|
||||
getActionsFromQueryString().forEach((action) => this._cardActionHandler(action));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return compiled CSS styles (thus safe to use with unsafeCSS).
|
||||
*/
|
||||
|
||||
@@ -52,9 +52,9 @@ export function getLanguage(hass?: HomeAssistant): string {
|
||||
export const loadLanguages = async (hass: HomeAssistant): Promise<void> => {
|
||||
const lang = getLanguage(hass);
|
||||
if (lang === 'it') {
|
||||
languages['it'] = await import('./languages/it.json');
|
||||
languages[lang] = await import('./languages/it.json');
|
||||
} else if (lang === 'pt_BR') {
|
||||
languages['pt_BR'] = await import('./languages/pt-BR.json');
|
||||
languages[lang] = await import('./languages/pt-BR.json');
|
||||
}
|
||||
|
||||
if (lang) {
|
||||
|
||||
@@ -205,6 +205,9 @@ const frigateCardCustomActionsBaseSchema = customActionSchema.extend({
|
||||
// Syntactic sugar to avoid 'fire-dom-event' as part of an external API.
|
||||
.transform((): 'fire-dom-event' => 'fire-dom-event')
|
||||
.or(z.literal('fire-dom-event')),
|
||||
|
||||
// Card this command is intended for.
|
||||
card_id: z.string().optional(),
|
||||
});
|
||||
|
||||
const FRIGATE_CARD_GENERAL_ACTIONS = [
|
||||
@@ -1316,6 +1319,9 @@ export const frigateCardConfigSchema = z.object({
|
||||
// Support for card_mod (https://github.com/thomasloven/lovelace-card-mod).
|
||||
card_mod: z.unknown(),
|
||||
|
||||
// Card ID (used for query string commands).
|
||||
card_id: z.string().optional(),
|
||||
|
||||
// Stock lovelace card config.
|
||||
type: z.string(),
|
||||
test_gui: z.boolean().optional(),
|
||||
|
||||
+5
-1
@@ -19,7 +19,7 @@ import {
|
||||
* @returns A FrigateCardCustomAction or null if it cannot be converted.
|
||||
*/
|
||||
export function convertActionToFrigateCardCustomAction(
|
||||
action: ActionType | null,
|
||||
action: unknown,
|
||||
): FrigateCardCustomAction | null {
|
||||
if (!action) {
|
||||
return null;
|
||||
@@ -38,6 +38,7 @@ export function convertActionToFrigateCardCustomAction(
|
||||
export function createFrigateCardCustomAction(
|
||||
action: FrigateCardAction,
|
||||
args?: {
|
||||
cardID?: string;
|
||||
camera?: string;
|
||||
media_player?: string;
|
||||
media_player_action?: 'play' | 'stop';
|
||||
@@ -51,6 +52,7 @@ export function createFrigateCardCustomAction(
|
||||
action: 'fire-dom-event',
|
||||
frigate_card_action: action,
|
||||
camera: args.camera as string,
|
||||
...(args.cardID && { card_id: args.cardID})
|
||||
};
|
||||
}
|
||||
if (action === 'media_player') {
|
||||
@@ -62,11 +64,13 @@ export function createFrigateCardCustomAction(
|
||||
frigate_card_action: action,
|
||||
media_player: args.media_player,
|
||||
media_player_action: args.media_player_action,
|
||||
...(args.cardID && { card_id: args.cardID})
|
||||
};
|
||||
}
|
||||
return {
|
||||
action: 'fire-dom-event',
|
||||
frigate_card_action: action,
|
||||
...(args?.cardID && { card_id: args.cardID})
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { FrigateCardCustomAction } from '../types';
|
||||
import { createFrigateCardCustomAction } from './action.js';
|
||||
|
||||
export const getActionsFromQueryString = (): FrigateCardCustomAction[] => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const actions: FrigateCardCustomAction[] = [];
|
||||
const actionRE = new RegExp(/^frigate-card-action(\/(?<cardID>\w+))?\/(?<action>\w+)/);
|
||||
|
||||
for (const [key, value] of params.entries()) {
|
||||
const match = key.match(actionRE);
|
||||
if (!match || !match.groups) {
|
||||
continue;
|
||||
}
|
||||
const cardID: string | undefined = match.groups['cardID'];
|
||||
const action = match.groups['action'];
|
||||
|
||||
let customAction: FrigateCardCustomAction | null = null;
|
||||
switch (action) {
|
||||
case 'camera_select':
|
||||
case 'live_substream_select':
|
||||
if (value) {
|
||||
customAction = createFrigateCardCustomAction(action, {
|
||||
camera: value,
|
||||
cardID: cardID,
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'camera_ui':
|
||||
case 'clip':
|
||||
case 'clips':
|
||||
case 'default':
|
||||
case 'diagnostics':
|
||||
case 'download':
|
||||
case 'expand_toggle':
|
||||
case 'image':
|
||||
case 'live':
|
||||
case 'menu_toggle':
|
||||
case 'recording':
|
||||
case 'recordings':
|
||||
case 'snapshot':
|
||||
case 'snapshots':
|
||||
case 'timeline':
|
||||
customAction = createFrigateCardCustomAction(action, {
|
||||
cardID: cardID,
|
||||
});
|
||||
break;
|
||||
default:
|
||||
console.warn(
|
||||
`Frigate card received unknown card action in query string: ${action}`,
|
||||
);
|
||||
}
|
||||
if (customAction) {
|
||||
actions.push(customAction);
|
||||
}
|
||||
}
|
||||
return actions;
|
||||
};
|
||||
Reference in new issue
Block a user