Initial fullscreen functionality.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
"dayjs": "^1.10.6",
|
||||
"home-assistant-js-websocket": "^5.11.1",
|
||||
"lit": "^2.0.0-rc.2",
|
||||
"screenfull": "^5.1.0",
|
||||
"zod": "^3.8.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
+33
@@ -17,6 +17,7 @@ import {
|
||||
getLovelace,
|
||||
stateIcon,
|
||||
} from 'custom-card-helpers';
|
||||
import screenfull from 'screenfull';
|
||||
|
||||
import { MenuButton, frigateCardConfigSchema } from './types';
|
||||
import type {
|
||||
@@ -191,6 +192,13 @@ export class FrigateCard extends LitElement {
|
||||
description: localize('menu.frigate_ui'),
|
||||
});
|
||||
}
|
||||
if ((this.config.menu_buttons?.fullscreen ?? false) && screenfull.isEnabled) {
|
||||
buttons.set('fullscreen', {
|
||||
icon: screenfull.isFullscreen ? 'mdi:fullscreen-exit' : 'mdi:fullscreen',
|
||||
description: localize('menu.fullscreen'),
|
||||
});
|
||||
}
|
||||
|
||||
const entities = this.config.entities || [];
|
||||
for (let i = 0; this._hass && i < entities.length; i++) {
|
||||
if (!entities[i].show) {
|
||||
@@ -294,6 +302,11 @@ export class FrigateCard extends LitElement {
|
||||
window.open(frigate_url);
|
||||
}
|
||||
break;
|
||||
case 'fullscreen':
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.toggle(this);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// If it's unknown, it's assumed to be an entity_id.
|
||||
fireEvent(this, 'hass-more-info', { entityId: name });
|
||||
@@ -383,6 +396,25 @@ export class FrigateCard extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
protected _fullScreenHandler(): void {
|
||||
// Re-render after a change to fullscreen mode to take advantage of
|
||||
// the expanded screen real-estate (vs staying in aspect-ratio locked
|
||||
// modes).
|
||||
this.requestUpdate();
|
||||
}
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.on('change', this._fullScreenHandler.bind(this));
|
||||
}
|
||||
}
|
||||
disconnectedCallback(): void {
|
||||
if (screenfull.isEnabled) {
|
||||
screenfull.off('change', this._fullScreenHandler.bind(this));
|
||||
}
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
protected _getAspectRatioPadding(): number | null {
|
||||
const aspect_ratio_mode = this.config.dimensions?.aspect_ratio_mode ?? 'dynamic';
|
||||
|
||||
@@ -391,6 +423,7 @@ export class FrigateCard extends LitElement {
|
||||
// dynamic mode (as the aspect_ratio is essentially whatever the media
|
||||
// dimensions are).
|
||||
if (
|
||||
(screenfull.isEnabled && screenfull.isFullscreen) ||
|
||||
aspect_ratio_mode == 'unconstrained' ||
|
||||
(!this._view.isGalleryView() && aspect_ratio_mode == 'dynamic' && this._mediaInfo)
|
||||
) {
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
"snapshots": "Snapshots Gallery",
|
||||
"clip": "Latest Clip",
|
||||
"snapshot": "Latest Snapshot",
|
||||
"frigate_ui": "Frigate User Interface"
|
||||
"frigate_ui": "Frigate User Interface",
|
||||
"fullscreen": "Fullscreen"
|
||||
},
|
||||
"control": {
|
||||
"nextprev": "Media Next & Previous Controls",
|
||||
@@ -93,7 +94,6 @@
|
||||
"could_not_resolve": "Could not resolve media URL",
|
||||
"no_live_camera": "No live camera",
|
||||
"invalid_configuration": "Invalid configuration",
|
||||
"missing_webrtc": "WebRTC component not found",
|
||||
"internal": "Internal error"
|
||||
"missing_webrtc": "WebRTC component not found"
|
||||
}
|
||||
}
|
||||
|
||||
+36
-2
@@ -1,5 +1,7 @@
|
||||
.container {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.frigate-card-contents {
|
||||
@@ -8,6 +10,11 @@
|
||||
overflow: auto;
|
||||
-ms-overflow-style: none; /* Hide scrollbar: IE and Edge */
|
||||
scrollbar-width: none; /* Hide scrollbar: Firefox */
|
||||
|
||||
// Vertically align items in case the container is larger than the media (e.g.
|
||||
// fullscreen mode, or forced aspect ratios).
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Hide scrollbar for Chrome, Safari and Opera */
|
||||
@@ -15,7 +22,7 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* The 'hover' menu mode is styling applied outside of the menu itself */
|
||||
/* When forcing aspect ratio absolute positioning is required */
|
||||
.frigate-card-contents.absolute {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
@@ -24,7 +31,7 @@
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
/* Support the 'hover' menu mode. */
|
||||
/* The 'hover' menu mode is styling applied outside of the menu itself */
|
||||
.hover-menu {
|
||||
z-index: 1;
|
||||
transition: all 0.5s ease;
|
||||
@@ -50,4 +57,31 @@ ha-card {
|
||||
|
||||
ha-card a {
|
||||
color: var(--primary-text-color, white);
|
||||
}
|
||||
|
||||
frigate-card-gallery, frigate-card-viewer, frigate-card-live {
|
||||
width: 100%;
|
||||
}
|
||||
frigate-card-gallery {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// Browsers will reject invalid whole CSS selectors if one selector is bad, so
|
||||
// need to use mixin here instead of just comma-separated selectors.
|
||||
// - Related: https://stackoverflow.com/questions/16982449/why-isnt-it-possible-to-combine-vendor-specific-pseudo-elements-classes-into-on
|
||||
@mixin fullscreen-ha-card {
|
||||
// Make the background black, to give it the expected fullscreen feel.
|
||||
background-color: black;
|
||||
}
|
||||
:host(:fullscreen) ha-card {
|
||||
@include fullscreen-ha-card;
|
||||
}
|
||||
:host(:-webkit-full-screen) ha-card {
|
||||
@include fullscreen-ha-card;
|
||||
}
|
||||
:host(:-moz-full-screen) ha-card {
|
||||
@include fullscreen-ha-card;
|
||||
}
|
||||
:host(:-webkit-full-screen) ha-card {
|
||||
@include fullscreen-ha-card;
|
||||
}
|
||||
@@ -82,6 +82,7 @@ export const frigateCardConfigSchema = z.object({
|
||||
clips: z.boolean().default(true),
|
||||
snapshots: z.boolean().default(true),
|
||||
frigate_ui: z.boolean().default(true),
|
||||
fullscreen: z.boolean().default(false),
|
||||
})
|
||||
.optional(),
|
||||
entities: z
|
||||
|
||||
Reference in New Issue
Block a user