137 lines
4.6 KiB
TypeScript
137 lines
4.6 KiB
TypeScript
import {
|
|
html,
|
|
LitElement,
|
|
unsafeCSS,
|
|
type CSSResultGroup,
|
|
type PropertyValues,
|
|
type TemplateResult,
|
|
} from 'lit';
|
|
import { customElement, property } from 'lit/decorators.js';
|
|
|
|
import type { CameraManager } from '../../camera-manager/manager.js';
|
|
import type { CallSession } from '../../card-controller/call/types.js';
|
|
import type { StateWatcherSubscriptionInterface } from '../../card-controller/hass/state-watcher.js';
|
|
import type { MicrophoneManager } from '../../card-controller/microphone-manager.js';
|
|
import type { MicrophoneState } from '../../card-controller/types.js';
|
|
import type { ViewManagerEpoch } from '../../card-controller/view/types.js';
|
|
import { MicrophoneActionsController } from '../../components-lib/live/microphone-actions-controller.js';
|
|
|
|
import '../../components-lib/live/types.js';
|
|
|
|
import type { LiveConfig } from '../../config/schema/live.js';
|
|
import type { CardWideConfig } from '../../config/schema/types.js';
|
|
import type { HomeAssistant } from '../../ha/types.js';
|
|
import basicBlockStyle from '../../scss/basic-block.scss';
|
|
import { contentsChanged } from '../../utils/basic.js';
|
|
|
|
import './grid.js';
|
|
|
|
@customElement('advanced-camera-card-live')
|
|
export class AdvancedCameraCardLive extends LitElement {
|
|
@property({ attribute: false })
|
|
public hass?: HomeAssistant;
|
|
|
|
@property({ attribute: false })
|
|
public stateWatcher?: StateWatcherSubscriptionInterface;
|
|
|
|
@property({ attribute: false })
|
|
public viewManagerEpoch?: ViewManagerEpoch;
|
|
|
|
@property({ attribute: false })
|
|
public liveConfig?: LiveConfig;
|
|
|
|
@property({ attribute: false })
|
|
public cameraManager?: CameraManager;
|
|
|
|
@property({ attribute: false })
|
|
public cardWideConfig?: CardWideConfig;
|
|
|
|
@property({ attribute: false })
|
|
public microphoneManager?: MicrophoneManager;
|
|
|
|
@property({ attribute: false })
|
|
public microphoneState?: MicrophoneState;
|
|
|
|
@property({ attribute: false })
|
|
public call?: CallSession;
|
|
|
|
@property({ attribute: false })
|
|
public locked?: boolean;
|
|
|
|
@property({ attribute: false, hasChanged: contentsChanged })
|
|
public triggeredCameraIDs?: Set<string>;
|
|
|
|
private _microphoneActionsController = new MicrophoneActionsController();
|
|
|
|
public connectedCallback(): void {
|
|
super.connectedCallback();
|
|
this._microphoneActionsController.setRoot(this);
|
|
}
|
|
|
|
public disconnectedCallback(): void {
|
|
this._microphoneActionsController.destroy();
|
|
super.disconnectedCallback();
|
|
}
|
|
|
|
protected willUpdate(changedProps: PropertyValues): void {
|
|
if (changedProps.has('liveConfig') || changedProps.has('microphoneManager')) {
|
|
this._microphoneActionsController.setOptions({
|
|
microphoneManager: this.microphoneManager,
|
|
autoMuteConditions: this.liveConfig?.microphone.auto_mute,
|
|
autoUnmuteConditions: this.liveConfig?.microphone.auto_unmute,
|
|
});
|
|
}
|
|
if (changedProps.has('viewManagerEpoch')) {
|
|
// The live element is also rendered (and this willUpdate runs) when
|
|
// `live.preload` is true even while the user is on gallery/viewer/
|
|
// timeline. `view.camera` is set across all views, so without this gate
|
|
// `auto_unmute: ['selected']` would prompt for / open the microphone
|
|
// from a hidden live view. Treat the live view as having no selected
|
|
// camera unless it is the active view.
|
|
const view = this.viewManagerEpoch?.manager.getView();
|
|
void this._microphoneActionsController.setSelectedCamera(
|
|
view?.is('live') ? view.camera ?? null : null,
|
|
);
|
|
}
|
|
if (changedProps.has('call')) {
|
|
// Gate on `answered`, not mere presence, so `microphone.auto_unmute:
|
|
// ['call']` doesn't transmit audio during the pre-answer ringing state.
|
|
// Outbound calls are answered at construction; inbound calls only after
|
|
// the user accepts.
|
|
this._microphoneActionsController.setCallAnswered(!!this.call?.answered);
|
|
}
|
|
}
|
|
|
|
protected render(): TemplateResult | void {
|
|
if (!this.hass || !this.cameraManager) {
|
|
return;
|
|
}
|
|
|
|
return html`
|
|
<advanced-camera-card-live-grid
|
|
.hass=${this.hass}
|
|
.stateWatcher=${this.stateWatcher}
|
|
.viewManagerEpoch=${this.viewManagerEpoch}
|
|
.liveConfig=${this.liveConfig}
|
|
.cardWideConfig=${this.cardWideConfig}
|
|
.cameraManager=${this.cameraManager}
|
|
.microphoneState=${this.microphoneState}
|
|
.call=${this.call}
|
|
.locked=${this.locked}
|
|
.triggeredCameraIDs=${this.triggeredCameraIDs}
|
|
>
|
|
</advanced-camera-card-live-grid>
|
|
`;
|
|
}
|
|
|
|
static get styles(): CSSResultGroup {
|
|
return unsafeCSS(basicBlockStyle);
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'advanced-camera-card-live': AdvancedCameraCardLive;
|
|
}
|
|
}
|