refactor: Unify substream actions into substream_{on,off} (#2497)
## Summary
- Collapse `live_substream_{on,off,select}` into a unified
`substream_{on,off}` pair, symmetric with `call_{start,end}`.
- Rename the `camera` field on the former `live_substream_select` to
`stream` (it always was a stream ID).
- Add optional `camera` field to both new actions for targeting a
non-selected base camera.
- YAML configs are migrated automatically; URL bookmarks must be updated
by hand.
## Migration
### Cycling between camera and substream (toggle button)
Before:
```yaml
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_on
```
After:
```yaml
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: substream_on
```
### Selecting a specific substream
Before:
```yaml
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_select
camera: camera.front_door_hd
```
After:
```yaml
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: substream_on
stream: camera.front_door_hd
```
### Turning the substream off
Before:
```yaml
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: live_substream_off
```
After:
```yaml
tap_action:
action: custom:advanced-camera-card-action
advanced_camera_card_action: substream_off
```
### URL querystrings (manual update required)
| Before | After |
| --- | --- |
|
`?advanced-camera-card-action.live_substream_select=camera.front_door_hd`
| `?advanced-camera-card-action.substream_on=camera.front_door_hd` |
This commit is contained in:
committed by
dermotduffy
parent
15e335a647
commit
f18e4cd4b8
@@ -1,30 +1,38 @@
|
||||
import { View } from '../../../view/view';
|
||||
import { ViewModifier } from '../types';
|
||||
|
||||
// The single write path for the camera-keyed `live.overrides` map (the read
|
||||
// path being `getStreamCameraID` in `view/substream`): sets a camera's
|
||||
// substream override, or clears it when `substreamID` is absent so the
|
||||
// camera's own stream is used. `cameraID` defaults to the selected camera.
|
||||
export class SubstreamViewModifier implements ViewModifier {
|
||||
private _substreamID?: string;
|
||||
private _cameraID?: string;
|
||||
interface SubstreamViewModifierOptions {
|
||||
// The substream to engage. When absent, the override is cleared so the
|
||||
// camera's own stream is used.
|
||||
stream?: string;
|
||||
|
||||
constructor(substreamID?: string, cameraID?: string) {
|
||||
this._substreamID = substreamID;
|
||||
this._cameraID = cameraID;
|
||||
// The camera whose override to write. Defaults to the selected camera.
|
||||
camera?: string;
|
||||
}
|
||||
|
||||
// The single write path for the camera-keyed `live.overrides` map (the read
|
||||
// path being `getStreamCameraID` in `view/substream`).
|
||||
export class SubstreamViewModifier implements ViewModifier {
|
||||
private _options: SubstreamViewModifierOptions;
|
||||
|
||||
constructor(options?: SubstreamViewModifierOptions) {
|
||||
this._options = options ?? {};
|
||||
}
|
||||
|
||||
public modify(view: View): void {
|
||||
const cameraID = this._cameraID ?? view.camera;
|
||||
const cameraID = this._options.camera ?? view.camera;
|
||||
if (!cameraID) {
|
||||
return;
|
||||
}
|
||||
if (!this._substreamID) {
|
||||
// A stream equal to the camera itself is semantically "no substream";
|
||||
// normalise it to a cleared override so the map doesn't carry self-
|
||||
// referential entries.
|
||||
if (!this._options.stream || this._options.stream === cameraID) {
|
||||
view.context?.live?.overrides?.delete(cameraID);
|
||||
return;
|
||||
}
|
||||
const overrides = view.context?.live?.overrides ?? new Map<string, string>();
|
||||
overrides.set(cameraID, this._substreamID);
|
||||
overrides.set(cameraID, this._options.stream);
|
||||
view.mergeInContext({ live: { overrides } });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user