Add 'image' view.
This commit is contained in:
+2
-1
@@ -21,12 +21,13 @@
|
|||||||
"home-assistant-js-websocket": "^5.11.1",
|
"home-assistant-js-websocket": "^5.11.1",
|
||||||
"lit": "^2.0.2",
|
"lit": "^2.0.2",
|
||||||
"screenfull": "^5.1.0",
|
"screenfull": "^5.1.0",
|
||||||
"zod": "^3.9.8"
|
"zod": "^3.10.0-beta.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.15.8",
|
"@babel/core": "^7.15.8",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||||
"@babel/plugin-proposal-decorators": "^7.15.8",
|
"@babel/plugin-proposal-decorators": "^7.15.8",
|
||||||
|
"@rollup/plugin-image": "^2.1.1",
|
||||||
"@rollup/plugin-json": "^4.1.0",
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||||
"@typescript-eslint/parser": "^4.33.0",
|
"@typescript-eslint/parser": "^4.33.0",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { terser } from 'rollup-plugin-terser';
|
|||||||
import serve from 'rollup-plugin-serve';
|
import serve from 'rollup-plugin-serve';
|
||||||
import json from '@rollup/plugin-json';
|
import json from '@rollup/plugin-json';
|
||||||
import styles from 'rollup-plugin-styles';
|
import styles from 'rollup-plugin-styles';
|
||||||
|
import image from '@rollup/plugin-image';
|
||||||
|
|
||||||
const dev = process.env.ROLLUP_WATCH;
|
const dev = process.env.ROLLUP_WATCH;
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ const plugins = [
|
|||||||
includePaths: ['./node_modules/'],
|
includePaths: ['./node_modules/'],
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
image(),
|
||||||
nodeResolve({}),
|
nodeResolve({}),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
typescript(),
|
typescript(),
|
||||||
|
|||||||
+25
-2
@@ -31,6 +31,7 @@ import type {
|
|||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
import { CARD_VERSION, REPO_URL } from './const';
|
import { CARD_VERSION, REPO_URL } from './const';
|
||||||
|
import { FrigateCardElements } from './components/elements';
|
||||||
import { FrigateCardMenu, MENU_HEIGHT } from './components/menu';
|
import { FrigateCardMenu, MENU_HEIGHT } from './components/menu';
|
||||||
import { View } from './view';
|
import { View } from './view';
|
||||||
import { homeAssistantWSRequest, shouldUpdateBasedOnHass } from './common';
|
import { homeAssistantWSRequest, shouldUpdateBasedOnHass } from './common';
|
||||||
@@ -40,6 +41,7 @@ import { renderMessage, renderProgressIndicator } from './components/message';
|
|||||||
import './editor';
|
import './editor';
|
||||||
import './components/elements';
|
import './components/elements';
|
||||||
import './components/gallery';
|
import './components/gallery';
|
||||||
|
import './components/image';
|
||||||
import './components/live';
|
import './components/live';
|
||||||
import './components/menu';
|
import './components/menu';
|
||||||
import './components/message';
|
import './components/message';
|
||||||
@@ -48,7 +50,6 @@ import './patches/ha-camera-stream';
|
|||||||
import './patches/ha-hls-player';
|
import './patches/ha-hls-player';
|
||||||
|
|
||||||
import cardStyle from './scss/card.scss';
|
import cardStyle from './scss/card.scss';
|
||||||
import { FrigateCardElements } from './components/elements';
|
|
||||||
|
|
||||||
const MEDIA_HEIGHT_CUTOFF = 50;
|
const MEDIA_HEIGHT_CUTOFF = 50;
|
||||||
const MEDIA_WIDTH_CUTOFF = MEDIA_HEIGHT_CUTOFF;
|
const MEDIA_WIDTH_CUTOFF = MEDIA_HEIGHT_CUTOFF;
|
||||||
@@ -112,7 +113,7 @@ export class FrigateCard extends LitElement {
|
|||||||
|
|
||||||
// A small cache to avoid needing to create a new list of entities every time
|
// A small cache to avoid needing to create a new list of entities every time
|
||||||
// a hass update arrives.
|
// a hass update arrives.
|
||||||
protected _entitiesToMonitor: string[] | null = null;
|
protected _entitiesToMonitor: string[] = [];
|
||||||
|
|
||||||
// Information about the most recently loaded media item.
|
// Information about the most recently loaded media item.
|
||||||
protected _mediaInfo: MediaLoadInfo | null = null;
|
protected _mediaInfo: MediaLoadInfo | null = null;
|
||||||
@@ -197,6 +198,15 @@ export class FrigateCard extends LitElement {
|
|||||||
emphasize: this._view.is('snapshots'),
|
emphasize: this._view.is('snapshots'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (this.config.menu_buttons?.image ?? false) {
|
||||||
|
buttons.push({
|
||||||
|
type: 'internal-menu-icon',
|
||||||
|
card_action: 'image',
|
||||||
|
title: localize('menu.image'),
|
||||||
|
icon: 'mdi:image',
|
||||||
|
emphasize: this._view.is('image'),
|
||||||
|
});
|
||||||
|
}
|
||||||
if ((this.config.menu_buttons?.frigate_ui ?? true) && this.config.frigate_url) {
|
if ((this.config.menu_buttons?.frigate_ui ?? true) && this.config.frigate_url) {
|
||||||
buttons.push({
|
buttons.push({
|
||||||
type: 'internal-menu-icon',
|
type: 'internal-menu-icon',
|
||||||
@@ -357,6 +367,7 @@ export class FrigateCard extends LitElement {
|
|||||||
case 'frigate':
|
case 'frigate':
|
||||||
this._changeView();
|
this._changeView();
|
||||||
break;
|
break;
|
||||||
|
case 'image':
|
||||||
case 'live':
|
case 'live':
|
||||||
case 'clips':
|
case 'clips':
|
||||||
case 'snapshots':
|
case 'snapshots':
|
||||||
@@ -625,10 +636,22 @@ export class FrigateCard extends LitElement {
|
|||||||
const liveClasses = {
|
const liveClasses = {
|
||||||
hidden: this.config.live_preload && this._view.view != 'live',
|
hidden: this.config.live_preload && this._view.view != 'live',
|
||||||
};
|
};
|
||||||
|
const imageClasses = {
|
||||||
|
hidden: this.config.live_preload && this._view.view != 'image',
|
||||||
|
};
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div class="${classMap(pictureElementsClasses)}">
|
<div class="${classMap(pictureElementsClasses)}">
|
||||||
${this._message ? renderMessage(this._message) : ``}
|
${this._message ? renderMessage(this._message) : ``}
|
||||||
|
${!this._message && this._view.is('image')
|
||||||
|
? html` <frigate-card-image
|
||||||
|
.image=${this.config.image}
|
||||||
|
class="${classMap(imageClasses)}"
|
||||||
|
@frigate-card:media-load=${this._mediaLoadHandler}
|
||||||
|
@frigate-card:message=${this._messageHandler}
|
||||||
|
>
|
||||||
|
</frigate-card-image>`
|
||||||
|
: ``}
|
||||||
${!this._message && this._view.isGalleryView()
|
${!this._message && this._view.isGalleryView()
|
||||||
? html` <frigate-card-gallery
|
? html` <frigate-card-gallery
|
||||||
.hass=${this._hass}
|
.hass=${this._hass}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
|
||||||
|
import { customElement, property } from 'lit/decorators';
|
||||||
|
|
||||||
|
import { dispatchMediaLoadEvent } from '../common';
|
||||||
|
|
||||||
|
import imageStyle from '../scss/image.scss';
|
||||||
|
import defaultImage from '../images/frigate-bird-in-sky.jpg'
|
||||||
|
|
||||||
|
@customElement('frigate-card-image')
|
||||||
|
export class FrigateCardImage extends LitElement {
|
||||||
|
@property({ attribute: false })
|
||||||
|
protected image?: string;
|
||||||
|
|
||||||
|
protected render(): TemplateResult | void {
|
||||||
|
return html` <img
|
||||||
|
src=${this.image || defaultImage}
|
||||||
|
@load=${(e) => {
|
||||||
|
dispatchMediaLoadEvent(this, e);
|
||||||
|
}}
|
||||||
|
>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return unsafeCSS(imageStyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+1
@@ -1 +1,2 @@
|
|||||||
declare module '*.scss';
|
declare module '*.scss';
|
||||||
|
declare module '*.jpg';
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
|||||||
snapshots: localize('menu.snapshots'),
|
snapshots: localize('menu.snapshots'),
|
||||||
clip: localize('menu.clip'),
|
clip: localize('menu.clip'),
|
||||||
snapshot: localize('menu.snapshot'),
|
snapshot: localize('menu.snapshot'),
|
||||||
|
image: localize('menu.image'),
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuModes = {
|
const menuModes = {
|
||||||
@@ -382,6 +383,18 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor
|
|||||||
></ha-switch>
|
></ha-switch>
|
||||||
</ha-formfield>
|
</ha-formfield>
|
||||||
<br />
|
<br />
|
||||||
|
<ha-formfield
|
||||||
|
.label=${localize('editor.show_button') +
|
||||||
|
': ' +
|
||||||
|
localize('menu.image')}
|
||||||
|
>
|
||||||
|
<ha-switch
|
||||||
|
.checked=${this._config?.menu_buttons?.image ?? false}
|
||||||
|
.configValue=${'menu_buttons.image'}
|
||||||
|
@change=${this._valueChanged}
|
||||||
|
></ha-switch>
|
||||||
|
</ha-formfield>
|
||||||
|
<br />
|
||||||
<ha-formfield
|
<ha-formfield
|
||||||
.label=${localize('editor.show_button') +
|
.label=${localize('editor.show_button') +
|
||||||
': ' +
|
': ' +
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Image Copyright
|
||||||
|
|
||||||
|
## frigate-bird-in-sky.jpg
|
||||||
|
|
||||||
|
**Link**: https://www.flickr.com/photos/dianasch/47543120431
|
||||||
|
|
||||||
|
**Description**: A Frigate bird with a very large wingspan (7 ft) soaring overhead on Sanibel Island, Florida.
|
||||||
|
|
||||||
|
**Copyright**: Diana Robinson
|
||||||
|
|
||||||
|
**License**: https://creativecommons.org/licenses/by-nc-nd/2.0/
|
||||||
|
|
||||||
|
**Modifications**:
|
||||||
|
|
||||||
|
* Cropped for 16:9
|
||||||
|
* Scaled down to 420x277
|
||||||
|
* Gaussian blur 0.05
|
||||||
|
* Quality @ 50%
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
@@ -43,7 +43,8 @@
|
|||||||
"clip": "Latest Clip",
|
"clip": "Latest Clip",
|
||||||
"snapshot": "Latest Snapshot",
|
"snapshot": "Latest Snapshot",
|
||||||
"frigate_ui": "Frigate User Interface",
|
"frigate_ui": "Frigate User Interface",
|
||||||
"fullscreen": "Fullscreen"
|
"fullscreen": "Fullscreen",
|
||||||
|
"image": "Static Image"
|
||||||
},
|
},
|
||||||
"control": {
|
"control": {
|
||||||
"nextprev": "Media Next & Previous Controls",
|
"nextprev": "Media Next & Previous Controls",
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ export const FRIGATE_CARD_VIEWS = [
|
|||||||
'clips',
|
'clips',
|
||||||
'snapshot',
|
'snapshot',
|
||||||
'snapshots',
|
'snapshots',
|
||||||
|
'image'
|
||||||
] as const;
|
] as const;
|
||||||
export type FrigateCardView = typeof FRIGATE_CARD_VIEWS[number];
|
export type FrigateCardView = typeof FRIGATE_CARD_VIEWS[number];
|
||||||
|
|
||||||
@@ -263,6 +264,7 @@ export const frigateCardConfigSchema = z.object({
|
|||||||
.default(180),
|
.default(180),
|
||||||
live_provider: z.enum(LIVE_PROVIDERS).default('frigate'),
|
live_provider: z.enum(LIVE_PROVIDERS).default('frigate'),
|
||||||
live_preload: z.boolean().default(false),
|
live_preload: z.boolean().default(false),
|
||||||
|
image: z.string().optional(),
|
||||||
webrtc: z
|
webrtc: z
|
||||||
.object({
|
.object({
|
||||||
entity: z.string().optional(),
|
entity: z.string().optional(),
|
||||||
@@ -280,6 +282,7 @@ export const frigateCardConfigSchema = z.object({
|
|||||||
live: z.boolean().default(true),
|
live: z.boolean().default(true),
|
||||||
clips: z.boolean().default(true),
|
clips: z.boolean().default(true),
|
||||||
snapshots: z.boolean().default(true),
|
snapshots: z.boolean().default(true),
|
||||||
|
image: z.boolean().default(false),
|
||||||
frigate_ui: z.boolean().default(true),
|
frigate_ui: z.boolean().default(true),
|
||||||
fullscreen: z.boolean().default(true),
|
fullscreen: z.boolean().default(true),
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user