docs: Add special case warning for fullscreen condition (#2373)

This commit is contained in:
Dermot Duffy
2026-02-23 18:59:41 -08:00
committed by GitHub
parent d5e1e02328
commit 753cf02d90
5 changed files with 68 additions and 17 deletions
+11 -1
View File
@@ -92,7 +92,17 @@ conditions:
## `fullscreen` ## `fullscreen`
Matches based on whether the card is in fullscreen. Matches based on whether the card (or media within it) is in fullscreen mode.
> [!WARNING]
> When fullscreen is entered via a video player's built-in controls (rather than
> the card's own fullscreen [action](actions/custom/README.md) or menu button),
> the browser fullscreens the video element itself rather than the card. Any
> automation action that replaces that video element (e.g. switching substreams)
> will immediately exit fullscreen. A partial workaround may be to use the
> card's fullscreen action instead. See [Fullscreen with HD substream
> switching](../examples.md?id=fullscreen-with-hd-substream-switching) for an
> approach that combines substream switching with the card's fullscreen.
```yaml ```yaml
conditions: conditions:
+55
View File
@@ -43,6 +43,12 @@ This example will automatically turn on the first configured substream when the
card is put in fullscreen mode, and turn off the substream when exiting card is put in fullscreen mode, and turn off the substream when exiting
fullscreen mode. fullscreen mode.
> [!WARNING]
> When fullscreen is entered via a video player's built-in controls (rather than
> the card's fullscreen menu button), automation actions that replace _that_ video
> element (e.g. switching substreams from one video to another) will immediately exit fullscreen (as the browser sees the video the user clicked on be destroyed). See the
> [fullscreen condition](configuration/conditions.md?id=fullscreen) for details.
```yaml ```yaml
type: custom:advanced-camera-card type: custom:advanced-camera-card
cameras: cameras:
@@ -77,6 +83,55 @@ automations:
advanced_camera_card_action: live_substream_off advanced_camera_card_action: live_substream_off
``` ```
### Fullscreen with display mode and substream switching
This example adds a custom menu button that switches to single display mode,
activates the HD substream, and enters card fullscreen — all in a single tap.
An automation restores the grid layout and substream when fullscreen is exited.
This is useful in [grid](configuration/live.md) layouts where the card's
standard fullscreen button would show all cameras rather than a single HD
stream.
```yaml
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
dependencies:
cameras:
- office_hd
- camera_entity: camera.office_hd
title: Office HD
id: office_hd
capabilities:
disable_except:
- substream
live:
display:
mode: grid
elements:
- type: custom:advanced-camera-card-menu-icon
icon: mdi:fullscreen
title: Fullscreen HD
tap_action:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: display_mode_select
display_mode: single
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_on
- action: custom:advanced-camera-card-action
advanced_camera_card_action: fullscreen
automations:
- conditions:
- condition: fullscreen
fullscreen: false
actions:
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_off
- action: custom:advanced-camera-card-action
advanced_camera_card_action: display_mode_select
display_mode: grid
```
### Responding to key input ### Responding to key input
In addition to a handful of reconfigurable [built-in keyboard shortcuts](./usage/keyboard-shortcuts.md), `automations` can be used to take any action based on any keyboard input. These examples use [`key` conditions](./configuration/conditions.md?id=key) to assess keyboard state before taking action. In addition to a handful of reconfigurable [built-in keyboard shortcuts](./usage/keyboard-shortcuts.md), `automations` can be used to take any action based on any keyboard input. These examples use [`key` conditions](./configuration/conditions.md?id=key) to assess keyboard state before taking action.
-1
View File
@@ -28,7 +28,6 @@
"component-emitter": "^1.3.1", "component-emitter": "^1.3.1",
"compute-scroll-into-view": "^3.1.1", "compute-scroll-into-view": "^3.1.1",
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"date-fns-tz": "^3.1.3",
"embla-carousel": "^8.6.0", "embla-carousel": "^8.6.0",
"embla-carousel-wheel-gestures": "^8.0.1", "embla-carousel-wheel-gestures": "^8.0.1",
"ha-nunjucks": "^1.3.0", "ha-nunjucks": "^1.3.0",
+2 -5
View File
@@ -1,4 +1,3 @@
import { toZonedTime } from 'date-fns-tz';
import { CameraConfig } from '../../config/schema/cameras'; import { CameraConfig } from '../../config/schema/cameras';
import { Severity } from '../../severity'; import { Severity } from '../../severity';
import { formatDateAndTime, prettifyTitle } from '../../utils/basic'; import { formatDateAndTime, prettifyTitle } from '../../utils/basic';
@@ -14,7 +13,6 @@ import {
* @param event * @param event
*/ */
export const getEventTitle = (event: FrigateEvent): string => { export const getEventTitle = (event: FrigateEvent): string => {
const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const durationSeconds = Math.round( const durationSeconds = Math.round(
event.end_time event.end_time
? event.end_time - event.start_time ? event.end_time - event.start_time
@@ -23,7 +21,7 @@ export const getEventTitle = (event: FrigateEvent): string => {
const score = event.top_score !== null ? ` ${Math.round(event.top_score * 100)}%` : ''; const score = event.top_score !== null ? ` ${Math.round(event.top_score * 100)}%` : '';
return `${formatDateAndTime( return `${formatDateAndTime(
toZonedTime(event.start_time * 1000, localTimezone), new Date(event.start_time * 1000),
)} [${durationSeconds}s, ${prettifyTitle(event.label)}${score}]`; )} [${durationSeconds}s, ${prettifyTitle(event.label)}${score}]`;
}; };
@@ -115,7 +113,6 @@ export const getReviewTitle = (review: FrigateReview): string => {
return objects; return objects;
} }
const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const durationSeconds = Math.round( const durationSeconds = Math.round(
review.end_time review.end_time
? review.end_time - review.start_time ? review.end_time - review.start_time
@@ -123,7 +120,7 @@ export const getReviewTitle = (review: FrigateReview): string => {
); );
return `${formatDateAndTime( return `${formatDateAndTime(
toZonedTime(review.start_time * 1000, localTimezone), new Date(review.start_time * 1000),
)} [${durationSeconds}s${objects}]`; )} [${durationSeconds}s${objects}]`;
}; };
-10
View File
@@ -2497,7 +2497,6 @@ __metadata:
compute-scroll-into-view: "npm:^3.1.1" compute-scroll-into-view: "npm:^3.1.1"
conventional-changelog-conventionalcommits: "npm:^8.0.0" conventional-changelog-conventionalcommits: "npm:^8.0.0"
date-fns: "npm:^3.6.0" date-fns: "npm:^3.6.0"
date-fns-tz: "npm:^3.1.3"
docsify-cli: "npm:^4.4.4" docsify-cli: "npm:^4.4.4"
embla-carousel: "npm:^8.6.0" embla-carousel: "npm:^8.6.0"
embla-carousel-wheel-gestures: "npm:^8.0.1" embla-carousel-wheel-gestures: "npm:^8.0.1"
@@ -4014,15 +4013,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"date-fns-tz@npm:^3.1.3":
version: 3.1.3
resolution: "date-fns-tz@npm:3.1.3"
peerDependencies:
date-fns: ^3.0.0
checksum: 10c0/dcedf178a96632a798966cf5a881441aefc451cc308336a98919e49c2df8eff7a302d19b9d3903c50838dd0912533f862f0bfb9429e8c28c1c3ce5da19ccb64e
languageName: node
linkType: hard
"date-fns@npm:^3.6.0": "date-fns@npm:^3.6.0":
version: 3.6.0 version: 3.6.0
resolution: "date-fns@npm:3.6.0" resolution: "date-fns@npm:3.6.0"