${keyed(
mediaEpoch,
html`
0}
@advanced-camera-card:zoom:change=${(
ev: CustomEvent,
) =>
handleZoomSettingsObservedEvent(
ev,
this.viewManagerEpoch?.manager,
cameraID,
)}
>
`,
)}
`;
}
private _getSubstreamCameraID(cameraID: string, view?: View | null): string {
return view?.context?.live?.overrides?.get(cameraID) ?? cameraID;
}
private _toggleMute(): void {
const controller = this._mediaLoadedInfoSinkController.get()?.mediaPlayerController;
// Fire-and-forget; the `volumechange` event drives the re-render.
if (controller?.isMuted()) {
void controller.unmute();
} else {
void controller?.mute();
}
}
private _getCameraNeighbors(): CameraNeighbors | null {
const cameraIDs = this.cameraManager
? [...this.cameraManager?.getStore().getCameraIDsWithCapability('live')]
: [];
const view = this.viewManagerEpoch?.manager.getView();
if (this.viewFilterCameraID || cameraIDs.length <= 1 || !view || !this.hass) {
return {};
}
const cameraID = this.viewFilterCameraID ?? view.camera;
if (!cameraID) {
return {};
}
const currentIndex = cameraIDs.indexOf(cameraID);
if (currentIndex < 0) {
return {};
}
const prevID = cameraIDs[currentIndex > 0 ? currentIndex - 1 : cameraIDs.length - 1];
const nextID = cameraIDs[currentIndex + 1 < cameraIDs.length ? currentIndex + 1 : 0];
return {
previous: {
id: prevID,
metadata: prevID
? this.cameraManager?.getCameraMetadata(
this._getSubstreamCameraID(prevID, view),
)
: null,
},
next: {
id: nextID,
metadata: nextID
? this.cameraManager?.getCameraMetadata(
this._getSubstreamCameraID(nextID, view),
)
: null,
},
};
}
private _renderNextPrevious(
side: 'left' | 'right',
neighbors: CameraNeighbors | null,
): TemplateResult {
const textDirection = getTextDirection(this);
const neighbor =
(textDirection === 'ltr' && side === 'left') ||
(textDirection === 'rtl' && side === 'right')
? neighbors?.previous
: neighbors?.next;
return html`