feat: Rename the card to advanced-camera-card (#1873)

Whilst the Frigate support in this card is the best among camera
engines, the name incorrectly suggests that Frigate is a requirement.
Instead, to broaden the appeal, change to more camera agnostic name.
This does not suggest any change in priority, role or support for
Frigate.

This change is likely to be bug prone, due to the size of the rename --
the code contains 1500+ references to "Frigate" most of which make sense
to rename, some which do not, all of which needed human assessment.

- Closes #1298


BREAKING CHANGE: References to `frigate-card` in all kinds of
configuration need to be updated to `advanced-camera-card`. An automated
config upgrade should take care of the majority of usecases (click `Edit
-> Upgrade -> Save`), though may not be perfect.
This commit is contained in:
Dermot Duffy
2025-02-06 19:32:32 -08:00
committed by GitHub
parent 43947b49dc
commit cc376a8be1
305 changed files with 4270 additions and 3686 deletions
+3 -3
View File
@@ -4,7 +4,7 @@
"key": "lovelace",
"data": {
"config": {
"title": "Frigate Card",
"title": "Advanced Camera Card",
"views": [
{
"theme": "Backend-selected",
@@ -13,8 +13,8 @@
"badges": [],
"cards": [
{
"type": "custom:frigate-card",
"name": "Frigate Card with Frigate Camera",
"type": "custom:advanced-camera-card",
"name": "Advanced Camera Card with Frigate Camera",
"cameras": [
{
"camera_entity": "camera.big_buck_bunny",
@@ -5,7 +5,7 @@
"data": {
"items": [
{
"url": "http://localhost:10001/frigate-hass-card.js",
"url": "http://localhost:10001/advanced-camera-card.js",
"type": "module",
"id": "00c459541bac4290af01c51bf9c06ba1"
}
+2 -2
View File
@@ -14,13 +14,13 @@ assignees: ''
**Checklist:**
- Please try updating to the [latest available version](https://github.com/dermotduffy/frigate-hass-card/releases).
- Please try updating to the [latest available version](https://github.com/dermotduffy/advanced-camera-card/releases).
- Please try clearing your browser cache.
**[REQUIRED] Card diagnostic information:**
<!--
On the card, hold down the Default/Frigate menu button for a few seconds then paste the diagnostics below. No help can be provided without this
On the card, hold down the Iris (default) menu button for a few seconds then paste the diagnostics *between* the pair of triple backticks below. No help can be provided without this.
-->
```yaml
+2 -2
View File
@@ -49,7 +49,7 @@ jobs:
- name: Upload javascript
uses: actions/upload-artifact@v4
with:
name: frigate-hass-card
name: advanced-camera-card
path: dist/*.js
# When this issue is fixed, it would be useful to upload visualizations:
@@ -57,5 +57,5 @@ jobs:
# - name: Upload visualizations
# uses: actions/upload-artifact@v4
# with:
# name: frigate-hass-card
# name: advanced-camera-card
# path: visualizations/*.html
+2 -2
View File
@@ -26,7 +26,7 @@ jobs:
with:
type: zip
path: dist
filename: frigate-hass-card.zip
filename: advanced-camera-card.zip
- name: Upload JS files to release
uses: svenstaro/upload-release-action@2.9.0
@@ -43,7 +43,7 @@ jobs:
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: frigate-hass-card.zip
file: advanced-camera-card.zip
tag: ${{ github.ref }}
overwrite: true
+1 -1
View File
@@ -50,7 +50,7 @@ jobs:
with:
type: zip
path: dist
filename: frigate-hass-card.zip
filename: advanced-camera-card.zip
- run: npx semantic-release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+8 -11
View File
@@ -2,20 +2,17 @@
<!-- markdownlint-disable fenced-code-language -->
<!-- markdownlint-disable no-inline-html -->
<img src="https://raw.githubusercontent.com/blakeblackshear/frigate-hass-integration/master/images/frigate.png"
alt="Frigate icon"
width="35%"
align="right"
style="float: right; margin: 10px 0px 20px 20px;" />
[![GitHub Release](https://img.shields.io/github/release/dermotduffy/frigate-hass-card.svg?style=flat-square)](https://github.com/dermotduffy/frigate-hass-card/releases)
[![Build Status](https://img.shields.io/github/actions/workflow/status/dermotduffy/frigate-hass-card/build.yml?style=flat-square)](https://github.com/dermotduffy/frigate-hass-card/actions/workflows/build.yml)
[![License](https://img.shields.io/github/license/dermotduffy/frigate-hass-card.svg?style=flat-square)](LICENSE)
[![GitHub Release](https://img.shields.io/github/release/dermotduffy/advanced-camera-card.svg?style=flat-square)](https://github.com/dermotduffy/advanced-camera-card/releases)
[![Build Status](https://img.shields.io/github/actions/workflow/status/dermotduffy/advanced-camera-card/build.yml?style=flat-square)](https://github.com/dermotduffy/advanced-camera-card/actions/workflows/build.yml)
[![License](https://img.shields.io/github/license/dermotduffy/advanced-camera-card.svg?style=flat-square)](LICENSE)
[![HACS](https://img.shields.io/badge/HACS-default-orange.svg?style=flat-square)](https://hacs.xyz)
[![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86&style=flat-square)](https://github.com/sponsors/dermotduffy)
<img src="https://raw.githubusercontent.com/dermotduffy/frigate-hass-card/main/docs/images/image-view.png" alt="Frigate Card" width="400px">
<img src="https://raw.githubusercontent.com/dermotduffy/advanced-camera-card/main/docs/images/advanced-camera-card.png" alt="Advanced Camera Card" width="500px">
# Frigate Card
# Advanced Camera Card
Formerly known as: `Frigate Card`
A comprehensive camera card for Home Assistant.
@@ -31,4 +28,4 @@ A comprehensive camera card for Home Assistant.
- Full [Picture Elements](https://www.home-assistant.io/lovelace/picture-elements/) support.
- Theme friendly.
See [full documentation](https://dermotduffy.github.io/frigate-hass-card).
See [full documentation](https://dermotduffy.github.io/advanced-camera-card).
+6 -4
View File
@@ -10,6 +10,8 @@
Home Assistant > HACS > Frontend > "Explore & Add Integrations" > Frigate Card
```
[](./common/rename-hacs.md ':include')
- Click `Download this repository with HACS`.
See [Advanced Installation](advanced-installation.md) for other installation resources, or [Rolling Back](./rolling-back.md) to rollback to prior versions.
@@ -23,14 +25,14 @@ See [Advanced Installation](advanced-installation.md) for other installation res
```
- Click `+ Add Card` shown on the bottom of the screen
- Choose `Custom: Frigate card` from the list
- Choose `Custom: Advanced Camera Card` from the list
## Initial configuration
### Minimal configuration
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
```
@@ -38,7 +40,7 @@ cameras:
### Video scrubbing configuration
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
profiles:
@@ -48,7 +50,7 @@ profiles:
### Multi-camera grid configuration
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
- camera_entity: camera.kitchen
+6 -4
View File
@@ -1,8 +1,10 @@
![logo](images/icons/frigate.svg)
![logo](images/icons/iris.svg ':size=48px')
# Frigate Card <small>6.0.0</small>
# Advanced Camera Card
> A comprehensive camera card for Home Assistant.
> A comprehensive camera card for Home Assistant
[GitHub](https://github.com/dermotduffy/frigate-hass-card/)
<small>FKA: Frigate Card</small>
[GitHub](https://github.com/dermotduffy/advanced-camera-card/)
[Documentation](README.md)
+5 -5
View File
@@ -14,7 +14,7 @@ For most users, HACS should automatically add the necessary resources. Should th
Three dots menu -> "Edit Dashboard" -> Three dots menu -> "Manage resources" -> "Add Resource"
```
- URL: `/hacsfiles/frigate-hass-card/frigate-hass-card.js`
- URL: `/hacsfiles/advanced-camera-card/advanced-camera-card.js`
- Resource type: `JavaScript Module`
#### Lovelace in "YAML mode" (rare)
@@ -26,7 +26,7 @@ You would see`mode: yaml` under `lovelace:` in your `configuration.yaml` if this
```yaml
lovelace:
resources:
- url: /hacsfiles/frigate-hass-card/frigate-hass-card.js
- url: /hacsfiles/advanced-camera-card/advanced-camera-card.js
type: module
```
@@ -34,15 +34,15 @@ lovelace:
### Manual installation
- Download the `frigate-hass-card.zip` attachment of the desired [release](https://github.com/dermotduffy/frigate-hass-card/releases) to a location accessible by Home Assistant. Note that the release will have a series of `.js` files (for HACS users) **and** a `frigate-hass-card.zip` for the convenience of manual installers.
- Unzip the file and move the contents of the `dist/` folder to any subfolder name you'd like, e.g. `frigate-card` is used in the below example.
- Download the `advanced-camera-card.zip` attachment of the desired [release](https://github.com/dermotduffy/advanced-camera-card/releases) to a location accessible by Home Assistant. Note that the release will have a series of `.js` files (for HACS users) **and** a `advanced-camera-card.zip` for the convenience of manual installers.
- Unzip the file and move the contents of the `dist/` folder to any subfolder name you'd like, e.g. `advanced-camera-card` is used in the below example.
- Add the location as a Lovelace resource via the UI, or via [YAML configuration](https://www.home-assistant.io/lovelace/dashboards/#resources) such as:
```yaml
lovelace:
mode: yaml
resources:
- url: /local/frigate-card/frigate-hass-card.js
- url: /local/advanced-camera-card/advanced-camera-card.js
type: module
```
+1
View File
@@ -0,0 +1 @@
?> This card was previously called `Frigate Card`. Until the rename is processed by HACS, use `Frigate Card` as the search term, thereafter it will be called `Advanced Camera Card`.
+1 -1
View File
@@ -5,7 +5,7 @@ The card supports a myriad of configuration options for simple or complex setups
### Minimal configuration
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
```
+5 -5
View File
@@ -10,15 +10,15 @@ variety of circumstances (e.g. tapping on a menu icon, double tapping on an
[element](../elements/README.md) or holding the mouse/tap down on a particular
[view](../view.md?id=supported-views)).
### Differences in actions between Frigate Card and Home Assistant
### Differences in actions between Advanced Camera Card and Home Assistant
Both the Home Assistant frontend and the Frigate card cooperate to provide
action functionality. In general, the Frigate Card functionality is a superset
Both the Home Assistant frontend and the Advanced Camera Card cooperate to provide
action functionality. In general, the Advanced Camera Card functionality is a superset
of that offered by stock Home Assistant.
Stock action functionality is used for Stock [Home Assistant picture
elements](https://www.home-assistant.io/lovelace/picture-elements/). Extended
Frigate card behavior covers all other interactions on the Frigate card (e.g.
Advanced Camera Card behavior covers all other interactions on the Advanced Camera Card (e.g.
menu icon elements, submenus and actions on the card or views).
#### Custom action types: `start_tap` and `end_tap`
@@ -32,7 +32,7 @@ actually occurring.
#### Multiple actions
Extended Frigate card behavior supports a list of actions instead of a single
Extended Advanced Camera Card behavior supports a list of actions instead of a single
action, all of which will be handled. See [an example of multiple
actions](../../examples.md?id=multiple-actions).
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -30,9 +30,9 @@ automations:
- condition: fullscreen
fullscreen: true
actions:
- action: custom:frigate-card-action
frigate_card_action: live_substream_on
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_on
actions_not:
- action: custom:frigate-card-action
frigate_card_action: live_substream_off
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_off
```
+8 -8
View File
@@ -7,7 +7,7 @@ The `live_provider` parameter determines what provides the live stream for a cam
| Live Provider | Latency | Frame Rate | Loading Time | Installation | Description |
| ---------------------------------- | ------- | ---------- | ------------ | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `go2rtc` | Best | High | Better | Builtin | Uses [go2rtc](https://github.com/AlexxIT/go2rtc) to stream live feeds. This is supported by Frigate &gt;= `0.12`. |
| `ha` (default HA configuration) | Poor | High | Better | Builtin | Use the built-in Home Assistant camera stream. The camera doesn't even need to be a Frigate camera! |
| `ha` (default HA configuration) | Poor | High | Better | Builtin | Use the built-in Home Assistant camera stream. |
| `ha` (Native WebRTC) | Best | High | Better | Builtin | Use the built-in Home Assistant camera streams -- can be configured to use [native WebRTC](https://www.home-assistant.io/integrations/rtsp_to_webrtc/) offering a very low-latency feed direct to your browser. |
| `ha` (when configured with LL-HLS) | Better | High | Better | Builtin | Use the built-in Home Assistant camera streams -- can be configured to use an [LL-HLS](https://www.home-assistant.io/integrations/stream/#ll-hls) feed for lower latency. |
| `image` | Poor | Poor | Best | Builtin | Use refreshing snapshots of the built-in Home Assistant camera streams. |
@@ -44,13 +44,13 @@ cameras:
# [...]
```
| Option | Default | Description |
| ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entity` | | The entity to use when `mode` is set to `entity`. This entity is expected to have an `entity_picture` attribute that specifies the image URL. |
| `entity_parameters` | | Optional URL parameters to add to the URL generated for entity-based modes (i.e. when `mode` is `camera` or `entity`). |
| `mode` | `auto` | Value must be one of `url` (to fetch an arbitrary image URL), `camera` (to show a still of the currently selected camera entity using either `camera_entity` or `webrtc_card.entity` in that order of precedence), `entity` to show an image associated with a named entity (see the `entity` parameter below), or `screensaver` (to show an [embedded stock Frigate card logo](https://github.com/dermotduffy/frigate-hass-card/blob/main/src/images/frigate-bird-in-sky.jpg)). If `auto`, the mode is chosen automatically based on whether `url` or `entity` parameters have been specified. |
| `refresh_seconds` | 1 | The image will be refreshed at least every `refresh_seconds` (it may refresh more frequently, e.g. whenever Home Assistant updates its camera security token). `0` implies no refreshing. |
| `url` | | A static image URL to be used when the `mode` is set to `url` or when a temporary image is required (e.g. may appear momentarily prior to load of a camera snapshot in the `camera` mode). Note that a `_t=[timestsamp]` query parameter will be automatically added to all URLs such that the image will not be cached by the browser. |
| Option | Default | Description |
| ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entity` | | The entity to use when `mode` is set to `entity`. This entity is expected to have an `entity_picture` attribute that specifies the image URL. |
| `entity_parameters` | | Optional URL parameters to add to the URL generated for entity-based modes (i.e. when `mode` is `camera` or `entity`). |
| `mode` | `auto` | Value must be one of `url` (to fetch an arbitrary image URL), `camera` (to show a still of the currently selected camera entity using either `camera_entity` or `webrtc_card.entity` in that order of precedence), `entity` to show an image associated with a named entity (see the `entity` parameter below), or `screensaver` (to show an [embedded image](https://github.com/dermotduffy/advanced-camera-card/blob/main/src/images/iris-screensaver.jpg)). If `auto`, the mode is chosen automatically based on whether `url` or `entity` parameters have been specified. |
| `refresh_seconds` | 1 | The image will be refreshed at least every `refresh_seconds` (it may refresh more frequently, e.g. whenever Home Assistant updates its camera security token). `0` implies no refreshing. |
| `url` | | A static image URL to be used when the `mode` is set to `url` or when a temporary image is required (e.g. may appear momentarily prior to load of a camera snapshot in the `camera` mode). Note that a `_t=[timestsamp]` query parameter will be automatically added to all URLs such that the image will not be cached by the browser. |
## `jsmpeg`
+1 -1
View File
@@ -12,7 +12,7 @@ elements:
- [element_2]
```
?> The Frigate Card allows either a single [action](../actions/README.md) (as in stock Home
?> The Advanced Camera Card allows either a single [action](../actions/README.md) (as in stock Home
Assistant) or list of [actions](../actions/README.md) to be defined for each class of user interaction
(e.g. `tap`, `double_tap`, `hold`, etc). See [an example of multiple actions](../../examples.md?id=multiple-actions).
+28 -28
View File
@@ -2,19 +2,19 @@
## `conditional`
Restrict a set of elements to only render when the card is matches a set of [conditions](../../conditions.md). This is analogous to the stock [`conditional`](../stock/README.md?id=conditional) element except supporting a rich set of Frigate Card [conditions](../../conditions.md).
Restrict a set of elements to only render when the card is matches a set of [conditions](../../conditions.md). This is analogous to the stock [`conditional`](../stock/README.md?id=conditional) element except supporting a rich set of Advanced Camera Card [conditions](../../conditions.md).
```yaml
elements:
- type: custom:frigate-card-conditional
- type: custom:advanced-camera-card-conditional
# [...]
```
Parameters for the `custom:frigate-card-conditional` element:
Parameters for the `custom:advanced-camera-card-conditional` element:
| Parameter | Description |
| ------------ | ---------------------------------------------------------------------------------------------------------------- |
| `type` | Must be `custom:frigate-card-conditional`. |
| `type` | Must be `custom:advanced-camera-card-conditional`. |
| `conditions` | A list of [conditions](../../conditions.md) that must evaluate to true in order for the elements to be rendered. |
| `elements` | The elements to render. Can be any supported element. |
@@ -22,11 +22,11 @@ See the [conditional elements example](../../../examples.md?id=conditional-eleme
## `menu-icon`
Add an arbitrary icon to the Frigate Card menu.
Add an arbitrary icon to the Advanced Camera Card menu.
```yaml
elements:
- type: custom:frigate-card-menu-icon
- type: custom:advanced-camera-card-menu-icon
# [...]
```
@@ -34,7 +34,7 @@ Configuration is similar to a stock [Picture Elements Icon](https://www.home-ass
| Parameter | Default | Description |
| ------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | | Must be `custom:frigate-card-menu-icon`. |
| `type` | | Must be `custom:advanced-camera-card-menu-icon`. |
| `alignment` | `matching` | Whether this menu item should have an alignment that is `matching` the menu alignment or `opposing` the menu alignment. Can be used to create two separate groups of buttons on the menu. The `priority` option orders buttons within a given `alignment`. |
| `enabled` | `true` | Whether or not to show this menu item. |
| `entity` | | An optional Home Assistant entity for use with actions. |
@@ -51,13 +51,13 @@ Add a configurable submenu dropdown.
```yaml
elements:
- type: custom:frigate-card-menu-submenu
- type: custom:advanced-camera-card-menu-submenu
# [...]
```
| Parameter | Default | Description |
| ------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | | Must be `custom:frigate-card-menu-submenu`. |
| `type` | | Must be `custom:advanced-camera-card-menu-submenu`. |
| `alignment` | `matching` | Whether this menu item should have an alignment that is `matching` the menu alignment or `opposing` the menu alignment. Can be used to create two separate groups of buttons on the menu. The `priority` option orders buttons within a given `alignment`. |
| `enabled` | `true` | Whether or not to show this menu item. |
| `entity` | | An optional Home Assistant entity for use with actions. |
@@ -88,13 +88,13 @@ Add a submenu based on a `select` or `input_select`. This element allows you to
```yaml
elements:
- type: custom:frigate-card-menu-submenu-select
- type: custom:advanced-camera-card-menu-submenu-select
# [...]
```
| Parameter | Default | Description |
| ------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | | Must be `custom:frigate-card-menu-submenu-select`. |
| `type` | | Must be `custom:advanced-camera-card-menu-submenu-select`. |
| `alignment` | `matching` | Whether this menu item should have an alignment that is `matching` the menu alignment or `opposing` the menu alignment. Can be used to create two separate groups of buttons on the menu. The `priority` option orders buttons within a given `alignment`. |
| `enabled` | `true` | Whether or not to show this menu item. |
| `entity` | | An optional Home Assistant entity for use with actions. |
@@ -110,11 +110,11 @@ See the `select` [submenu example](../../../examples.md?id=select-submenu).
## `menu-state-icon`
Add a state icon to the Frigate Card menu that represents the state of a Home Assistant entity.
Add a state icon to the Advanced Camera Card menu that represents the state of a Home Assistant entity.
```yaml
elements:
- type: custom:frigate-card-menu-state-icon
- type: custom:advanced-camera-card-menu-state-icon
# [...]
```
@@ -122,7 +122,7 @@ Configuration is similar to a stock [Picture Elements State Icon](https://www.ho
| Parameter | Default | Description |
| ------------------------------------------------------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | | Must be `custom:frigate-card-menu-state-icon`. |
| `type` | | Must be `custom:advanced-camera-card-menu-state-icon`. |
| `alignment` | `matching` | Whether this menu item should have an alignment that is `matching` the menu alignment or `opposing` the menu alignment. Can be used to create two separate groups of buttons on the menu. The `priority` option orders buttons within a given `alignment`. |
| `enabled` | `true` | Whether or not to show this menu item. |
| `entity` | | An optional Home Assistant entity for use with actions. |
@@ -140,13 +140,13 @@ Add an arbitrary icon to the status bar.
```yaml
elements:
- type: custom:frigate-card-status-bar-icon
- type: custom:advanced-camera-card-status-bar-icon
# [...]
```
| Parameter | Default | Description |
| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `type` | | Must be `custom:frigate-card-status-bar-icon`. |
| `type` | | Must be `custom:advanced-camera-card-status-bar-icon`. |
| `actions` | | Actions to performs when the status bar item is interacted with. See [actions](../../actions/README.md). |
| `enabled` | `true` | `true` to enable this status bar item, `false` to disable. |
| `exclusive` | `false` | Whether or not this item should evict non-exclusive items from the status bar. |
@@ -161,13 +161,13 @@ Add an arbitrary image to the status bar.
```yaml
elements:
- type: custom:frigate-card-status-bar-image
- type: custom:advanced-camera-card-status-bar-image
# [...]
```
| Parameter | Default | Description |
| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `type` | | Must be `custom:frigate-card-status-bar-image`. |
| `type` | | Must be `custom:advanced-camera-card-status-bar-image`. |
| `actions` | | Actions to performs when the status bar item is interacted with. See [actions](../../actions/README.md). |
| `enabled` | `true` | `true` to enable this status bar item, `false` to disable. |
| `exclusive` | `false` | Whether or not this item should evict non-exclusive items from the status bar. |
@@ -182,13 +182,13 @@ Add an arbitrary string to the status bar.
```yaml
elements:
- type: custom:frigate-card-status-bar-string
- type: custom:advanced-camera-card-status-bar-string
# [...]
```
| Parameter | Default | Description |
| ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `type` | | Must be `custom:frigate-card-status-bar-string`. |
| `type` | | Must be `custom:advanced-camera-card-status-bar-string`. |
| `actions` | | Actions to performs when the status bar item is interacted with. See [actions](../../actions/README.md). |
| `enabled` | `true` | `true` to enable this status bar item, `false` to disable. |
| `exclusive` | `false` | Whether or not this item should evict non-exclusive items from the status bar. |
@@ -205,7 +205,7 @@ elements:
```yaml
elements:
- type: custom:frigate-card-menu-icon
- type: custom:advanced-camera-card-menu-icon
alignment: matching
enabled: true
entity: light.office_main_lights
@@ -215,7 +215,7 @@ elements:
style:
color: white
title: Vroom
- type: custom:frigate-card-menu-state-icon
- type: custom:advanced-camera-card-menu-state-icon
alignment: matching
enabled: true
entity: light.office_main_lights
@@ -226,7 +226,7 @@ elements:
style:
color: white
title: Office lights
- type: custom:frigate-card-menu-submenu
- type: custom:advanced-camera-card-menu-submenu
alignment: matching
enabled: true
entity: light.office_main_lights
@@ -256,7 +256,7 @@ elements:
style:
color: white
title: Office lights
- type: custom:frigate-card-menu-submenu-select
- type: custom:advanced-camera-card-menu-submenu-select
alignment: matching
enabled: true
entity: input_select.kitchen_scene
@@ -280,7 +280,7 @@ elements:
color: white
title: 'Kitchen Scene'
# Show a pig icon if a variety of conditions are met.
- type: custom:frigate-card-conditional
- type: custom:advanced-camera-card-conditional
elements:
- type: icon
icon: mdi:pig
@@ -321,21 +321,21 @@ elements:
- condition: user
users:
- 581fca7fdc014b8b894519cc531f9a04
- type: custom:frigate-card-status-bar-string
- type: custom:advanced-camera-card-status-bar-string
enabled: true
exclusive: false
expand: false
string: 'Intruder alert!'
priority: 50
sufficient: false
- type: custom:frigate-card-status-bar-icon
- type: custom:advanced-camera-card-status-bar-icon
enabled: true
exclusive: false
expand: false
icon: 'mdi:cow'
priority: 50
sufficient: false
- type: custom:frigate-card-status-bar-image
- type: custom:advanced-camera-card-status-bar-image
enabled: true
exclusive: false
expand: false
+1 -1
View File
@@ -20,7 +20,7 @@ elements:
# [...]
```
?> See [Frigate Card custom elements](../custom//README.md) for the custom elements offered by _this_ card.
?> See [Advanced Camera Card custom elements](../custom//README.md) for the custom elements offered by _this_ card.
## `icon`
+8 -8
View File
@@ -7,14 +7,14 @@ image:
# [...]
```
| Option | Default | Description |
| ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `actions` | | [Actions](actions/README.md) to use for the `image` view. |
| `entity` | | The entity to use when `mode` is set to `entity`. This entity is expected to have an `entity_picture` attribute that specifies the image URL. |
| `entity_parameters` | | Optional URL parameters to add to the URL generated for entity-based modes (i.e. when `mode` is `camera` or `entity`). |
| `mode` | `auto` | Value must be one of `url` (to fetch an arbitrary image URL), `camera` (to show a still of the currently selected camera entity using either `camera_entity` or `webrtc_card.entity` in that order of precedence), `entity` to show an image associated with a named entity (see the `entity` parameter below), or `screensaver` (to show an [embedded stock Frigate card logo](https://github.com/dermotduffy/frigate-hass-card/blob/main/src/images/frigate-bird-in-sky.jpg)). If `auto`, the mode is chosen automatically based on whether `url` or `entity` parameters have been specified. |
| `refresh_seconds` | 1 | The image will be refreshed at least every `refresh_seconds` (it may refresh more frequently, e.g. whenever Home Assistant updates its camera security token). `0` implies no refreshing. |
| `url` | | A static image URL to be used when the `mode` is set to `url` or when a temporary image is required (e.g. may appear momentarily prior to load of a camera snapshot in the `camera` mode). Note that a `_t=[timestsamp]` query parameter will be automatically added to all URLs such that the image will not be cached by the browser. |
| Option | Default | Description |
| ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `actions` | | [Actions](actions/README.md) to use for the `image` view. |
| `entity` | | The entity to use when `mode` is set to `entity`. This entity is expected to have an `entity_picture` attribute that specifies the image URL. |
| `entity_parameters` | | Optional URL parameters to add to the URL generated for entity-based modes (i.e. when `mode` is `camera` or `entity`). |
| `mode` | `auto` | Value must be one of `url` (to fetch an arbitrary image URL), `camera` (to show a still of the currently selected camera entity using either `camera_entity` or `webrtc_card.entity` in that order of precedence), `entity` to show an image associated with a named entity (see the `entity` parameter below), or `screensaver` (to show an [embedded image](https://github.com/dermotduffy/advanced-camera-card/blob/main/src/images/iris-screensaver.jpg)). If `auto`, the mode is chosen automatically based on whether `url` or `entity` parameters have been specified. |
| `refresh_seconds` | 1 | The image will be refreshed at least every `refresh_seconds` (it may refresh more frequently, e.g. whenever Home Assistant updates its camera security token). `0` implies no refreshing. |
| `url` | | A static image URL to be used when the `mode` is set to `url` or when a temporary image is required (e.g. may appear momentarily prior to load of a camera snapshot in the `camera` mode). Note that a `_t=[timestsamp]` query parameter will be automatically added to all URLs such that the image will not be cached by the browser. |
?> When `mode` is set to `camera` this is effectively providing the same image as the `image` [live provider](cameras/live-provider.md) would show in the live camera carousel.
+18 -20
View File
@@ -36,9 +36,9 @@ menu:
| `display_mode` | The `display_mode` button allows changing between single and grid views. |
| `download` | The `download` menu button: allow direct download of the media being displayed. |
| `expand` | The `expand` menu button: expand the card into a popup/dialog. |
| `frigate` | The `Frigate` menu button: brings the user to the default configured view (`view.default`), or collapses/expands the menu if the `menu.style` is `hidden` . |
| `fullscreen` | The `fullscreen` menu button: expand the card to consume the fullscreen. Please note that fullscreen behavior on iPhone is limited, see [troubleshooting](../troubleshooting.md?id=fullscreen-doesn39t-work-on-iphone). |
| `image` | The `image` view menu button: brings the user to the static `image` view. |
| `iris` | The main Advanced Camera Card `iris` menu button: brings the user to the default configured view (`view.default`), or collapses/expands the menu if the `menu.style` is `hidden` . |
| `live` | The `live` view menu button: brings the user to the `live` view. |
| `media_player` | The `media_player` menu button: sends the visible media to a remote media player. Supports Frigate clips, snapshots and live camera (only for cameras that specify a `camera_entity` and only using the default HA stream (equivalent to the `ha` live provider)). `jsmpeg` or `webrtc-card` are not supported, although live can still be played as long as `camera_entity` is specified. In the player list, a `tap` will send the media to the player, a `hold` will stop the media on the player. |
| `microphone` | The `microphone` button allows usage of 2-way audio in certain configurations. See [Using 2-way audio](../usage/2-way-audio.md). |
@@ -51,26 +51,26 @@ menu:
### Options for each button
| Option | Default | Description |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `alignment` | `matching` | Whether this menu item should have an alignment that is `matching` the menu alignment or `opposing` the menu alignment. Can be used to create two separate groups of buttons on the menu. The `priority` option orders buttons within a given `alignment`. |
| `enabled` | `true` for `frigate`, `cameras`, `substreams`, `live`, `clips`, `snapshots`, `timeline`, `download`, `camera_ui`, `fullscreen`, `media_player`, `display_mode` and `ptz_home`. `false` for `image`, `expand`, `microphone`, `mute`, `play`, `recordings`, `screenshot`, `ptz_controls` | Whether or not to show the button. |
| `icon` | | An icon to overriding the default for that button, e.g. `mdi:camera-front`. See also [custom icons](../usage/custom-icons.md). |
| `permanent` | `false` | If `false` the menu item is hidden when the menu has the `hidden` style and the menu is closed, otherwise it is shown (and sorted to the front). |
| `priority` | `50` | The menu item priority. Higher priority items are ordered closer to the start of the menu alignment (i.e. a button with priority `70` will order further to the left than a button with priority `60`). Priority applies separately to `matching` and `opposing` groups (see `alignment` above). Minimum `0`, maximum `100`. |
| Option | Default | Description |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `alignment` | `matching` | Whether this menu item should have an alignment that is `matching` the menu alignment or `opposing` the menu alignment. Can be used to create two separate groups of buttons on the menu. The `priority` option orders buttons within a given `alignment`. |
| `enabled` | `true` for `iris`, `cameras`, `substreams`, `live`, `clips`, `snapshots`, `timeline`, `download`, `camera_ui`, `fullscreen`, `media_player`, `display_mode` and `ptz_home`. `false` for `image`, `expand`, `microphone`, `mute`, `play`, `recordings`, `screenshot`, `ptz_controls` | Whether or not to show the button. |
| `icon` | | An icon to overriding the default for that button, e.g. `mdi:camera-front`. See also [custom icons](../usage/custom-icons.md). |
| `permanent` | `false` | If `false` the menu item is hidden when the menu has the `hidden` style and the menu is closed, otherwise it is shown (and sorted to the front). |
| `priority` | `50` | The menu item priority. Higher priority items are ordered closer to the start of the menu alignment (i.e. a button with priority `70` will order further to the left than a button with priority `60`). Priority applies separately to `matching` and `opposing` groups (see `alignment` above). Minimum `0`, maximum `100`. |
## `style`
This card supports several menu styles.
| Key | Description | Screenshot |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `hidden` | Hide the menu by default. It may be toggled open as needed. | ![](../images/menu-mode-hidden.png 'Menu hidden :size=400') |
| `hover-card` | Overlay the menu over the card contents when the mouse is over the **card**, otherwise it is not shown. The Frigate button shows the default view. | ![](../images/menu-mode-overlay.png 'Menu hover-card :size=400') |
| `hover` | Overlay the menu over the card contents when the mouse is over the **menu**, otherwise it is not shown. The Frigate button shows the default view. | ![](../images/menu-mode-overlay.png 'Menu hover :size=400') |
| `none` | No menu is shown. | ![](../images/menu-mode-none.png 'No menu :size=400') |
| `outside` | Render the menu outside the card (i.e. above it if `position` is `top`, or below it if `position` is `bottom`). The Frigate button shows the default view. | ![](../images/menu-mode-above.png 'Menu outside :size=400') |
| `overlay` | Overlay the menu over the card contents. The Frigate button shows the default view. | ![](../images/menu-mode-overlay.png 'Menu hidden :size=400') |
| Key | Description | Screenshot |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| `hidden` | Hide the menu by default. It may be toggled open as needed with the `iris` button. | ![](../images/menu-mode-hidden.png 'Menu hidden :size=400') |
| `hover-card` | Overlay the menu over the card contents when the mouse is over the **card**, otherwise it is not shown. The `iris` button shows the default view. | ![](../images/menu-mode-overlay.png 'Menu hover-card :size=400') |
| `hover` | Overlay the menu over the card contents when the mouse is over the **menu**, otherwise it is not shown. The `iris` button shows the default view. | ![](../images/menu-mode-overlay.png 'Menu hover :size=400') |
| `none` | No menu is shown. | ![](../images/menu-mode-none.png 'No menu :size=400') |
| `outside` | Render the menu outside the card (i.e. above it if `position` is `top`, or below it if `position` is `bottom`). The `iris` button shows the default view. | ![](../images/menu-mode-above.png 'Menu outside :size=400') |
| `overlay` | Overlay the menu over the card contents. The `iris` button shows the default view. | ![](../images/menu-mode-overlay.png 'Menu hidden :size=400') |
## Fully expanded reference
@@ -80,13 +80,11 @@ This card supports several menu styles.
menu:
alignment: left
buttons:
frigate:
iris:
priority: 50
enabled: true
alignment: matching
# Default icon is an internal coded Frigate icon. Note
# absence of 'mdi' here (mdi has no Frigate icon).
icon: frigate
icon: iris
cameras:
priority: 50
enabled: true
+2 -2
View File
@@ -39,13 +39,13 @@ Principles used in the selection of options set by `low-performance` profile mod
- Get 'out of the box' performance similar to the basic "Home Assistant Picture Glance" card.
- Do not break the visual aesthetic of the card.
See the [source code](https://github.com/dermotduffy/frigate-hass-card/blob/main/src/config/profiles/low-performance.ts) for an exhaustive list of defaults set by this profile.
See the [source code](https://github.com/dermotduffy/advanced-camera-card/blob/main/src/config/profiles/low-performance.ts) for an exhaustive list of defaults set by this profile.
## `scrubbing`
Configures the `live` view and media viewer to allow media "scrubbing" as the timeline is dragged back and forth.
See the [source code](https://github.com/dermotduffy/frigate-hass-card/blob/main/src/config/profiles/scrubbing.ts) for an exhaustive list of options set by this profile.
See the [source code](https://github.com/dermotduffy/advanced-camera-card/blob/main/src/config/profiles/scrubbing.ts) for an exhaustive list of options set by this profile.
## Fully expanded reference
+20 -20
View File
@@ -7,20 +7,20 @@ view:
# [...]
```
| Option | Default | Description |
| ------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `actions` | | [Actions](actions/README.md) to use for all views, individual actions may be overriden by view-specific actions. |
| `camera_select` | `current` | The [view](view.md?id=supported-views) to show when a new camera is selected (e.g. in the camera menu). If `current` the view is unchanged when a new camera is selected. |
| `dim` | `false` | Whether or not to 'dim' the brightness of the card (by 25%) if the card `interaction_seconds` has expired (i.e. card has been left unattended for that period of time). |
| `default` | `live` | The view to show in the card by default. The default camera is the first one listed. See [Supported Views](view.md?id=supported-views) below. |
| `default_reset` | | The circumstances and behavior that cause the card to reset to the default view. See below. |
| `interaction_seconds` | `300` | After a mouse/touch interaction with the card, it will be considered "interacted with" until this number of seconds elapses without further interaction. May be used as part of an [interaction condition](conditions.md?id=interaction) or with `reset_after_interaction` to reset the view after the interaction is complete. |
| `keyboard_shortcuts` | See [usage](../usage/keyboard-shortcuts.md) for defaults. | Configure keyboard shortcuts. See below. |
| `render_entities` | | **YAML only**: A list of entity ids that should cause the card to re-render 'in-place'. The view/camera is not changed. This should **very** rarely be needed, but could be useful if the card is both setting and changing HA state of the same object as could be the case for some complex `card_mod` scenarios ([example](https://github.com/dermotduffy/frigate-hass-card/issues/343)). |
| `reset_after_interaction` | `true` | If `true` the card will reset to the default configured view (i.e. 'screensaver' functionality) after `interaction_seconds` has elapsed after user interaction. |
| `theme` | | How the card is themed. See below. |
| `triggers` | | How to react when a camera is [triggered](cameras/README.md?id=triggers). |
| `default_cycle_camera` | `false` | When set to `true` the selected camera is cycled on each default view change. |
| Option | Default | Description |
| ------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `actions` | | [Actions](actions/README.md) to use for all views, individual actions may be overriden by view-specific actions. |
| `camera_select` | `current` | The [view](view.md?id=supported-views) to show when a new camera is selected (e.g. in the camera menu). If `current` the view is unchanged when a new camera is selected. |
| `dim` | `false` | Whether or not to 'dim' the brightness of the card (by 25%) if the card `interaction_seconds` has expired (i.e. card has been left unattended for that period of time). |
| `default` | `live` | The view to show in the card by default. The default camera is the first one listed. See [Supported Views](view.md?id=supported-views) below. |
| `default_reset` | | The circumstances and behavior that cause the card to reset to the default view. See below. |
| `interaction_seconds` | `300` | After a mouse/touch interaction with the card, it will be considered "interacted with" until this number of seconds elapses without further interaction. May be used as part of an [interaction condition](conditions.md?id=interaction) or with `reset_after_interaction` to reset the view after the interaction is complete. |
| `keyboard_shortcuts` | See [usage](../usage/keyboard-shortcuts.md) for defaults. | Configure keyboard shortcuts. See below. |
| `render_entities` | | **YAML only**: A list of entity ids that should cause the card to re-render 'in-place'. The view/camera is not changed. This should **very** rarely be needed, but could be useful if the card is both setting and changing HA state of the same object as could be the case for some complex `card_mod` scenarios ([example](https://github.com/dermotduffy/advanced-camera-card/issues/343)). |
| `reset_after_interaction` | `true` | If `true` the card will reset to the default configured view (i.e. 'screensaver' functionality) after `interaction_seconds` has elapsed after user interaction. |
| `theme` | | How the card is themed. See below. |
| `triggers` | | How to react when a camera is [triggered](cameras/README.md?id=triggers). |
| `default_cycle_camera` | `false` | When set to `true` the selected camera is cycled on each default view change. |
## `default_reset`
@@ -87,15 +87,15 @@ Configure the theming/colors applied to the card.
| `dark` | Use a dark theme that is identical to the HA dark theme. |
| `ha` | Uses HA-prescribed theming. Respects HA choice of dark or light colors. |
| `light` | Use a light theme that is similar to the HA light theme (there are some differences if you do not use the standard choices of primary color). |
| `traditional` | A theme based on the default Frigate card theme before full theming support was added. Respects HA color theme choices. |
| `traditional` | A theme based on the default Advanced Camera Card theme before full theming support was added. Respects HA color theme choices. |
### `overrides`
Allows overriding of any CSS value, can be used to tweak theming parameters.
| Option | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Any CSS key. Overriding the [Frigate Card](https://github.com/dermotduffy/frigate-hass-card/tree/main/src/scss/themes/base.scss) CSS variables allows changing individual theming paramters, e.g. `--frigate-card-menu-override-background` | Any CSS value, e.g. `red` or `rgba(10, 11, 12, 0.64)`. |
| Option | Description |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| Any CSS key. Overriding the [Advanced Camera Card](https://github.com/dermotduffy/advanced-camera-card/tree/main/src/scss/themes/base.scss) CSS variables allows changing individual theming paramters, e.g. `--advanced-camera-card-menu-override-background` | Any CSS value, e.g. `red` or `rgba(10, 11, 12, 0.64)`. |
## `triggers`
@@ -199,8 +199,8 @@ view:
themes:
- ha
overrides:
'--frigate-card-menu-button-active-color': red
'--frigate-card-menu-position-left-style-overlay-alignment-left-background': pink
'--advanced-camera-card-menu-button-active-color': red
'--advanced-camera-card-menu-position-left-style-overlay-alignment-left-background': pink
actions:
entity: light.office_main_lights
tap_action:
+7 -7
View File
@@ -1,6 +1,6 @@
# Developing
?> Want to contribute? Development help [**welcome**](https://github.com/dermotduffy/frigate-hass-card/issues/1248)!
?> Want to contribute? Development help [**welcome**](https://github.com/dermotduffy/advanced-camera-card/issues/1248)!
## Building
@@ -13,13 +13,13 @@ However, if you are not using Volta, you can check the `volta` key in the
`package.json` to see which version of Node and Yarn should be used.
```sh
$ git clone https://github.com/dermotduffy/frigate-hass-card
$ cd frigate-hass-card
$ git clone https://github.com/dermotduffy/advanced-camera-card
$ cd advanced-camera-card
$ yarn install
$ yarn run build
```
Resultant build entry file will be in `dist/frigate-hass-card.js`. This could be
Resultant build entry file will be in `dist/advanced-camera-card.js`. This could be
installed via the [manual installation
instructions](advanced-installation.md?id=manual-installation).
@@ -38,7 +38,7 @@ Releases follow [Semantic Versioning](https://semver.org/) with the following de
### Manual Releases
1. Merge a PR that contains only a `package.json` version number bump.
1. Go to the [releases page](https://github.com/dermotduffy/frigate-hass-card/releases).
1. Go to the [releases page](https://github.com/dermotduffy/advanced-camera-card/releases).
1. A release draft will automatically have been created, click 'Edit'.
1. Use the same version number for the release title and tag.
1. Choose 'This is a pre-release' for a beta version.
@@ -46,14 +46,14 @@ Releases follow [Semantic Versioning](https://semver.org/) with the following de
## Translations
[![translation badge](https://badge.inlang.com/?url=github.com/dermotduffy/frigate-hass-card)](https://fink.inlang.com/github.com/dermotduffy/frigate-hass-card?ref=badge)
[![translation badge](https://badge.inlang.com/?url=github.com/dermotduffy/advanced-camera-card)](https://fink.inlang.com/github.com/dermotduffy/advanced-camera-card?ref=badge)
To add translations, you can manually edit the JSON translation files in
`src/localize/languages` or use the [inlang](https://inlang.com/) online editor.
## Using a dev container
[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/dermotduffy/frigate-hass-card)
[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/dermotduffy/advanced-camera-card)
You can use the [VS Code Dev Containers](https://code.visualstudio.com/docs/remote/containers) extension to
speed up the development environment creation. Simply:
+121 -120
View File
@@ -9,14 +9,14 @@ into fullscreen mode, **except** when the view is `live` in which case the
office lights are toggled.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
view:
actions:
double_tap_action:
action: custom:frigate-card-action
frigate_card_action: fullscreen
action: custom:advanced-camera-card-action
advanced_camera_card_action: fullscreen
live:
actions:
entity: light.office_main_lights
@@ -27,7 +27,7 @@ live:
## Aspect ratios
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
dimensions:
@@ -44,7 +44,7 @@ card is put in fullscreen mode, and turn off the substream when exiting
fullscreen mode.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: image
@@ -63,11 +63,11 @@ automations:
- condition: fullscreen
fullscreen: true
actions:
- action: custom:frigate-card-action
frigate_card_action: live_substream_on
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_on
actions_not:
- action: custom:frigate-card-action
frigate_card_action: live_substream_off
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_off
```
### Responding to key input
@@ -85,14 +85,14 @@ automations:
key: z
alt: true
actions:
- action: custom:frigate-card-action
frigate_card_action: live
- action: custom:frigate-card-action
frigate_card_action: sleep
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live
- action: custom:advanced-camera-card-action
advanced_camera_card_action: sleep
duration:
s: 5
- action: custom:frigate-card-action
frigate_card_action: clips
- action: custom:advanced-camera-card-action
advanced_camera_card_action: clips
```
#### Change to `live` while key _held_ down
@@ -106,11 +106,11 @@ automations:
key: z
alt: true
actions:
- action: custom:frigate-card-action
frigate_card_action: live
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live
actions_not:
- action: custom:frigate-card-action
frigate_card_action: clips
- action: custom:advanced-camera-card-action
advanced_camera_card_action: clips
```
## Cameras
@@ -120,7 +120,7 @@ automations:
In this example, there is no Home Assistant entity linked to the camera, just a `frigate` camera name:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- frigate:
camera_name: office
@@ -132,7 +132,7 @@ cameras:
In this example, there is no Home Assistant entity linked to the camera, just a `go2rtc` stream.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- live_provider: go2rtc
go2rtc:
@@ -158,12 +158,12 @@ Elements state
label](https://www.home-assistant.io/lovelace/picture-elements/#state-label).
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
card_mod:
style:
frigate-card-elements $:
advanced-camera-card-elements $:
hui-state-label-element $: |
div {
padding: 0px !important;
@@ -173,12 +173,12 @@ card_mod:
## Cast a `dashboard`
This example will configure a Frigate card that can cast a dashboard view to a media player, which has a second Frigate card in panel mode with a low-latency live provider.
This example will configure an Advanced Camera Card that can cast a dashboard view to a media player, which has a second Advanced Camera Card in panel mode with a low-latency live provider.
### Source card
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: image
@@ -194,7 +194,7 @@ cameras:
?> This dashboard is configured at the path `/cast/` (path referred to in `dashboard_path` above).
```yaml
title: Frigate Card Casting
title: Advanced Camera Card Casting
views:
- title: Casting
# This path is referred to in `view_path` above.
@@ -202,7 +202,7 @@ views:
# Ensure the video is "maximized" / dashboard in "panel" mode.
type: panel
cards:
- type: custom:frigate-card
- type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: go2rtc
@@ -212,15 +212,15 @@ views:
You can restrict elements to only show for certain
[views](configuration/view.md?id=supported-views) using a
`custom:frigate-card-conditional` element. This example shows a car icon that
`custom:advanced-camera-card-conditional` element. This example shows a car icon that
calls a service but only in the `live` view.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-conditional
- type: custom:advanced-camera-card-conditional
conditions:
- condition: view
views:
@@ -248,7 +248,7 @@ You can have icons conditionally added to the menu based on entity state.
### Show a menu icon based on state
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
@@ -258,7 +258,7 @@ elements:
entity: light.office_main_lights
state: on
elements:
- type: custom:frigate-card-menu-state-icon
- type: custom:advanced-camera-card-menu-state-icon
entity: light.office
tap_action:
action: toggle
@@ -269,13 +269,13 @@ elements:
This example adds a menu button to optionally activate a siren when the camera is triggered.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-conditional
- type: custom:advanced-camera-card-conditional
elements:
- type: custom:frigate-card-menu-icon
- type: custom:advanced-camera-card-menu-icon
icon: mdi:alarm-bell
title: Activate alarm
style:
@@ -308,7 +308,7 @@ events with the `birdseye` camera (since it will not have events of its own).
This example shows events for two other cameras when `birdseye` is selected.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
- camera_entity: camera.kitchen
@@ -326,7 +326,7 @@ This example shows events for _all_ other cameras when `birdseye` is selected.
This is just a shortcut for naming all other cameras.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.kitchen
- camera_entity: camera.sitting_room
@@ -342,7 +342,7 @@ This example will automatically use a HD live substream when
the mouse cursor interacts with the card.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: image
@@ -356,11 +356,11 @@ cameras:
- substream
automations:
- actions:
- action: custom:frigate-card-action
frigate_card_action: live_substream_on
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_on
actions_not:
- action: custom:frigate-card-action
frigate_card_action: live_substream_off
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_off
conditions:
- condition: interaction
interaction: true
@@ -373,7 +373,7 @@ These examples change how the media fits and is positioned within the card dimen
### Stretch a camera into a 4:4 square
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.landing
dimensions:
@@ -387,7 +387,7 @@ cameras:
Take the left-hand side (position with x == `0`) and use that as the basis of a `9:16` (i.e. portrait) live view.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
dimensions:
@@ -404,7 +404,7 @@ This example moves the fullscreen button into its own group aligned to the
`left`, enables the `image` button and orders it furthest to the `right`.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
menu:
@@ -423,15 +423,15 @@ You can add custom icons to the menu with arbitrary actions. This example adds
an icon that navigates the browser to the releases page for this card:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-menu-icon
- type: custom:advanced-camera-card-menu-icon
icon: mdi:book
tap_action:
action: url
url_path: https://github.com/dermotduffy/frigate-hass-card/releases
url_path: https://github.com/dermotduffy/advanced-camera-card/releases
```
## Menu state icons
@@ -442,11 +442,11 @@ of the `light.office_main_lights` entity, that toggles the light on double
click.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-menu-state-icon
- type: custom:advanced-camera-card-menu-state-icon
entity: light.office_main_lights
tap_action:
action: toggle
@@ -454,21 +454,21 @@ elements:
## Multiple actions
This example shows how to configure multiple actions for a single Frigate card user interaction, in this case both selecting a different camera and changing the view on `tap`. Note that multiple actions are not supported on stock Picture Elements, see [actions](configuration/actions/README.md) for more information.
This example shows how to configure multiple actions for a single Advanced Camera Card user interaction, in this case both selecting a different camera and changing the view on `tap`. Note that multiple actions are not supported on stock Picture Elements, see [actions](configuration/actions/README.md) for more information.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-menu-icon
- type: custom:advanced-camera-card-menu-icon
icon: mdi:chair-rolling
tap_action:
- action: custom:frigate-card-action
frigate_card_action: camera_select
- action: custom:advanced-camera-card-action
advanced_camera_card_action: camera_select
camera: camera.office
- action: custom:frigate-card-action
frigate_card_action: live
- action: custom:advanced-camera-card-action
advanced_camera_card_action: live
```
## Multiple providers
@@ -478,7 +478,7 @@ to provide a separate unambiguous way of referring to that camera, since the
`camera_entity` is shared between the two cameras).
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: jsmpeg
@@ -496,7 +496,7 @@ You can override card configuration when certain [conditions](configuration/cond
### Change menu position based on HA state
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
overrides:
@@ -519,7 +519,7 @@ ask the card to trigger a card update based on that entity -- which causes it to
use the new overriden default immediately.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
view:
@@ -543,7 +543,7 @@ This example will always render 5 columns in fullscreen mode in both the live
and media viewer views, and will not enlarge the selected item. The [normal auto-layout behavior](configuration/grid-layout-algorithm.md) will be used outside of fullscreen mode.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
overrides:
@@ -569,7 +569,7 @@ This example changes the menu style to `overlay` in expanded mode in order to
take advantage of the extra horizontal space of the dialog/popup.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
menu:
@@ -589,14 +589,14 @@ This example disables the menu unless the card is in fullscreen mode, and uses a
card-wide action to enable fullscreen mode on `double_tap`.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
view:
actions:
double_tap_action:
action: custom:frigate-card-action
frigate_card_action: fullscreen
action: custom:advanced-camera-card-action
advanced_camera_card_action: fullscreen
overrides:
- conditions:
- condition: fullscreen
@@ -611,7 +611,7 @@ overrides:
This example removes a camera from the card when an entity is disabled (e.g. a switch controlling power to the camera).
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
- camera_entity: camera.kitchen
@@ -629,7 +629,7 @@ overrides:
This example disables the PTZ controls when the card is viewed on the Companion app:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
overrides:
@@ -644,10 +644,11 @@ overrides:
The card supports using PTZ controls to conveniently control pan, tilt and zoom
for cameras. If you're using a Frigate camera, and Frigate itself shows PTZ
controls, this should work straight out of the box without any extra configuration:
controls, this should work straight out of the box without any extra
configuration:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
```
@@ -657,7 +658,7 @@ controls on your camera but Home Assistant does, you can still manually
configure actions for the card to perform for each PTZ control:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
ptz:
@@ -677,7 +678,7 @@ These examples show altering the card configuration based on device or viewport
### Change menu position when orientation changes
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
- camera_entity: camera.kitchen
@@ -695,7 +696,7 @@ overrides:
### Hide menu & controls when viewport width &lt;= 300 (e.g. PIP mode)
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
- camera_entity: camera.kitchen
@@ -720,7 +721,7 @@ You can add a state badge to the card showing arbitrary entity states. This
example adds a state badge showing the temperature and hides the label text:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
@@ -740,7 +741,7 @@ elements:
This example fetches a static image every 10 seconds (in this case the latest image saved on the Frigate server for a given camera).
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
view:
@@ -757,7 +758,7 @@ image:
This example disables the status bar.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
status_bar:
@@ -771,7 +772,7 @@ This example shows an icon and a message on the status bar when a camera is trig
![Dynamic Status Messages](images/dynamic-status.gif 'Dynamic Status Messages :size=400')
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
automations:
@@ -780,21 +781,21 @@ automations:
triggered:
- camera.office
actions:
- action: custom:frigate-card-action
frigate_card_action: status_bar
- action: custom:advanced-camera-card-action
advanced_camera_card_action: status_bar
status_bar_action: add
items:
- type: custom:frigate-card-status-bar-icon
- type: custom:advanced-camera-card-status-bar-icon
icon: mdi:alarm-light
exclusive: true
- type: custom:frigate-card-status-bar-string
- type: custom:advanced-camera-card-status-bar-string
string: Intruder detected!
expand: true
exclusive: true
sufficient: true
actions_not:
- action: custom:frigate-card-action
frigate_card_action: status_bar
- action: custom:advanced-camera-card-action
advanced_camera_card_action: status_bar
status_bar_action: reset
```
@@ -805,11 +806,11 @@ You can add submenus to the menu -- buttons that when pressed reveal a dropdown
### Basic submenu
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-menu-submenu
- type: custom:advanced-camera-card-menu-submenu
icon: mdi:menu
items:
- title: Lights
@@ -825,8 +826,8 @@ elements:
- title: Fullscreen
icon: mdi:fullscreen
tap_action:
action: custom:frigate-card-action
frigate_card_action: fullscreen
action: custom:advanced-camera-card-action
advanced_camera_card_action: fullscreen
```
### Conditional submenu
@@ -834,17 +835,17 @@ elements:
This example shows submenus conditional on the camera selected.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-conditional
- type: custom:advanced-camera-card-conditional
conditions:
- condition: camera
cameras:
- camera.office
elements:
- type: custom:frigate-card-menu-submenu
- type: custom:advanced-camera-card-menu-submenu
icon: mdi:door
items:
- title: Office Lights
@@ -852,13 +853,13 @@ elements:
entity: light.office_main_lights
tap_action:
action: toggle
- type: custom:frigate-card-conditional
- type: custom:advanced-camera-card-conditional
conditions:
- condition: camera
cameras:
- camera.kitchen
elements:
- type: custom:frigate-card-menu-submenu
- type: custom:advanced-camera-card-menu-submenu
icon: mdi:sofa
items:
- title: Kitchen Lights
@@ -890,22 +891,22 @@ input_select:
The following will convert this entity into a submenu:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-menu-submenu-select
- type: custom:advanced-camera-card-menu-submenu-select
entity: input_select.office_scene
```
To override 1 or more individual options (e.g. to set custom icons and titles)
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
- type: custom:frigate-card-menu-submenu-select
- type: custom:advanced-camera-card-menu-submenu-select
icon: mdi:lamps
entity: input_select.office_scene
options:
@@ -925,7 +926,7 @@ camera through the use of [camera dependencies](configuration/cameras/README.md?
This example shows two substreams for a single live camera, and uses the 'HD' icon.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: image
@@ -948,11 +949,11 @@ menu:
## Trigger actions
You can control the card itself with the `custom:frigate-card-action` action.
You can control the card itself with the `custom:advanced-camera-card-action` action.
This example shows an icon that toggles the card fullscreen mode.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
elements:
@@ -962,8 +963,8 @@ elements:
left: 40px
top: 40px
tap_action:
action: custom:frigate-card-action
frigate_card_action: fullscreen
action: custom:advanced-camera-card-action
advanced_camera_card_action: fullscreen
```
## Trigger fullscreen
@@ -999,7 +1000,7 @@ action:
size: wide
timeout: 15000
content:
type: custom:frigate-card
type: custom:advanced-camera-card
aspect_ratio: 55%
cameras:
- camera_entity: camera.frontdoor
@@ -1023,7 +1024,7 @@ trigger conditions per camera. It will change back to the `default` view when
untriggered.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
# This is a Frigate camera which will automatically
# be triggered when events occur.
@@ -1051,7 +1052,7 @@ view:
Disable the stock video controls and add menu button equivalents.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live:
@@ -1076,27 +1077,27 @@ The card can respond to actions in the query string. See [URL Actions](usage/url
### Choosing `clips` view on a named card
This example assumes that one card (of potentially multiple Frigate Cards on the dashboard) is configured with a `card_id` parameter:
This example assumes that one card (of potentially multiple Advanced Camera Cards on the dashboard) is configured with a `card_id` parameter:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
card_id: main
```
```text
https://ha.mydomain.org/lovelace-test/0?frigate-card-action.main.clips
https://ha.mydomain.org/lovelace-test/0?advanced_camera_card_action-action.main.clips
```
### Choosing the camera from a separate picture elements card
In this example, the card will select a given camera when the user navigates from a _separate_ Picture Elements card:
Frigate Card configuration:
Advanced Camera Card configuration:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
- camera_entity: camera.kitchen
@@ -1115,7 +1116,7 @@ elements:
left: 30%
tap_action:
action: navigate
navigation_path: /lovelace-test/0?frigate-card-action.camera_select=camera.office
navigation_path: /lovelace-test/0?advanced_camera_card_action-action.camera_select=camera.office
- type: icon
icon: mdi:cctv
style:
@@ -1123,7 +1124,7 @@ elements:
left: 42%
tap_action:
action: navigate
navigation_path: /lovelace-test/0?frigate-card-action.camera_select=camera.kitchen
navigation_path: /lovelace-test/0?advanced_camera_card_action-action.camera_select=camera.kitchen
```
![Taking card actions via the URL](images/navigate-picture-elements.gif 'Taking card actions via the URL :size=400')
@@ -1131,13 +1132,13 @@ elements:
### Selecting a camera in expanded mode via query string
```text
https://ha.mydomain.org/lovelace-test/0?frigate-card-action.camera_select=kitchen&frigate-card-action.expand
https://ha.mydomain.org/lovelace-test/0?advanced_camera_card_action-action.camera_select=kitchen&advanced_camera_card_action-action.expand
```
## WebRTC Card configuration
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: webrtc-card
@@ -1152,7 +1153,7 @@ cameras:
This example changes the default [zoom/pan settings for a camera](./configuration/cameras/README.md?id=layout-configuration) to always zoom in on a given area:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
dimensions:
@@ -1168,7 +1169,7 @@ cameras:
This example prevents zooming on the media viewer but keeps it on in other views (e.g. `live` view):
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
dimensions:
@@ -1186,7 +1187,7 @@ media_viewer:
This example uses different settings for the media viewer and `live` view, by overriding the camera configuration:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
dimensions:
@@ -1210,7 +1211,7 @@ overrides:
This example automatically zooms in and out based on the state of an entity:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.living_room
live_provider: go2rtc
@@ -1222,8 +1223,8 @@ automations:
entity: binary_sensor.door_contact
state: 'on'
actions:
- action: custom:frigate-card-action
frigate_card_action: ptz_digital
- action: custom:advanced-camera-card-action
advanced_camera_card_action: ptz_digital
target_id: camera.living_room
absolute:
zoom: 4
@@ -1231,8 +1232,8 @@ automations:
x: 38
y: 20
actions_not:
- action: custom:frigate-card-action
frigate_card_action: ptz_digital
- action: custom:advanced-camera-card-action
advanced_camera_card_action: ptz_digital
target_id: camera.living_room
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

+11 -6
View File
@@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Frigate Card</title>
<title>Advanced Camera Card</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Frigate Card Documentation" />
<meta name="description" content="Advanced Camera Card Documentation" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1.0, shrink-to-fit=no, viewport-fit=cover"
@@ -27,6 +27,7 @@
<style>
:root {
--content-max-width: 95vw;
--cover-heading-font-size-max: 48;
}
.svg-icon {
background-color: rgb(255, 255, 255);
@@ -34,6 +35,9 @@
background: repeating-conic-gradient(#80808091 0% 25%, transparent 0% 50%) 50% /
4px 4px;
}
#__sidebar img {
max-width: 100px;
}
</style>
</head>
<body>
@@ -43,12 +47,13 @@
// Full reference: https://docsify.js.org/#/configuration
// The repo to link to.
repo: 'dermotduffy/frigate-hass-card',
repo: 'dermotduffy/advanced-camera-card',
// The overall documentation name.
name: 'Frigate Card',
name: 'Advanced Camera Card',
logo: 'images/icons/frigate.svg',
// The logo to show on the top of the sidebar.
logo: 'images/icons/iris.svg',
// Automatically go to the top of a page on route change.
auto2top: true,
@@ -59,7 +64,7 @@
// Automatically use headings up to H2 for sider.
subMaxLevel: 2,
// Show the Frigate Card cover page.
// Show the Advanced Camera Card cover page.
coverpage: true,
// Use relative links (this way both vscode and docsify work on clicking
+2
View File
@@ -13,6 +13,8 @@ There may be many versions of this card (see [release philosophy](./developing.m
- Click "Download"
- Reload your browser
[](./common/rename-hacs.md ':include')
### Rolling Back Manually
If you didn't use `HACS` to install the card, you're on your own to roll it
+2 -2
View File
@@ -19,7 +19,7 @@ incrementally improve, and I think time is better spent working on reproducible
issues or new features, than guessing what versions/options you are using. The
new issue template asks for the minimum possible information to support you:
- **Diagnostics**: On the card, hold down the Default/Frigate menu button for a
- **Diagnostics**: On the card, hold down the Iris (default) menu button for a
few seconds then paste the diagnostics into the issue between the backticks.
- **Description of the problem**: I need to understand the issue in sufficient
detail.
@@ -44,7 +44,7 @@ fixes should be provided, or new features developed, is misunderstanding the
fundamental dynamics of open source. I am sorry you feel this way, but open
source software (including this card) is typically provided "as-is". Take it or
leave it. If you want things to go faster / differently, [please
contribute](https://github.com/dermotduffy/frigate-hass-card/issues/1248). If
contribute](https://github.com/dermotduffy/advanced-camera-card/issues/1248). If
you don't want to contribute to the shared codebase, fork it and make your own.
Or pay for a (different) Enterprise grade solution to your problem. This is
certainly not that -- a card, developed in hobbiest-level time, with
+6 -6
View File
@@ -36,7 +36,7 @@ Debugging broken streams:
ensure [you have configured Frigate
accordingly](https://docs.frigate.video/configuration/live/#webrtc-extra-configuration).
1. Search for your symptoms on the [card issues
page](https://github.com/dermotduffy/frigate-hass-card/issues) and see if
page](https://github.com/dermotduffy/advanced-camera-card/issues) and see if
you find any prior relevant discussions.
If you're happy with just using an image stream but want the small circle to go
@@ -81,7 +81,7 @@ live:
disableGl: true
```
[This bug](https://github.com/dermotduffy/frigate-hass-card/issues/191) has some
[This bug](https://github.com/dermotduffy/advanced-camera-card/issues/191) has some
more discussion on this topic. New ideas to address this underlying limitation
most welcome!
@@ -97,7 +97,7 @@ by the card. Other browsers (e.g. Firefox, Safari) do not exhibit this behavior.
For some slowly loading cameras, for which [Home Assistant stream
preloading](https://www.home-assistant.io/integrations/camera/) is not enabled,
Home Assistant may return a blank white image when asked for a still. These
stills are used during initial Frigate card load of the `live` view if the
stills are used during initial Advanced Camera Card load of the `live` view if the
`live.show_image_during_load` option is enabled. Disabling this option should
show the default media loading controls (e.g. a spinner or empty video player)
instead of the blank white image.
@@ -130,7 +130,7 @@ The Android video player swallows `double_tap` interactions in order to
rewind or fast-forward. Workarounds:
- Use `hold` instead of `double_tap` for your card-wide action.
- Use a [Frigate Card Element](configuration/elements/README.md) or menu icon to
- Use an [Advanced Camera Card Element](configuration/elements/README.md) or menu icon to
trigger the action instead.
### Dragging in carousels broken in Firefox
@@ -252,10 +252,10 @@ status_bar:
[AlexxIT's WebRTC Card](https://github.com/AlexxIT/WebRTC) which is embedded by
the `webrtc_card` live provider internally disconnects the stream when the
browser tab is changed (regardless of any Frigate card configuration settings,
browser tab is changed (regardless of any Advanced Camera Card configuration settings,
e.g. `lazy_unload`). To allow the stream to continue running in the background,
pass the `background` argument to the `webrtc_card` live provider as shown
below. This effectively allows the Frigate card to decide whether or not to
below. This effectively allows the Advanced Camera Card to decide whether or not to
unload the stream.
```yaml
+1 -1
View File
@@ -23,7 +23,7 @@ challenging.
## Example configuration
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: go2rtc
+6 -6
View File
@@ -3,7 +3,7 @@
This card allows casting a camera stream to a Google Cast device. You can enable the cast button with:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: go2rtc
@@ -21,7 +21,7 @@ There are two different casting methods for cameras: `standard` and `dashboard`
This is the default casting method.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: go2rtc
@@ -41,7 +41,7 @@ The main disadvantage of this method is that the stream will be played through H
This method is powered by [Home Assistant Cast](https://cast.home-assistant.io) and requires additional configuration, but allows **low latency streaming** with go2rtc.
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: go2rtc
@@ -68,7 +68,7 @@ For the example above to work, a dashboard with `dashboard-cast` URL must exist:
![image](https://github.com/user-attachments/assets/67f0e145-df05-412a-8c6d-897feb5439d2)
Within that dashboard, create an `office` view and finally within that view you can place the Frigate card configured for that camera for a proper full-screen casting experience:
Within that dashboard, create an `office` view and finally within that view you can place the Advanced Camera Card configured for that camera for a proper full-screen casting experience:
```yaml
views:
@@ -76,7 +76,7 @@ views:
type: panel
path: office
cards:
- type: custom:frigate-card
- type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: go2rtc
@@ -92,7 +92,7 @@ The `casting` profile pre-configures the card to be casted to a 16:9 screen (suc
When casting to a Google Nest Hub, the following configuration can be used:
```yaml
type: custom:frigate-card
type: custom:advanced-camera-card
cameras:
- camera_entity: camera.office
live_provider: go2rtc
+13 -11
View File
@@ -1,12 +1,12 @@
# URL Actions
It is possible to pass the Frigate card one or more
It is possible to pass the Advanced Camera Card one or more
[actions](../configuration/actions/README.md) from the URL (e.g. select a particular
camera, open the live view in expanded mode, etc).
### When actions are executed
The Frigate card will execute these actions in the following circumstances:
The Advanced Camera Card will execute these actions in the following circumstances:
- On initial card load.
- On 'tab' change in a dashboard.
@@ -17,28 +17,30 @@ The Frigate card will execute these actions in the following circumstances:
## Instructions
To send an action to _all_ Frigate Cards on a dashboard:
To send an action to _all_ Advanced Camera Cards on a dashboard:
```
[PATH_TO_YOUR_HA_DASHBOARD]?frigate-card-action.[ACTION]=[VALUE]
[PATH_TO_YOUR_HA_DASHBOARD]?advanced-camera-card-action.[ACTION]=[VALUE]
```
To send an action to a specific named Frigate Card:
To send an action to a specific named Advanced Camera Card:
```
[PATH_TO_YOUR_HA_DASHBOARD]?frigate-card-action.[CARD_ID].[ACTION]=[VALUE]
[PATH_TO_YOUR_HA_DASHBOARD]?advanced-camera-card-action.[CARD_ID].[ACTION]=[VALUE]
```
?> For backwards compatibility, the card will also respond to `frigate-card-action` as a query-parameter with the same syntax.
| Parameter | Description |
| --------- | ------------------------------------------------------------------------------------------------- |
| `ACTION` | One of the supported Frigate Card custom actions. See below. |
| `ACTION` | One of the supported Advanced Camera Card custom actions. See below. |
| `CARD_ID` | When specified only cards that have a [`card_id`](../configuration/README.md) parameter will act. |
| `VALUE` | An optional value to use with the `camera_select` and `live_substream_select` actions. |
?> Both `.` and `:` may be used as the delimiter. If you use `:` some
browsers may require it be escaped to `%3A`.
!> If a dashboard has multiple Frigate cards on it, even if they are on
!> If a dashboard has multiple Advanced Camera Cards on it, even if they are on
different 'tabs' within that dashboard, they will all respond to the actions
unless the action is targeted with a `CARD_ID` as shown above.
@@ -59,16 +61,16 @@ Only a subset of all [actions](../configuration/actions/README.md) are supported
| `image` | :white_check_mark: | |
| `live_substream_select` | :white_check_mark: | |
| `live` | :white_check_mark: | |
| `media_player` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/frigate-hass-card/issues) if you need this. |
| `media_player` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
| `menu_toggle` | :white_check_mark: | |
| `microphone_connect`, `microphone_disconnect`, `microphone_mute`, `microphone_unmute` | :heavy_multiplication_x: | |
| `mute`, `unmute` | :heavy_multiplication_x: | |
| `play`, `pause` | :heavy_multiplication_x: | |
| `ptz` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/frigate-hass-card/issues) if you need this. |
| `ptz` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
| `recording` | :white_check_mark: | |
| `recordings` | :white_check_mark: | |
| `screenshot` | :heavy_multiplication_x: | Latest media information is not available on initial render. |
| `ptz_controls` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/frigate-hass-card/issues) if you need this. |
| `ptz_controls` | :heavy_multiplication_x: | Please [request](https://github.com/dermotduffy/advanced-camera-card/issues) if you need this. |
| `snapshot` | :white_check_mark: | |
| `snapshots` | :white_check_mark: | |
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "Frigate Card",
"name": "Advanced Camera Card",
"render_readme": true,
"filename": "frigate-hass-card.js",
"filename": "advanced-camera-card.js",
"homeassistant": "2022.3.0"
}
+9 -6
View File
@@ -1,8 +1,11 @@
{
"name": "frigate-hass-card",
"name": "advanced-camera-card",
"version": "0.0.0-dev",
"description": "Frigate Lovelace Card for Home Assistant",
"description": "Advanced Camera Card for Home Assistant",
"keywords": [
"advanced",
"camera",
"card",
"frigate",
"home-assistant",
"homeassistant",
@@ -10,8 +13,8 @@
"lovelace"
],
"type": "module",
"module": "frigate-hass-card.js",
"repository": "github:dermotduffy/frigate-hass-card",
"module": "advanced-camera-card.js",
"repository": "github:dermotduffy/advanced-camera-card",
"author": "Dermot Duffy <dermot.duffy@gmail.com>",
"license": "MIT",
"dependencies": {
@@ -149,7 +152,7 @@
{
"assets": [
{
"path": "frigate-hass-card.zip",
"path": "advanced-camera-card.zip",
"label": "Zip distribution"
},
{
@@ -163,7 +166,7 @@
"assignees": [
"dermotduffy"
],
"successComment": ":tada: This issue has been resolved in version ${nextRelease.version} :tada:\n\nSee: [GitHub release](https://github.com/dermotduffy/frigate-hass-card/releases/tag/${nextRelease.gitTag})",
"successComment": ":tada: This issue has been resolved in version ${nextRelease.version} :tada:\n\nSee: [GitHub release](https://github.com/dermotduffy/advanced-camera-card/releases/tag/${nextRelease.gitTag})",
"releaseNameTemplate": "v${nextRelease.version}"
}
]
+26 -16
View File
@@ -60,7 +60,7 @@ const plugins = [
preventAssignment: true,
values: {
'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production'),
__FRIGATE_CARD_RELEASE_VERSION__:
__ADVANCED_CAMERA_CARD_RELEASE_VERSION__:
process.env.RELEASE_VERSION ?? (dev ? 'dev' : 'pkg'),
},
}),
@@ -72,6 +72,23 @@ const plugins = [
}),
];
const outputEntryTemplate = {
entryFileNames: 'advanced-camera-card.js',
dir: 'dist',
chunkFileNames: (chunk) => {
// Add "lang-" to the front of the language chunk names for readability.
if (
chunk.facadeModuleId &&
chunk.facadeModuleId.match(/localize\/languages\/.*\.json/)
) {
return 'lang-[name]-[hash].js';
}
return '[name]-[hash].js';
},
format: 'es',
sourcemap: dev,
};
/**
* @type {import('rollup').RollupOptions}
*/
@@ -83,22 +100,15 @@ const config = {
// the hacstag, causing a re-download of the same content and functionality
// problems.
preserveEntrySignatures: 'strict',
output: {
entryFileNames: 'frigate-hass-card.js',
dir: 'dist',
chunkFileNames: (chunk) => {
// Add "lang-" to the front of the language chunk names for readability.
if (
chunk.facadeModuleId &&
chunk.facadeModuleId.match(/localize\/languages\/.*\.json/)
) {
return 'lang-[name]-[hash].js';
}
return '[name]-[hash].js';
output: [
outputEntryTemplate,
// Continue to include the old file name for backwards compatibility.
{
...outputEntryTemplate,
entryFileNames: 'frigate-hass-card.js',
},
format: 'es',
sourcemap: dev,
},
],
plugins: plugins,
// These files use this at the toplevel, which causes rollup warning
// spam on build: `this` has been rewritten to `undefined`.
+11 -11
View File
@@ -1,8 +1,8 @@
import { fireEvent } from '@dermotduffy/custom-card-helpers';
import type {
ActionHandlerDetail,
ActionHandlerOptions,
} from '@dermotduffy/custom-card-helpers';
import { fireEvent } from '@dermotduffy/custom-card-helpers';
import { noChange } from 'lit';
import {
AttributePart,
@@ -18,10 +18,10 @@ interface ActionHandlerInterface extends HTMLElement {
bind(element: Element, options): void;
}
interface ActionHandlerElement extends HTMLElement {
actionHandlerOptions?: FrigateCardActionHandlerOptions;
actionHandlerOptions?: AdvancedCameraCardActionHandlerOptions;
}
interface FrigateCardActionHandlerOptions extends ActionHandlerOptions {
interface AdvancedCameraCardActionHandlerOptions extends ActionHandlerOptions {
allowPropagation?: boolean;
}
@@ -56,7 +56,7 @@ class ActionHandler extends HTMLElement implements ActionHandlerInterface {
public bind(
element: ActionHandlerElement,
options?: FrigateCardActionHandlerOptions,
options?: AdvancedCameraCardActionHandlerOptions,
): void {
if (element.actionHandlerOptions) {
// Reset the options on an existing actionHandler.
@@ -160,15 +160,15 @@ class ActionHandler extends HTMLElement implements ActionHandlerInterface {
}
}
customElements.define('action-handler-frigate-card', ActionHandler);
customElements.define('action-handler-advanced-camera-card', ActionHandler);
const getActionHandler = (): ActionHandler => {
const body = document.body;
if (body.querySelector('action-handler-frigate-card')) {
return body.querySelector('action-handler-frigate-card') as ActionHandler;
if (body.querySelector('action-handler-advanced-camera-card')) {
return body.querySelector('action-handler-advanced-camera-card') as ActionHandler;
}
const actionhandler = document.createElement('action-handler-frigate-card');
const actionhandler = document.createElement('action-handler-advanced-camera-card');
body.appendChild(actionhandler);
return actionhandler as ActionHandler;
@@ -176,7 +176,7 @@ const getActionHandler = (): ActionHandler => {
const actionHandlerBind = (
element: ActionHandlerElement,
options?: FrigateCardActionHandlerOptions,
options?: AdvancedCameraCardActionHandlerOptions,
): void => {
const actionhandler: ActionHandler = getActionHandler();
if (!actionhandler) {
@@ -193,7 +193,7 @@ export const actionHandler = directive(
}
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
render(_options?: FrigateCardActionHandlerOptions) {}
render(_options?: AdvancedCameraCardActionHandlerOptions) {}
},
);
@@ -222,7 +222,7 @@ export interface ActionEventTarget extends EventTarget {
declare global {
interface HTMLElementTagNameMap {
'action-handler-frigate-card': ActionHandler;
'action-handler-advanced-camera-card': ActionHandler;
}
interface HASSDomEvents {
action: ActionHandlerDetail;
+3 -3
View File
@@ -1,4 +1,4 @@
import { FrigateCardError } from '../types.js';
import { AdvancedCameraCardError } from '../types.js';
export class CameraInitializationError extends FrigateCardError {}
export class CameraNoIDError extends FrigateCardError {}
export class CameraInitializationError extends AdvancedCameraCardError {}
export class CameraNoIDError extends AdvancedCameraCardError {}
+4 -4
View File
@@ -1,6 +1,6 @@
import { HomeAssistant } from '@dermotduffy/custom-card-helpers';
import { localize } from '../../localize/localize';
import { FrigateCardError } from '../../types';
import { AdvancedCameraCardError } from '../../types';
import { homeAssistantWSRequest } from '../../utils/ha/ws-request';
import { RecordingSegment } from '../types';
import {
@@ -38,7 +38,7 @@ export const getRecordingsSummary = async (
camera: camera_name,
// Ask for the summary relative to HA timezone
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1267
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1267
timezone: hass.config.time_zone,
},
true,
@@ -100,7 +100,7 @@ export async function retainEvent(
true,
);
if (!response.success) {
throw new FrigateCardError(localize('error.failed_retain'), {
throw new AdvancedCameraCardError(localize('error.failed_retain'), {
request: retainRequest,
response: response,
});
@@ -153,7 +153,7 @@ export const getEventSummary = async (
instance_id: clientID,
// Ask for the summary relative to HA timezone
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1267
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1267
timezone: hass.config.time_zone,
},
true,
+4 -4
View File
@@ -228,7 +228,7 @@ export class CameraManager {
}
// Engines are created sequentially, to avoid duplicate creation of the same
// engine. See: https://github.com/dermotduffy/frigate-hass-card/issues/941
// engine. See: https://github.com/dermotduffy/advanced-camera-card/issues/941
const engineByConfig = await this._getEnginesForCameras(camerasConfig);
// Configuration is initialized in parallel.
@@ -272,7 +272,7 @@ export class CameraManager {
log(
this._api.getConfigManager().getCardWideConfig(),
'Frigate Card CameraManager initialized (Cameras: ',
'Advanced Camera Card CameraManager initialized (Cameras: ',
this._store.getCameras(),
`, Duration: ${
(new Date().getTime() - initializationStartTime.getTime()) / 1000
@@ -546,7 +546,7 @@ export class CameraManager {
log(
this._api.getConfigManager().getCardWideConfig(),
'Frigate Card CameraManager favorite request (',
'Advanced Camera Card CameraManager favorite request (',
`Duration: ${(new Date().getTime() - queryStartTime.getTime()) / 1000}s,`,
'Media:',
media.getID(),
@@ -679,7 +679,7 @@ export class CameraManager {
log(
this._api.getConfigManager().getCardWideConfig(),
'Frigate Card CameraManager request [Input queries:',
'Advanced Camera Card CameraManager request [Input queries:',
_queries.length,
', Cached output queries:',
cachedOutputQueries,
+1 -1
View File
@@ -181,7 +181,7 @@ export class ReolinkCameraManagerEngine extends BrowseMediaCameraManagerEngine {
// First fetch all the Reolink cameras that show up under the media root,
// that match the expected camera. Some Reolink cameras will not show up
// here causing errors.
// https://github.com/dermotduffy/frigate-hass-card/issues/1723
// https://github.com/dermotduffy/advanced-camera-card/issues/1723
const camerasWithMedia = await this._browseMediaManager.walkBrowseMedias(
hass,
[
+1 -1
View File
@@ -48,7 +48,7 @@ export class CameraManagerStore implements CameraManagerReadOnlyConfigStore {
// In setting the store cameras, take great care to replace/add first before
// remove. Otherwise, there may be race conditions where the card attempts
// to render a view with (momentarily) no camera.
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1533
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1533
// Replace/Add the new cameras.
for (const camera of cameras) {
+2 -2
View File
@@ -1,5 +1,5 @@
import { AdvancedCameraCardView, SSLCiphers } from '../config/types';
import { CapabilityKey, Icon } from '../types';
import { FrigateCardView, SSLCiphers } from '../config/types';
import { ViewMedia } from '../view/media';
// ====
@@ -114,7 +114,7 @@ export interface CameraManagerCameraMetadata {
export interface CameraEndpointsContext {
media?: ViewMedia;
view?: FrigateCardView;
view?: AdvancedCameraCardView;
}
export interface CameraEndpoint {
@@ -67,9 +67,9 @@ export class ActionsManager {
if (
config &&
interaction &&
// Don't call frigateCardHandleActionConfig() unless there is explicitly an
// action defined (as it uses a default that is unhelpful for views that
// have default tap/click actions).
// Don't execute unless there is explicitly an action defined (as it uses
// a default that is unhelpful for views that have default tap/click
// actions).
actionConfig
) {
this.executeActions(actionConfig, config);
@@ -91,8 +91,8 @@ export class ActionsManager {
};
/**
* This method handles actions requested by components of the Frigate card
* itself (e.g. menu, PTZ controller).
* This method handles actions requested by components of the Advanced Camera
* Card itself (e.g. menu, PTZ controller).
*/
public handleActionExecutionRequestEvent = async (
ev: CustomEvent<ActionExecutionRequest>,
+3 -3
View File
@@ -1,5 +1,5 @@
import { ActionContext } from 'action';
import { FrigateCardCustomAction } from '../../../config/types';
import { AdvancedCameraCardCustomAction } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { Action, AuxillaryActionConfig } from '../types';
@@ -24,6 +24,6 @@ export class BaseAction<T> implements Action {
}
}
export class FrigateCardAction<
T extends FrigateCardCustomAction,
export class AdvancedCameraCardAction<
T extends AdvancedCameraCardCustomAction,
> extends BaseAction<T> {}
@@ -1,8 +1,8 @@
import { CameraSelectActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class CameraSelectAction extends FrigateCardAction<CameraSelectActionConfig> {
export class CameraSelectAction extends AdvancedCameraCardAction<CameraSelectActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
const selectCameraID =
this._action.camera ??
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class CameraUIAction extends FrigateCardAction<GeneralActionConfig> {
export class CameraUIAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getCameraURLManager().openURL();
}
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class DefaultAction extends FrigateCardAction<GeneralActionConfig> {
export class DefaultAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getViewManager().setViewDefaultWithNewQuery();
}
@@ -1,8 +1,8 @@
import { DisplayModeActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class DisplayModeSelectAction extends FrigateCardAction<DisplayModeActionConfig> {
export class DisplayModeSelectAction extends AdvancedCameraCardAction<DisplayModeActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getViewManager().setViewByParametersWithNewQuery({
params: {
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class DownloadAction extends FrigateCardAction<GeneralActionConfig> {
export class DownloadAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getDownloadManager().downloadViewerMedia();
}
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class ExpandAction extends FrigateCardAction<GeneralActionConfig> {
export class ExpandAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getExpandManager().toggleExpanded();
}
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class FullscreenAction extends FrigateCardAction<GeneralActionConfig> {
export class FullscreenAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getFullscreenManager().toggleFullscreen();
}
@@ -3,7 +3,7 @@ import { CardActionsAPI } from '../../types';
import { BaseAction } from './base';
/**
* Handles generic HA (non-Frigate) actions (e.g. 'more-info')
* Handles generic HA actions (e.g. 'more-info')
*/
export class GenericAction extends BaseAction<ActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
+2 -2
View File
@@ -1,8 +1,8 @@
import { LogActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class LogAction extends FrigateCardAction<LogActionConfig> {
export class LogAction extends AdvancedCameraCardAction<LogActionConfig> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async execute(_api: CardActionsAPI): Promise<void> {
console[this._action.level](this._action.message);
@@ -1,9 +1,9 @@
import { MediaPlayerActionConfig } from '../../../config/types';
import { getStreamCameraID } from '../../../utils/substream';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class MediaPlayerAction extends FrigateCardAction<MediaPlayerActionConfig> {
export class MediaPlayerAction extends AdvancedCameraCardAction<MediaPlayerActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
const mediaPlayer = this._action.media_player;
const mediaPlayerController = api.getMediaPlayerManager();
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class MenuToggleAction extends FrigateCardAction<GeneralActionConfig> {
export class MenuToggleAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getCardElementManager().toggleMenu();
}
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class MicrophoneConnectAction extends FrigateCardAction<GeneralActionConfig> {
export class MicrophoneConnectAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getMicrophoneManager().connect();
}
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class MicrophoneDisconnectAction extends FrigateCardAction<GeneralActionConfig> {
export class MicrophoneDisconnectAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getMicrophoneManager().disconnect();
}
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class MicrophoneMuteAction extends FrigateCardAction<GeneralActionConfig> {
export class MicrophoneMuteAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getMicrophoneManager().mute();
}
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class MicrophoneUnmuteAction extends FrigateCardAction<GeneralActionConfig> {
export class MicrophoneUnmuteAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getMicrophoneManager().unmute();
}
+2 -2
View File
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class MuteAction extends FrigateCardAction<GeneralActionConfig> {
export class MuteAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getMediaLoadedInfoManager().get()?.player?.mute();
}
+2 -2
View File
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class PauseAction extends FrigateCardAction<GeneralActionConfig> {
export class PauseAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getMediaLoadedInfoManager().get()?.player?.pause();
}
+2 -2
View File
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class PlayAction extends FrigateCardAction<GeneralActionConfig> {
export class PlayAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getMediaLoadedInfoManager().get()?.player?.play();
}
@@ -1,8 +1,8 @@
import { PTZControlsActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class PTZControlsAction extends FrigateCardAction<PTZControlsActionConfig> {
export class PTZControlsAction extends AdvancedCameraCardAction<PTZControlsActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getViewManager().setViewWithMergedContext({
ptzControls: { enabled: this._action.enabled },
@@ -10,12 +10,12 @@ import { PTZDigitialActionConfig, ZOOM_MAX, ZOOM_MIN } from '../../../config/typ
import { getPTZTarget } from '../../../utils/ptz';
import { Timer } from '../../../utils/timer';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { TargetedActionContext } from '../types';
import {
setInProgressForThisTarget,
stopInProgressForThisTarget,
} from '../utils/action-state';
import { AdvancedCameraCardAction } from './base';
const STEP_DELAY_SECONDS = 0.1;
const STEP_ZOOM = 0.1;
@@ -27,7 +27,7 @@ declare module 'action' {
}
}
export class PTZDigitalAction extends FrigateCardAction<PTZDigitialActionConfig> {
export class PTZDigitalAction extends AdvancedCameraCardAction<PTZDigitialActionConfig> {
protected _timer = new Timer();
protected async _stepChange(api: CardActionsAPI, targetID: string): Promise<void> {
@@ -2,11 +2,11 @@ import { PTZMultiActionConfig } from '../../../config/types';
import { createPTZAction, createPTZDigitalAction } from '../../../utils/action';
import { PTZType, getPTZTarget, hasCameraTruePTZ } from '../../../utils/ptz';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
import { PTZAction } from './ptz';
import { PTZDigitalAction } from './ptz-digital';
export class PTZMultiAction extends FrigateCardAction<PTZMultiActionConfig> {
export class PTZMultiAction extends AdvancedCameraCardAction<PTZMultiActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
const view = api.getViewManager().getView();
let targetID: string | null = null;
+2 -2
View File
@@ -6,7 +6,7 @@ import {
setInProgressForThisTarget,
stopInProgressForThisTarget,
} from '../utils/action-state';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
interface PTZContext {
[cameraID: string]: {
@@ -20,7 +20,7 @@ declare module 'action' {
}
}
export class PTZAction extends FrigateCardAction<PTZActionConfig> {
export class PTZAction extends AdvancedCameraCardAction<PTZActionConfig> {
protected _timer = new Timer();
public async stop(): Promise<void> {
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class ScreenshotAction extends FrigateCardAction<GeneralActionConfig> {
export class ScreenshotAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getDownloadManager().downloadScreenshot();
}
+2 -2
View File
@@ -2,9 +2,9 @@ import { SleepActionConfig } from '../../../config/types';
import { sleep } from '../../../utils/basic';
import { CardActionsAPI } from '../../types';
import { timeDeltaToSeconds } from '../utils/time-delta';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class SleepAction extends FrigateCardAction<SleepActionConfig> {
export class SleepAction extends AdvancedCameraCardAction<SleepActionConfig> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async execute(_api: CardActionsAPI): Promise<void> {
await sleep(timeDeltaToSeconds(this._action.duration));
@@ -1,8 +1,8 @@
import { StatusBarActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class StatusBarAction extends FrigateCardAction<StatusBarActionConfig> {
export class StatusBarAction extends AdvancedCameraCardAction<StatusBarActionConfig> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async execute(api: CardActionsAPI): Promise<void> {
switch (this._action.status_bar_action) {
@@ -1,9 +1,9 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { SubstreamOffViewModifier } from '../../view/modifiers/substream-off';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class SubstreamOffAction extends FrigateCardAction<GeneralActionConfig> {
export class SubstreamOffAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getViewManager().setViewByParameters({
modifiers: [new SubstreamOffViewModifier()],
@@ -1,9 +1,9 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { SubstreamOnViewModifier } from '../../view/modifiers/substream-on';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class SubstreamOnAction extends FrigateCardAction<GeneralActionConfig> {
export class SubstreamOnAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getViewManager().setViewByParameters({
modifiers: [new SubstreamOnViewModifier(api)],
@@ -1,9 +1,9 @@
import { SubstreamSelectActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { SubstreamSelectViewModifier } from '../../view/modifiers/substream-select';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class SubstreamSelectAction extends FrigateCardAction<SubstreamSelectActionConfig> {
export class SubstreamSelectAction extends AdvancedCameraCardAction<SubstreamSelectActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
api.getViewManager().setViewByParameters({
modifiers: [new SubstreamSelectViewModifier(this._action.camera)],
@@ -1,8 +1,8 @@
import { GeneralActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class UnmuteAction extends FrigateCardAction<GeneralActionConfig> {
export class UnmuteAction extends AdvancedCameraCardAction<GeneralActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getMediaLoadedInfoManager().get()?.player?.unmute();
}
+3 -3
View File
@@ -1,12 +1,12 @@
import { ViewActionConfig } from '../../../config/types';
import { CardActionsAPI } from '../../types';
import { FrigateCardAction } from './base';
import { AdvancedCameraCardAction } from './base';
export class ViewAction extends FrigateCardAction<ViewActionConfig> {
export class ViewAction extends AdvancedCameraCardAction<ViewActionConfig> {
public async execute(api: CardActionsAPI): Promise<void> {
await api.getViewManager().setViewByParametersWithNewQuery({
params: {
view: this._action.frigate_card_action,
view: this._action.advanced_camera_card_action,
},
});
}
+35 -35
View File
@@ -43,8 +43,8 @@ export class ActionFactory {
cardID?: string;
},
): Action | null {
const frigateCardAction = convertActionToCardCustomAction(action);
if (action.action !== 'fire-dom-event' || !frigateCardAction) {
const cardCustomAction = convertActionToCardCustomAction(action);
if (action.action !== 'fire-dom-event' || !cardCustomAction) {
// * There is a slight typing (but not functional) difference between
// ActionType in this card and ActionConfig in `custom-card-helpers`. See
// `ExtendedConfirmationRestrictionConfig` in `types.ts` for the source and
@@ -54,15 +54,15 @@ export class ActionFactory {
if (
// Command not intended for this card (e.g. query string command).
frigateCardAction.card_id &&
frigateCardAction.card_id !== options?.cardID
cardCustomAction.card_id &&
cardCustomAction.card_id !== options?.cardID
) {
return null;
}
switch (frigateCardAction.frigate_card_action) {
switch (cardCustomAction.advanced_camera_card_action) {
case 'default':
return new DefaultAction(context, frigateCardAction, options?.config);
return new DefaultAction(context, cardCustomAction, options?.config);
case 'clip':
case 'clips':
case 'image':
@@ -73,70 +73,70 @@ export class ActionFactory {
case 'snapshots':
case 'timeline':
case 'diagnostics':
return new ViewAction(context, frigateCardAction, options?.config);
return new ViewAction(context, cardCustomAction, options?.config);
case 'sleep':
return new SleepAction(context, frigateCardAction, options?.config);
return new SleepAction(context, cardCustomAction, options?.config);
case 'download':
return new DownloadAction(context, frigateCardAction, options?.config);
return new DownloadAction(context, cardCustomAction, options?.config);
case 'camera_ui':
return new CameraUIAction(context, frigateCardAction, options?.config);
return new CameraUIAction(context, cardCustomAction, options?.config);
case 'expand':
return new ExpandAction(context, frigateCardAction, options?.config);
return new ExpandAction(context, cardCustomAction, options?.config);
case 'fullscreen':
return new FullscreenAction(context, frigateCardAction, options?.config);
return new FullscreenAction(context, cardCustomAction, options?.config);
case 'menu_toggle':
return new MenuToggleAction(context, frigateCardAction, options?.config);
return new MenuToggleAction(context, cardCustomAction, options?.config);
case 'camera_select':
return new CameraSelectAction(context, frigateCardAction, options?.config);
return new CameraSelectAction(context, cardCustomAction, options?.config);
case 'live_substream_select':
return new SubstreamSelectAction(context, frigateCardAction, options?.config);
return new SubstreamSelectAction(context, cardCustomAction, options?.config);
case 'live_substream_off':
return new SubstreamOffAction(context, frigateCardAction, options?.config);
return new SubstreamOffAction(context, cardCustomAction, options?.config);
case 'live_substream_on':
return new SubstreamOnAction(context, frigateCardAction, options?.config);
return new SubstreamOnAction(context, cardCustomAction, options?.config);
case 'media_player':
return new MediaPlayerAction(context, frigateCardAction, options?.config);
return new MediaPlayerAction(context, cardCustomAction, options?.config);
case 'microphone_connect':
return new MicrophoneConnectAction(context, frigateCardAction, options?.config);
return new MicrophoneConnectAction(context, cardCustomAction, options?.config);
case 'microphone_disconnect':
return new MicrophoneDisconnectAction(
context,
frigateCardAction,
cardCustomAction,
options?.config,
);
case 'microphone_mute':
return new MicrophoneMuteAction(context, frigateCardAction, options?.config);
return new MicrophoneMuteAction(context, cardCustomAction, options?.config);
case 'microphone_unmute':
return new MicrophoneUnmuteAction(context, frigateCardAction, options?.config);
return new MicrophoneUnmuteAction(context, cardCustomAction, options?.config);
case 'mute':
return new MuteAction(context, frigateCardAction, options?.config);
return new MuteAction(context, cardCustomAction, options?.config);
case 'unmute':
return new UnmuteAction(context, frigateCardAction, options?.config);
return new UnmuteAction(context, cardCustomAction, options?.config);
case 'play':
return new PlayAction(context, frigateCardAction, options?.config);
return new PlayAction(context, cardCustomAction, options?.config);
case 'pause':
return new PauseAction(context, frigateCardAction, options?.config);
return new PauseAction(context, cardCustomAction, options?.config);
case 'screenshot':
return new ScreenshotAction(context, frigateCardAction, options?.config);
return new ScreenshotAction(context, cardCustomAction, options?.config);
case 'display_mode_select':
return new DisplayModeSelectAction(context, frigateCardAction, options?.config);
return new DisplayModeSelectAction(context, cardCustomAction, options?.config);
case 'ptz':
return new PTZAction(context, frigateCardAction, options?.config);
return new PTZAction(context, cardCustomAction, options?.config);
case 'ptz_digital':
return new PTZDigitalAction(context, frigateCardAction, options?.config);
return new PTZDigitalAction(context, cardCustomAction, options?.config);
case 'ptz_multi':
return new PTZMultiAction(context, frigateCardAction, options?.config);
return new PTZMultiAction(context, cardCustomAction, options?.config);
case 'ptz_controls':
return new PTZControlsAction(context, frigateCardAction, options?.config);
return new PTZControlsAction(context, cardCustomAction, options?.config);
case 'log':
return new LogAction(context, frigateCardAction, options?.config);
return new LogAction(context, cardCustomAction, options?.config);
case 'status_bar':
return new StatusBarAction(context, frigateCardAction, options?.config);
return new StatusBarAction(context, cardCustomAction, options?.config);
}
/* istanbul ignore next: this path cannot be reached -- @preserve */
console.warn(
`Frigate card received unknown card action: ${frigateCardAction['frigate_card_action']}`,
`Advanced Camera Card received unknown card action: ${cardCustomAction['advanced_camera_card_action']}`,
);
/* istanbul ignore next: this path cannot be reached -- @preserve */
return null;
@@ -1,16 +1,16 @@
import { dispatchFrigateCardEvent } from '../../../utils/basic';
import { dispatchAdvancedCameraCardEvent } from '../../../utils/basic';
import { ActionExecutionRequest } from '../types';
export const dispatchActionExecutionRequest = (
element: HTMLElement,
request: ActionExecutionRequest,
) => {
dispatchFrigateCardEvent(element, 'action:execution-request', request);
dispatchAdvancedCameraCardEvent(element, 'action:execution-request', request);
};
export interface ActionExecutionRequestEventTarget extends EventTarget {
addEventListener(
event: 'frigate-card:action:execution-request',
event: 'advanced-camera-card:action:execution-request',
listener: (
this: ActionExecutionRequestEventTarget,
ev: CustomEvent<ActionExecutionRequest>,
@@ -23,7 +23,7 @@ export interface ActionExecutionRequestEventTarget extends EventTarget {
options?: AddEventListenerOptions | boolean,
): void;
removeEventListener(
event: 'frigate-card:action:execution-request',
event: 'advanced-camera-card:action:execution-request',
listener: (
this: ActionExecutionRequestEventTarget,
ev: CustomEvent<ActionExecutionRequest>,
+1 -1
View File
@@ -31,7 +31,7 @@ export class AutomationsManager {
!this._api.getHASSManager().hasHASS() ||
// Never execute automations if the card hasn't finished initializing, as
// it could cause a view change when camera loads are not finished.
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1407
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1407
!this._api.getInitializationManager().isInitializedMandatory() ||
// Never execute automations if there's an error (as our automation loop
// avoidance -- which shows as an error -- would not work!).
+3 -3
View File
@@ -78,7 +78,7 @@ export class CardElementManager {
...(this._api.getConfigManager().getConfig()?.view.render_entities ?? []),
// Refresh the card if media player state changes:
// https://github.com/dermotduffy/frigate-hass-card/issues/881
// https://github.com/dermotduffy/advanced-camera-card/issues/881
...(this._api.getMediaPlayerManager().getMediaPlayers() ?? []),
]);
@@ -109,7 +109,7 @@ export class CardElementManager {
this._api.getInteractionManager().reportInteraction,
);
this._element.addEventListener(
'frigate-card:action:execution-request',
'advanced-camera-card:action:execution-request',
this._api.getActionsManager().handleActionExecutionRequestEvent,
);
@@ -179,7 +179,7 @@ export class CardElementManager {
this._api.getInteractionManager().reportInteraction,
);
this._element.removeEventListener(
'frigate-card:action:execution-request',
'advanced-camera-card:action:execution-request',
this._api.getActionsManager().handleActionExecutionRequestEvent,
);
+18 -17
View File
@@ -10,14 +10,14 @@ import {
setConfigValue,
} from '../config/management';
import {
FrigateCardCondition,
frigateConditionalSchema,
AdvancedCameraCardCondition,
advancedCameraCardConditionalSchema,
Overrides,
RawFrigateCardConfig,
RawAdvancedCameraCardConfig,
ViewDisplayMode,
} from '../config/types';
import { localize } from '../localize/localize';
import { FrigateCardError, MediaLoadedInfo } from '../types';
import { AdvancedCameraCardError, MediaLoadedInfo } from '../types';
import { desparsifyArrays } from '../utils/basic';
import { isCompanionApp } from '../utils/companion';
import { CardConditionAPI, KeysState, MicrophoneState } from './types';
@@ -38,25 +38,26 @@ export interface ConditionState {
view?: string;
}
class OverrideConfigurationError extends FrigateCardError {}
class OverrideConfigurationError extends AdvancedCameraCardError {}
export class ConditionsEvaluateRequestEvent extends Event {
public conditions: FrigateCardCondition[];
public conditions: AdvancedCameraCardCondition[];
public evaluation?: boolean;
constructor(conditions: FrigateCardCondition[], eventInitDict?: EventInit) {
super('frigate-card:conditions:evaluate', eventInitDict);
constructor(conditions: AdvancedCameraCardCondition[], eventInitDict?: EventInit) {
super('advanced-camera-card:conditions:evaluate', eventInitDict);
this.conditions = conditions;
}
}
/**
* Evaluate whether a frigateCardCondition is met using an event to evaluate.
* Evaluate whether an AdvancedCameraCardCondition is met using an event to
* evaluate.
* @returns A boolean indicating whether the condition is met.
*/
export function evaluateConditionViaEvent(
element: HTMLElement,
conditions?: FrigateCardCondition[],
conditions?: AdvancedCameraCardCondition[],
): boolean {
if (!conditions) {
return true;
@@ -69,7 +70,7 @@ export function evaluateConditionViaEvent(
/* Special note on what's going on here:
*
* Some parts of the card (e.g. <frigate-card-elements>) may have arbitrary
* Some parts of the card (e.g. <advanced-camera-card-elements>) may have arbitrary
* complexity and layers (that this card doesn't control) between that master
* element and the element that needs to evaluate the condition. In these
* cases there's no clean way to pass state from the rest of card down through
@@ -83,7 +84,7 @@ export function evaluateConditionViaEvent(
return evaluateEvent.evaluation ?? false;
}
export function getOverriddenConfig<RT extends RawFrigateCardConfig>(
export function getOverriddenConfig<RT extends RawAdvancedCameraCardConfig>(
manager: Readonly<ConditionsManager>,
config: Readonly<RT>,
options?: {
@@ -198,9 +199,9 @@ export class ConditionsManager {
public setConditionsFromConfig(): void {
this.removeConditions();
const getAllConditions = (): FrigateCardCondition[] => {
const getAllConditions = (): AdvancedCameraCardCondition[] => {
const config = this._api.getConfigManager().getConfig();
const conditions: FrigateCardCondition[] = [];
const conditions: AdvancedCameraCardCondition[] = [];
config?.overrides?.forEach((override) => conditions.push(...override.conditions));
config?.automations?.forEach((automation) =>
conditions.push(...automation.conditions),
@@ -210,7 +211,7 @@ export class ConditionsManager {
// custom elements that this card may not known. Here we recursively parse
// down the elements tree, parsing as we go to find valid conditions.
const getElementsConditions = (data: unknown): void => {
const parseResult = frigateConditionalSchema.safeParse(data);
const parseResult = advancedCameraCardConditionalSchema.safeParse(data);
if (parseResult.success) {
conditions.push(...parseResult.data.conditions);
parseResult.data.elements?.forEach(getElementsConditions);
@@ -265,7 +266,7 @@ export class ConditionsManager {
}
public evaluateConditions(
conditions: Readonly<FrigateCardCondition>[],
conditions: Readonly<AdvancedCameraCardCondition>[],
stateOverrides?: Partial<ConditionState>,
): boolean {
return conditions.every((conditionObj) =>
@@ -274,7 +275,7 @@ export class ConditionsManager {
}
protected _evaluateCondition(
conditionObj: Readonly<FrigateCardCondition>,
conditionObj: Readonly<AdvancedCameraCardCondition>,
stateOverrides?: Partial<ConditionState>,
): boolean {
const state = {
+15 -15
View File
@@ -1,13 +1,13 @@
import isEqual from 'lodash-es/isEqual';
import { isConfigUpgradeable } from '../../config/management.js';
import { setProfiles } from '../../config/profiles/index.js';
import {
AdvancedCameraCardConfig,
advancedCameraCardConfigSchema,
CardWideConfig,
FrigateCardConfig,
frigateCardConfigSchema,
RawFrigateCardConfig,
RawAdvancedCameraCardConfig,
} from '../../config/types.js';
import { localize } from '../../localize/localize.js';
import { setProfiles } from '../../config/profiles/index.js';
import { getParseErrorPaths } from '../../utils/zod.js';
import { getOverriddenConfig } from '../conditions-manager.js';
import { InitializationAspect } from '../initialization-manager.js';
@@ -22,9 +22,9 @@ export class ConfigManager {
// get the correct configuration (which will return overrides as appropriate).
// This variable must be called `_config` or `config` to be compatible with
// card-mod.
protected _config: FrigateCardConfig | null = null;
protected _overriddenConfig: FrigateCardConfig | null = null;
protected _rawConfig: RawFrigateCardConfig | null = null;
protected _config: AdvancedCameraCardConfig | null = null;
protected _overriddenConfig: AdvancedCameraCardConfig | null = null;
protected _rawConfig: RawAdvancedCameraCardConfig | null = null;
protected _cardWideConfig: CardWideConfig | null = null;
constructor(api: CardConfigAPI) {
@@ -35,7 +35,7 @@ export class ConfigManager {
return !!this.getConfig();
}
public getConfig(): FrigateCardConfig | null {
public getConfig(): AdvancedCameraCardConfig | null {
return this._overriddenConfig ?? this._config;
}
@@ -43,20 +43,20 @@ export class ConfigManager {
return this._cardWideConfig;
}
public getNonOverriddenConfig(): FrigateCardConfig | null {
public getNonOverriddenConfig(): AdvancedCameraCardConfig | null {
return this._config;
}
public getRawConfig(): RawFrigateCardConfig | null {
public getRawConfig(): RawAdvancedCameraCardConfig | null {
return this._rawConfig;
}
public setConfig(inputConfig?: RawFrigateCardConfig): void {
public setConfig(inputConfig?: RawAdvancedCameraCardConfig): void {
if (!inputConfig) {
throw new Error(localize('error.invalid_configuration'));
}
const parseResult = frigateCardConfigSchema.safeParse(inputConfig);
const parseResult = advancedCameraCardConfigSchema.safeParse(inputConfig);
if (!parseResult.success) {
const configUpgradeable = isConfigUpgradeable(inputConfig);
const hint = getParseErrorPaths(parseResult.error);
@@ -113,11 +113,11 @@ export class ConfigManager {
return;
}
let overriddenConfig: FrigateCardConfig | null = null;
let overriddenConfig: AdvancedCameraCardConfig | null = null;
try {
overriddenConfig = getOverriddenConfig(conditionsManager, this._config, {
configOverrides: this._config.overrides,
schema: frigateCardConfigSchema,
schema: advancedCameraCardConfigSchema,
});
} catch (ev) {
this._api.getMessageManager().setErrorIfHigherPriority(ev);
@@ -162,7 +162,7 @@ export class ConfigManager {
* card hard requires, use InitializationManager instead.
*/
protected async _initializeBackground(
previousConfig: FrigateCardConfig | null,
previousConfig: AdvancedCameraCardConfig | null,
): Promise<void> {
await this._api.getDefaultManager().initializeIfNecessary(previousConfig);
await this._api.getMediaPlayerManager().initializeIfNecessary(previousConfig);
+4 -4
View File
@@ -1,7 +1,7 @@
import { LovelaceCardEditor } from '@dermotduffy/custom-card-helpers';
import { ReactiveController } from 'lit';
import { CameraManager } from '../camera-manager/manager';
import { FrigateCardConfig } from '../config/types';
import { AdvancedCameraCardConfig } from '../config/types';
import {
createDeviceRegistryCache,
DeviceRegistryManager,
@@ -177,7 +177,7 @@ export class CardController
public static async getConfigElement(): Promise<LovelaceCardEditor> {
await import('../editor.js');
return document.createElement('frigate-card-editor');
return document.createElement('advanced-camera-card-editor');
}
public getConfigManager(): ConfigManager {
@@ -255,7 +255,7 @@ export class CardController
return this._statusBarItemManager;
}
public static getStubConfig(entities: string[]): FrigateCardConfig {
public static getStubConfig(entities: string[]): AdvancedCameraCardConfig {
const cameraEntity = entities.find((element) => element.startsWith('camera.'));
return {
cameras: [
@@ -266,7 +266,7 @@ export class CardController
// Need to use 'as unknown' to convince Typescript that this really isn't a
// mistake, despite the miniscule size of the configuration vs the full type
// description.
} as unknown as FrigateCardConfig;
} as unknown as AdvancedCameraCardConfig;
}
public getStyleManager(): StyleManager {
+2 -2
View File
@@ -1,5 +1,5 @@
import isEqual from 'lodash-es/isEqual';
import { FrigateCardConfig } from '../config/types';
import { AdvancedCameraCardConfig } from '../config/types';
import { createGeneralAction } from '../utils/action';
import { isActionAllowedBasedOnInteractionState } from '../utils/interaction-mode';
import { Timer } from '../utils/timer';
@@ -17,7 +17,7 @@ export class DefaultManager {
}
public async initializeIfNecessary(
previousConfig: FrigateCardConfig | null,
previousConfig: AdvancedCameraCardConfig | null,
): Promise<void> {
if (
!isEqual(
@@ -9,7 +9,7 @@ const WEBKIT_PLAY_SECONDS = 0.5;
/**
* Fullscreen implementation for webkit based browsers that do not support the
* standard Fullscreen API (expected to be exclusively iOS on an iPhone).
* See: https://github.com/dermotduffy/frigate-hass-card/issues/1444
* See: https://github.com/dermotduffy/advanced-camera-card/issues/1444
*/
export class WebkitFullScreenProvider
extends FullscreenProviderBase
@@ -94,8 +94,8 @@ export class InitializationManager {
!(await this._initializer.initializeMultipleIfNecessary({
[InitializationAspect.CAMERAS]: async () => {
// Recreate the camera manager to guarantee an immediate re-render.
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1811
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1769
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1811
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1769
this._api.createCameraManager();
return await this._api.getCameraManager().initializeCamerasFromConfig();
},
@@ -103,7 +103,7 @@ export class InitializationManager {
// Connecting the microphone (if configured) is considered mandatory to
// avoid issues with some cameras that only allow 2-way audio on the
// first stream initialized.
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1235
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1235
...(this._api.getMicrophoneManager().shouldConnectOnInitialization() && {
[InitializationAspect.MICROPHONE_CONNECT]: async () => {
// Recreate the microphone manager to guarantee an immediate
+1 -1
View File
@@ -23,7 +23,7 @@ export class MediaLoadedInfoManager {
log(
this._api.getConfigManager().getCardWideConfig(),
`Frigate Card media load: `,
`Advanced Camera Card media load: `,
mediaLoadedInfo,
);
+4 -4
View File
@@ -1,4 +1,4 @@
import { CameraConfig, FrigateCardConfig } from '../config/types';
import { AdvancedCameraCardConfig, CameraConfig } from '../config/types';
import {
MEDIA_PLAYER_SUPPORT_BROWSE_MEDIA,
MEDIA_PLAYER_SUPPORT_STOP,
@@ -6,8 +6,8 @@ import {
} from '../const';
import { localize } from '../localize/localize';
import { errorToConsole } from '../utils/basic';
import { Entity } from '../utils/ha/registry/entity/types';
import { supportsFeature } from '../utils/ha';
import { Entity } from '../utils/ha/registry/entity/types';
import { ViewMedia } from '../view/media';
import { ViewMediaClassifier } from '../view/media-classifier';
import { CardMediaPlayerAPI } from './types';
@@ -30,7 +30,7 @@ export class MediaPlayerManager {
}
public async initializeIfNecessary(
previousConfig: FrigateCardConfig | null,
previousConfig: AdvancedCameraCardConfig | null,
): Promise<void> {
if (
previousConfig?.menu.buttons.media_player.enabled !==
@@ -80,7 +80,7 @@ export class MediaPlayerManager {
// available in the HA state, only in the registry).
this._mediaPlayers = mediaPlayers.filter((entityID) => {
// Specifically allow for media players that are not found in the entity registry:
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1016
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1016
const entity = mediaPlayerEntities?.get(entityID);
return !entity || !entity.hidden_by;
});
+2 -2
View File
@@ -1,4 +1,4 @@
import { FrigateCardError, Message, MessageType } from '../types';
import { AdvancedCameraCardError, Message, MessageType } from '../types';
import { errorToConsole } from '../utils/basic';
import { CardMessageAPI } from './types';
@@ -60,7 +60,7 @@ export class MessageManager {
this.setMessageIfHigherPriority({
message: prefix ? `${prefix}: ${error.message}` : String(error.message),
type: 'error',
...(error instanceof FrigateCardError && { context: error.context }),
...(error instanceof AdvancedCameraCardError && { context: error.context }),
});
}
+1 -1
View File
@@ -42,7 +42,7 @@ export class MicrophoneManager {
public isSupported(): boolean {
// Some browsers will have mediaDevices/getUserMedia as undefined if
// accessed over http.
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1543
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1543
return !!navigator.mediaDevices?.getUserMedia;
}
+13 -13
View File
@@ -1,4 +1,4 @@
import { FrigateCardCustomAction, ViewActionConfig } from '../config/types';
import { AdvancedCameraCardCustomAction, ViewActionConfig } from '../config/types';
import { createCameraAction, createGeneralAction } from '../utils/action.js';
import { ViewParameters } from '../view/view';
import { CardQueryStringAPI } from './types';
@@ -9,7 +9,7 @@ interface QueryStringViewIntent {
default?: boolean;
substream?: string;
};
other?: FrigateCardCustomAction[];
other?: AdvancedCameraCardCustomAction[];
}
export class QueryStringManager {
@@ -72,14 +72,14 @@ export class QueryStringManager {
const result: QueryStringViewIntent = {};
for (const action of this._getActions()) {
if (this._isViewAction(action)) {
(result.view ??= {}).view = action.frigate_card_action;
(result.view ??= {}).view = action.advanced_camera_card_action;
(result.view ??= {}).default = undefined;
} else if (action.frigate_card_action === 'default') {
} else if (action.advanced_camera_card_action === 'default') {
(result.view ??= {}).default = true;
(result.view ??= {}).view = undefined;
} else if (action.frigate_card_action === 'camera_select') {
} else if (action.advanced_camera_card_action === 'camera_select') {
(result.view ??= {}).camera = action.camera;
} else if (action.frigate_card_action === 'live_substream_select') {
} else if (action.advanced_camera_card_action === 'live_substream_select') {
(result.view ??= {}).substream = action.camera;
} else {
(result.other ??= []).push(action);
@@ -88,11 +88,11 @@ export class QueryStringManager {
return result;
}
protected _getActions(): FrigateCardCustomAction[] {
protected _getActions(): AdvancedCameraCardCustomAction[] {
const params = new URLSearchParams(window.location.search);
const actions: FrigateCardCustomAction[] = [];
const actions: AdvancedCameraCardCustomAction[] = [];
const actionRE = new RegExp(
/^frigate-card-action([.:](?<cardID>\w+))?[.:](?<action>\w+)/,
/^(advanced-camera-card|frigate-card)-action([.:](?<cardID>\w+))?[.:](?<action>\w+)/,
);
for (const [key, value] of params.entries()) {
const match = key.match(actionRE);
@@ -102,7 +102,7 @@ export class QueryStringManager {
const cardID: string | undefined = match.groups['cardID'];
const action = match.groups['action'];
let customAction: FrigateCardCustomAction | null = null;
let customAction: AdvancedCameraCardCustomAction | null = null;
switch (action) {
case 'camera_select':
case 'live_substream_select':
@@ -133,7 +133,7 @@ export class QueryStringManager {
break;
default:
console.warn(
`Frigate card received unknown card action in query string: ${action}`,
`Advanced Camera Card received unknown card action in query string: ${action}`,
);
}
if (customAction) {
@@ -144,9 +144,9 @@ export class QueryStringManager {
}
protected _isViewAction = (
action: FrigateCardCustomAction,
action: AdvancedCameraCardCustomAction,
): action is ViewActionConfig => {
switch (action.frigate_card_action) {
switch (action.advanced_camera_card_action) {
case 'clip':
case 'clips':
case 'diagnostics':
@@ -62,7 +62,7 @@ export class StatusBarItemManager {
...(title
? [
{
type: 'custom:frigate-card-status-bar-string' as const,
type: 'custom:advanced-camera-card-status-bar-string' as const,
string: title,
expand: true,
sufficient: true,
@@ -74,7 +74,7 @@ export class StatusBarItemManager {
...(resolution
? [
{
type: 'custom:frigate-card-status-bar-string' as const,
type: 'custom:advanced-camera-card-status-bar-string' as const,
string: resolution,
...options?.statusConfig?.items.resolution,
},
@@ -84,7 +84,7 @@ export class StatusBarItemManager {
...(technology && technology === 'webrtc'
? [
{
type: 'custom:frigate-card-status-bar-icon' as const,
type: 'custom:advanced-camera-card-status-bar-icon' as const,
icon: 'mdi:webrtc',
...options?.statusConfig?.items.technology,
},
@@ -92,7 +92,7 @@ export class StatusBarItemManager {
: !!technology
? [
{
type: 'custom:frigate-card-status-bar-string' as const,
type: 'custom:advanced-camera-card-status-bar-string' as const,
string: technology.toUpperCase(),
...options?.statusConfig?.items.technology,
},
@@ -102,7 +102,7 @@ export class StatusBarItemManager {
...(engineIcon
? [
{
type: 'custom:frigate-card-status-bar-icon' as const,
type: 'custom:advanced-camera-card-status-bar-icon' as const,
icon: engineIcon,
...options?.statusConfig?.items.engine,
},
+11 -11
View File
@@ -1,7 +1,7 @@
import { StyleInfo } from 'lit/directives/style-map';
import {
FrigateCardConfig,
frigateCardConfigDefaults,
AdvancedCameraCardConfig,
configDefaults,
ThemeConfig,
ThemeName,
} from '../config/types';
@@ -25,7 +25,7 @@ export class StyleManager {
// as dimension configuration does not apply in fullscreen or expanded mode.
const lastKnown = this._api.getMediaLoadedInfoManager().getLastKnown();
card.style.setProperty(
'--frigate-card-expand-aspect-ratio',
'--advanced-camera-card-expand-aspect-ratio',
view?.isAnyMediaView() && lastKnown
? `${lastKnown.width} / ${lastKnown.height}`
: 'unset',
@@ -35,16 +35,16 @@ export class StyleManager {
// space.
const isGrid = view?.isGrid();
card.style.setProperty(
'--frigate-card-expand-width',
'--advanced-camera-card-expand-width',
!isGrid && view?.isAnyMediaView()
? 'none'
: 'var(--frigate-card-expand-max-width)',
: 'var(--advanced-camera-card-expand-max-width)',
);
card.style.setProperty(
'--frigate-card-expand-height',
'--advanced-camera-card-expand-height',
!isGrid && view?.isAnyMediaView()
? 'none'
: 'var(--frigate-card-expand-max-height)',
: 'var(--advanced-camera-card-expand-max-height)',
);
}
@@ -76,7 +76,7 @@ export class StyleManager {
protected _getThemeNames(themeConfig: ThemeConfig): ThemeName[] | null {
return themeConfig.themes.length
? themeConfig.themes
: frigateCardConfigDefaults.view.theme.themes;
: configDefaults.view.theme.themes;
}
protected _setDimmable(): void {
@@ -92,7 +92,7 @@ export class StyleManager {
const config = this._api.getConfigManager().getConfig();
if (config) {
const card = this._api.getCardElementManager().getElement();
card.style.setProperty('--frigate-card-height', config.dimensions.height);
card.style.setProperty('--advanced-camera-card-height', config.dimensions.height);
}
}
@@ -106,7 +106,7 @@ export class StyleManager {
const styles = performance?.style ?? {};
for (const configKey of Object.keys(styles)) {
const CSSKey = `--frigate-card-css-${configKey.replaceAll('_', '-')}`;
const CSSKey = `--advanced-camera-card-css-${configKey.replaceAll('_', '-')}`;
if (styles[configKey] === false) {
element.style.setProperty(CSSKey, STYLE_DISABLE_MAP[configKey]);
} else {
@@ -116,7 +116,7 @@ export class StyleManager {
}
protected _isAspectRatioEnforced(
config: FrigateCardConfig,
config: AdvancedCameraCardConfig,
view?: View | null,
): boolean {
const aspectRatioMode = config.dimensions.aspect_ratio_mode;
+13 -13
View File
@@ -1,7 +1,7 @@
import {
FRIGATE_CARD_VIEW_DEFAULT,
FrigateCardConfig,
FrigateCardView,
VIEW_DEFAULT,
AdvancedCameraCardConfig,
AdvancedCameraCardView,
ViewDisplayMode,
} from '../../config/types';
import { localize } from '../../localize/localize';
@@ -26,7 +26,7 @@ export class ViewFactory {
// Neither options.baseView.camera nor options.baseView.view are respected
// here, since this is the default view / camera.
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1564
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1564
let cameraID: string | null = null;
const viewName = options?.params?.view ?? config.view.default;
@@ -101,11 +101,8 @@ export class ViewFactory {
}
if (!this.isViewSupportedByCamera(cameraID, viewName)) {
if (
options?.failSafe &&
this.isViewSupportedByCamera(cameraID, FRIGATE_CARD_VIEW_DEFAULT)
) {
viewName = FRIGATE_CARD_VIEW_DEFAULT;
if (options?.failSafe && this.isViewSupportedByCamera(cameraID, VIEW_DEFAULT)) {
viewName = VIEW_DEFAULT;
} else {
const capabilities = this._api
.getCameraManager()
@@ -124,7 +121,7 @@ export class ViewFactory {
const configuredDisplayMode = this._getDefaultDisplayModeForView(viewName, config);
const displayMode =
// Prioritize the configured display mode (if present).
// See: https://github.com/dermotduffy/frigate-hass-card/issues/1812
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1812
(viewName !== options?.baseView?.view ? configuredDisplayMode : null) ??
options?.params?.displayMode ??
options?.baseView?.displayMode ??
@@ -147,13 +144,16 @@ export class ViewFactory {
return view;
}
public isViewSupportedByCamera(cameraID: string, view: FrigateCardView): boolean {
public isViewSupportedByCamera(
cameraID: string,
view: AdvancedCameraCardView,
): boolean {
return !!getCameraIDsForViewName(this._api.getCameraManager(), view, cameraID).size;
}
protected _getDefaultDisplayModeForView(
viewName: FrigateCardView,
config: FrigateCardConfig,
viewName: AdvancedCameraCardView,
config: AdvancedCameraCardConfig,
): ViewDisplayMode | null {
let mode: ViewDisplayMode | null = null;
switch (viewName) {
+5 -5
View File
@@ -1,6 +1,6 @@
import { ViewContext } from 'view';
import { FrigateCardView } from '../../config/types.js';
import { FrigateCardError } from '../../types.js';
import { AdvancedCameraCardView } from '../../config/types.js';
import { AdvancedCameraCardError } from '../../types.js';
import { MediaQueriesResults } from '../../view/media-queries-results.js';
import { MediaQueries } from '../../view/media-queries.js';
import { ViewMedia } from '../../view/media.js';
@@ -72,9 +72,9 @@ export interface ViewManagerInterface {
setViewWithMergedContext(context: ViewContext | null): void;
isViewSupportedByCamera(cameraID: string, view: FrigateCardView): boolean;
isViewSupportedByCamera(cameraID: string, view: AdvancedCameraCardView): boolean;
hasMajorMediaChange(oldView?: View | null, newView?: View | null): boolean;
}
export class ViewNoCameraError extends FrigateCardError {}
export class ViewIncompatible extends FrigateCardError {}
export class ViewNoCameraError extends AdvancedCameraCardError {}
export class ViewIncompatible extends AdvancedCameraCardError {}
+8 -5
View File
@@ -1,5 +1,5 @@
import { ViewContext } from 'view';
import { FrigateCardView } from '../../config/types';
import { AdvancedCameraCardView } from '../../config/types';
import { log } from '../../utils/debug';
import { getStreamCameraID } from '../../utils/substream';
import { MediaQueriesClassifier } from '../../view/media-queries-classifier';
@@ -217,7 +217,7 @@ export class ViewManager implements ViewManagerInterface {
// target media of the gallery (e.g. clips, snapshots or recordings) is
// equal to the queries that are currently used in the viewer.
//
// See: https://github.com/dermotduffy/frigate-hass-card/issues/885
// See: https://github.com/dermotduffy/advanced-camera-card/issues/885
const switchingFromViewerToGallery =
this._view?.isViewerView() && newView?.isGalleryView();
@@ -233,7 +233,10 @@ export class ViewManager implements ViewManagerInterface {
}
}
public isViewSupportedByCamera(cameraID: string, view: FrigateCardView): boolean {
public isViewSupportedByCamera(
cameraID: string,
view: AdvancedCameraCardView,
): boolean {
return !!getCameraIDsForViewName(this._api.getCameraManager(), view, cameraID).size;
}
@@ -266,7 +269,7 @@ export class ViewManager implements ViewManagerInterface {
// If the query string contains a view related action, we don't set any view
// here and allow that action to be triggered by the next call of to execute
// query actions (called at least once per render cycle).
// Related: https://github.com/dermotduffy/frigate-hass-card/issues/1200
// Related: https://github.com/dermotduffy/advanced-camera-card/issues/1200
if (!this._api.getQueryStringManager().hasViewRelatedActionsToRun()) {
// This is not awaited to allow the initialization to complete before the
// query is answered.
@@ -280,7 +283,7 @@ export class ViewManager implements ViewManagerInterface {
log(
this._api.getConfigManager().getCardWideConfig(),
`Frigate Card view change: `,
`Advanced Camera Card view change: `,
view,
);
@@ -137,7 +137,7 @@ export class ViewQueryExecutor {
new MergeContextViewModifier({
// Force the window to start at the most recent time, not
// necessarily when the most recent event/recording was:
// https://github.com/dermotduffy/frigate-hass-card/issues/1301
// https://github.com/dermotduffy/advanced-camera-card/issues/1301
timeline: {
window: {
start: sub(now, {
+63 -58
View File
@@ -11,29 +11,29 @@ import { ConditionsEvaluateRequestEvent } from './card-controller/conditions-man
import { CardController } from './card-controller/controller';
import { MenuButtonController } from './components-lib/menu-button-controller';
import './components/elements.js';
import { FrigateCardElements } from './components/elements.js';
import { AdvancedCameraCardElements } from './components/elements.js';
import './components/loading.js';
import './components/menu.js';
import { FrigateCardMenu } from './components/menu.js';
import { AdvancedCameraCardMenu } from './components/menu.js';
import './components/message.js';
import { renderMessage } from './components/message.js';
import './components/overlay.js';
import { FrigateCardOverlay } from './components/overlay.js';
import { AdvancedCameraCardOverlay } from './components/overlay.js';
import './components/status-bar';
import './components/thumbnail-carousel.js';
import './components/views.js';
import { FrigateCardViews } from './components/views.js';
import { AdvancedCameraCardViews } from './components/views.js';
import {
FrigateCardConfig,
AdvancedCameraCardConfig,
MenuItem,
RawFrigateCardConfig,
RawAdvancedCameraCardConfig,
StatusBarItem,
} from './config/types';
import { REPO_URL } from './const.js';
import { localize } from './localize/localize.js';
import cardStyle from './scss/card.scss';
import { ExtendedHomeAssistant, MediaLoadedInfo, Message } from './types.js';
import { frigateCardHasAction } from './utils/action.js';
import { hasAction } from './utils/action.js';
import { getReleaseVersion } from './utils/diagnostics';
// ***************************************************************************
@@ -57,23 +57,14 @@ import { getReleaseVersion } from './utils/diagnostics';
* - Directly specifying hooks (e.g. for snapshot viewing with simple <img> tags)
*/
/** Actions (action/menu/ll-custom events):
*
* The card supports actions being configured in a number of places (e.g. tap on
* an element, double_tap on a menu item, hold on the live view). These actions
* are handled by frigateCardHandleActionConfig(). For Frigate-card specific
* actions, the frigateCardHandleActionConfig() call will result in an ll-custom
* DOM event being fired, which needs to be caught at the card level to handle.
*/
// ***************************************************************************
// Static Initializers
// ***************************************************************************
console.info(
`%c FRIGATE-HASS-CARD \n` + `%c ${localize('common.version')} ` + getReleaseVersion(),
'color: pink; font-weight: bold; background: black',
'color: white; font-weight: bold; background: dimgray',
`%c 📷 Advanced Camera Card %c ${getReleaseVersion()} `,
'padding: 3px; color: black; background: pink;',
'padding: 3px; color: black; background: white;',
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -81,22 +72,22 @@ console.info(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).customCards.push({
type: 'frigate-card',
name: localize('common.frigate_card'),
description: localize('common.frigate_card_description'),
type: 'advanced-camera-card',
name: localize('common.advanced_camera_card'),
description: localize('common.advanced_camera_card_description'),
preview: true,
documentationURL: REPO_URL,
});
// ***************************************************************************
// Main FrigateCard WebComponent
// Main AdvancedCameraCard WebComponent
//
// Any non-rendering / non-lit related functionality should be added to
// CardController instead of this file.
// ***************************************************************************
@customElement('frigate-card')
class FrigateCard extends LitElement {
@customElement('advanced-camera-card')
class AdvancedCameraCard extends LitElement {
protected _controller = new CardController(
this,
// Callback to scroll the main pane back to the top (example usecase: scrolling
@@ -109,14 +100,14 @@ class FrigateCard extends LitElement {
protected _menuButtonController = new MenuButtonController();
protected _refMenu: Ref<FrigateCardMenu> = createRef();
protected _refOverlay: Ref<FrigateCardOverlay> = createRef();
protected _refMenu: Ref<AdvancedCameraCardMenu> = createRef();
protected _refOverlay: Ref<AdvancedCameraCardOverlay> = createRef();
protected _refMain: Ref<HTMLElement> = createRef();
protected _refElements: Ref<FrigateCardElements> = createRef();
protected _refViews: Ref<FrigateCardViews> = createRef();
protected _refElements: Ref<AdvancedCameraCardElements> = createRef();
protected _refViews: Ref<AdvancedCameraCardViews> = createRef();
// Convenience methods for very frequently accessed attributes.
get _config(): FrigateCardConfig | null {
get _config(): AdvancedCameraCardConfig | null {
return this._controller.getConfigManager().getConfig();
}
@@ -145,7 +136,10 @@ class FrigateCard extends LitElement {
return await CardController.getConfigElement();
}
public static getStubConfig(_: HomeAssistant, entities: string[]): FrigateCardConfig {
public static getStubConfig(
_: HomeAssistant,
entities: string[],
): AdvancedCameraCardConfig {
return CardController.getStubConfig(entities);
}
@@ -153,7 +147,7 @@ class FrigateCard extends LitElement {
// Update the components that need to know about condition changes. Trigger
// updates directly on them to them to avoid the performance hit of a entire
// card re-render (esp. when using card-mod).
// https://github.com/dermotduffy/frigate-hass-card/issues/678
// https://github.com/dermotduffy/advanced-camera-card/issues/678
if (this._refViews.value) {
this._refViews.value.conditionsManagerEpoch =
this._controller.getConditionsManager().getEpoch() ?? undefined;
@@ -164,7 +158,7 @@ class FrigateCard extends LitElement {
}
}
public setConfig(config: RawFrigateCardConfig): void {
public setConfig(config: RawAdvancedCameraCardConfig): void {
this._controller.getConfigManager().setConfig(config);
}
@@ -246,7 +240,9 @@ class FrigateCard extends LitElement {
return html`
${position === 'overlay'
? html`<frigate-card-overlay>${getContents('overlay')}</frigate-card-overlay>`
? html`<advanced-camera-card-overlay
>${getContents('overlay')}</advanced-camera-card-overlay
>`
: html`<div class="outerlay" data-position="${position}">
${getContents('outerlay')}
</div>`}
@@ -259,7 +255,7 @@ class FrigateCard extends LitElement {
return;
}
return html`
<frigate-card-menu
<advanced-camera-card-menu
${ref(this._refMenu)}
slot=${ifDefined(slot)}
.hass=${this._hass}
@@ -280,7 +276,7 @@ class FrigateCard extends LitElement {
},
)}
.entityRegistryManager=${this._controller.getEntityRegistryManager()}
></frigate-card-menu>
></advanced-camera-card-menu>
`;
}
@@ -290,7 +286,7 @@ class FrigateCard extends LitElement {
}
return html`
<frigate-card-status-bar
<advanced-camera-card-status-bar
slot=${ifDefined(slot)}
.items=${this._controller.getStatusBarItemManager().calculateItems({
statusConfig: this._config.status_bar,
@@ -299,7 +295,7 @@ class FrigateCard extends LitElement {
mediaLoadedInfo: this._controller.getMediaLoadedInfoManager().get(),
})}
.config=${this._config.status_bar}
></frigate-card-status-bar>
></advanced-camera-card-status-bar>
`;
}
@@ -359,36 +355,36 @@ class FrigateCard extends LitElement {
html` <ha-card
id="ha-card"
.actionHandler=${actionHandler({
hasHold: frigateCardHasAction(actions.hold_action),
hasDoubleClick: frigateCardHasAction(actions.double_tap_action),
hasHold: hasAction(actions.hold_action),
hasDoubleClick: hasAction(actions.double_tap_action),
})}
style="${styleMap(this._controller.getStyleManager().getAspectRatioStyle())}"
@frigate-card:message=${(ev: CustomEvent<Message>) =>
@advanced-camera-card:message=${(ev: CustomEvent<Message>) =>
this._controller.getMessageManager().setMessageIfHigherPriority(ev.detail)}
@frigate-card:media:loaded=${(ev: CustomEvent<MediaLoadedInfo>) =>
@advanced-camera-card:media:loaded=${(ev: CustomEvent<MediaLoadedInfo>) =>
this._controller.getMediaLoadedInfoManager().set(ev.detail)}
@frigate-card:media:unloaded=${() =>
@advanced-camera-card:media:unloaded=${() =>
this._controller.getMediaLoadedInfoManager().clear()}
@frigate-card:media:volumechange=${
@advanced-camera-card:media:volumechange=${
() => this.requestUpdate() /* Refresh mute menu button */
}
@frigate-card:media:play=${
@advanced-camera-card:media:play=${
() => this.requestUpdate() /* Refresh play/pause menu button */
}
@frigate-card:media:pause=${
@advanced-camera-card:media:pause=${
() => this.requestUpdate() /* Refresh play/pause menu button */
}
@frigate-card:focus=${() => this.focus()}
@advanced-camera-card:focus=${() => this.focus()}
>
${showLoading
? html`<frigate-card-loading
? html`<advanced-camera-card-loading
?loaded=${this._controller.getInitializationManager().wasEverInitialized()}
></frigate-card-loading>`
></advanced-camera-card-loading>`
: ''}
${this._renderMenuStatusContainer('top')}
${this._renderMenuStatusContainer('overlay')}
<div ${ref(this._refMain)} class="${classMap(mainClasses)}">
<frigate-card-views
<advanced-camera-card-views
${ref(this._refViews)}
.hass=${this._hass}
.viewManagerEpoch=${this._controller.getViewManager().getEpoch()}
@@ -410,7 +406,7 @@ class FrigateCard extends LitElement {
? this._controller.getTriggersManager().getTriggeredCameraIDs()
: undefined}
.deviceRegistryManager=${this._controller.getDeviceRegistryManager()}
></frigate-card-views>
></advanced-camera-card-views>
${this._controller.getMessageManager().hasMessage()
? // Keep message rendering to last to show messages that may have been
// generated during the render.
@@ -421,32 +417,36 @@ class FrigateCard extends LitElement {
${this._config?.elements
? // Elements need to render after the main views so it can render 'on
// top'.
html` <frigate-card-elements
html` <advanced-camera-card-elements
${ref(this._refElements)}
.hass=${this._hass}
.elements=${this._config?.elements}
.conditionsManagerEpoch=${this._controller
.getConditionsManager()
?.getEpoch()}
@frigate-card:menu:add=${(ev: CustomEvent<MenuItem>) => {
@advanced-camera-card:menu:add=${(ev: CustomEvent<MenuItem>) => {
this._menuButtonController.addDynamicMenuButton(ev.detail);
this.requestUpdate();
}}
@frigate-card:menu:remove=${(ev: CustomEvent<MenuItem>) => {
@advanced-camera-card:menu:remove=${(ev: CustomEvent<MenuItem>) => {
this._menuButtonController.removeDynamicMenuButton(ev.detail);
this.requestUpdate();
}}
@frigate-card:status-bar:add=${(ev: CustomEvent<StatusBarItem>) => {
@advanced-camera-card:status-bar:add=${(
ev: CustomEvent<StatusBarItem>,
) => {
this._controller
.getStatusBarItemManager()
.addDynamicStatusBarItem(ev.detail);
}}
@frigate-card:status-bar:remove=${(ev: CustomEvent<StatusBarItem>) => {
@advanced-camera-card:status-bar:remove=${(
ev: CustomEvent<StatusBarItem>,
) => {
this._controller
.getStatusBarItemManager()
.removeDynamicStatusBarItem(ev.detail);
}}
@frigate-card:conditions:evaluate=${(
@advanced-camera-card:conditions:evaluate=${(
ev: ConditionsEvaluateRequestEvent,
) => {
ev.evaluation = this._controller
@@ -454,7 +454,7 @@ class FrigateCard extends LitElement {
?.evaluateConditions(ev.conditions);
}}
>
</frigate-card-elements>`
</advanced-camera-card-elements>`
: ``}
</ha-card>`,
);
@@ -477,8 +477,13 @@ class FrigateCard extends LitElement {
}
}
// Keep the old name around for backwards compatibility.
@customElement('frigate-card')
class FrigateCard extends AdvancedCameraCard {}
declare global {
interface HTMLElementTagNameMap {
'advanced-camera-card': AdvancedCameraCard;
'frigate-card': FrigateCard;
}
}
+12 -6
View File
@@ -1,10 +1,10 @@
import { LitElement, ReactiveController } from 'lit';
import { MediaLoadedInfo } from '../../types.js';
import {
FrigateCardMediaLoadedEventTarget,
AdvancedCameraCardMediaLoadedEventTarget,
dispatchExistingMediaLoadedInfoAsEvent,
} from '../../utils/media-info.js';
import { FrigateCardMessageEventTarget } from '../message/dispatch.js';
import { AdvancedCameraCardMessageEventTarget } from '../message/dispatch.js';
interface LiveViewContext {
// A cameraID override (used for dependencies/substreams to force a different
@@ -24,8 +24,8 @@ interface LastMediaLoadedInfo {
}
type LiveControllerHost = LitElement &
FrigateCardMediaLoadedEventTarget &
FrigateCardMessageEventTarget;
AdvancedCameraCardMediaLoadedEventTarget &
AdvancedCameraCardMessageEventTarget;
export class LiveController implements ReactiveController {
protected _host: LiveControllerHost;
@@ -56,13 +56,19 @@ export class LiveController implements ReactiveController {
public hostConnected(): void {
this._intersectionObserver.observe(this._host);
this._host.addEventListener('frigate-card:media:loaded', this._handleMediaLoaded);
this._host.addEventListener(
'advanced-camera-card:media:loaded',
this._handleMediaLoaded,
);
}
public hostDisconnected(): void {
this._intersectionObserver.disconnect();
this._host.removeEventListener('frigate-card:media:loaded', this._handleMediaLoaded);
this._host.removeEventListener(
'advanced-camera-card:media:loaded',
this._handleMediaLoaded,
);
}
public isInBackground(): boolean {
@@ -1,5 +1,5 @@
import { dispatchFrigateCardEvent } from '../../../utils/basic';
import { dispatchAdvancedCameraCardEvent } from '../../../utils/basic';
export function dispatchLiveErrorEvent(element: EventTarget): void {
dispatchFrigateCardEvent(element, 'live:error');
dispatchAdvancedCameraCardEvent(element, 'live:error');
}
@@ -5,8 +5,8 @@ import {
AutoPlayCondition,
AutoUnmuteCondition,
} from '../config/types.js';
import { FrigateCardMediaPlayer } from '../types.js';
import { FrigateCardMediaLoadedEventTarget } from '../utils/media-info.js';
import { AdvancedCameraCardMediaPlayer } from '../types.js';
import { AdvancedCameraCardMediaLoadedEventTarget } from '../utils/media-info.js';
import { Timer } from '../utils/timer.js';
export interface MediaActionsControllerOptions {
@@ -21,8 +21,8 @@ export interface MediaActionsControllerOptions {
microphoneMuteSeconds?: number;
}
type RenderRoot = HTMLElement & FrigateCardMediaLoadedEventTarget;
type PlayerElement = HTMLElement & FrigateCardMediaPlayer;
type RenderRoot = HTMLElement & AdvancedCameraCardMediaLoadedEventTarget;
type PlayerElement = HTMLElement & AdvancedCameraCardMediaPlayer;
/**
* General note: Always unmute before playing, since Chrome may pause a piece of
@@ -191,7 +191,7 @@ export class MediaActionsController {
protected _removeChildHandlers(): void {
for (const [child, callback] of this._eventListeners.entries()) {
child.removeEventListener('frigate-card:media:loaded', callback);
child.removeEventListener('advanced-camera-card:media:loaded', callback);
}
this._eventListeners.clear();
}
@@ -223,7 +223,7 @@ export class MediaActionsController {
for (const [index, child] of this._children.entries()) {
const eventListener = () => this._mediaLoadedHandler(index);
this._eventListeners.set(child, eventListener);
child.addEventListener('frigate-card:media:loaded', eventListener);
child.addEventListener('advanced-camera-card:media:loaded', eventListener);
}
}
protected async _intersectionHandler(

Some files were not shown because too many files have changed in this diff Show More