+30
-54
@@ -1,17 +1,9 @@
|
||||
import {
|
||||
CSSResultGroup,
|
||||
html,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
unsafeCSS,
|
||||
} from 'lit';
|
||||
import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { guard } from 'lit/directives/guard.js';
|
||||
import { createRef, ref, Ref } from 'lit/directives/ref.js';
|
||||
import { CameraManager } from '../camera-manager/manager';
|
||||
import { ViewManagerEpoch } from '../card-controller/view/types';
|
||||
import { MediaProviderDimensionsController } from '../components-lib/media-provider-dimensions-controller';
|
||||
import { ZoomSettingsObserved } from '../components-lib/zoom/types';
|
||||
import { handleZoomSettingsObservedEvent } from '../components-lib/zoom/zoom-view-context';
|
||||
import { CameraConfig } from '../config/schema/cameras';
|
||||
@@ -22,6 +14,7 @@ import imageStyle from '../scss/image.scss';
|
||||
import { MediaPlayer, MediaPlayerController, MediaPlayerElement } from '../types.js';
|
||||
import './image-updating-player';
|
||||
import { resolveImageMode } from './image-updating-player';
|
||||
import './media-dimensions-container';
|
||||
import './zoomer.js';
|
||||
|
||||
@customElement('advanced-camera-card-image')
|
||||
@@ -41,28 +34,13 @@ export class AdvancedCameraCardImage extends LitElement implements MediaPlayer {
|
||||
@property({ attribute: false })
|
||||
public imageConfig?: ImageViewConfig;
|
||||
|
||||
protected _dimensionsController = new MediaProviderDimensionsController(this);
|
||||
protected _refImage: Ref<MediaPlayerElement> = createRef();
|
||||
protected _refContainer: Ref<HTMLElement> = createRef();
|
||||
|
||||
public async getMediaPlayerController(): Promise<MediaPlayerController | null> {
|
||||
await this.updateComplete;
|
||||
return (await this._refImage.value?.getMediaPlayerController()) ?? null;
|
||||
}
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
if (changedProps.has('cameraConfig') || changedProps.has('imageConfig')) {
|
||||
this._dimensionsController.setCameraConfig(
|
||||
resolveImageMode({
|
||||
imageConfig: this.imageConfig,
|
||||
cameraConfig: this.cameraConfig,
|
||||
}) === 'camera'
|
||||
? this.cameraConfig?.dimensions
|
||||
: undefined,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected _renderContainer(template: TemplateResult): TemplateResult {
|
||||
const zoomTarget = IMAGE_VIEW_ZOOM_TARGET_SENTINEL;
|
||||
const view = this.viewManagerEpoch?.manager.getView();
|
||||
@@ -71,33 +49,35 @@ export class AdvancedCameraCardImage extends LitElement implements MediaPlayer {
|
||||
cameraConfig: this.cameraConfig,
|
||||
});
|
||||
|
||||
return html`<div class="container" ${ref(this._refContainer)}>
|
||||
${this.imageConfig?.zoomable
|
||||
? html`<advanced-camera-card-zoomer
|
||||
.defaultSettings=${guard(
|
||||
[this.imageConfig, this.cameraConfig?.dimensions?.layout],
|
||||
() =>
|
||||
mode === 'camera' && this.cameraConfig?.dimensions?.layout
|
||||
? {
|
||||
pan: this.cameraConfig.dimensions.layout.pan,
|
||||
zoom: this.cameraConfig.dimensions.layout.zoom,
|
||||
}
|
||||
: undefined,
|
||||
const intermediateTemplate = html` <advanced-camera-card-media-dimensions-container
|
||||
.dimensionsConfig=${mode === 'camera' ? this.cameraConfig?.dimensions : undefined}
|
||||
>
|
||||
${template}
|
||||
</advanced-camera-card-media-dimensions-container>`;
|
||||
|
||||
return html` ${this.imageConfig?.zoomable
|
||||
? html`<advanced-camera-card-zoomer
|
||||
.defaultSettings=${guard(
|
||||
[this.imageConfig, this.cameraConfig?.dimensions?.layout],
|
||||
() =>
|
||||
mode === 'camera' && this.cameraConfig?.dimensions?.layout
|
||||
? {
|
||||
pan: this.cameraConfig.dimensions.layout.pan,
|
||||
zoom: this.cameraConfig.dimensions.layout.zoom,
|
||||
}
|
||||
: undefined,
|
||||
)}
|
||||
.settings=${view?.context?.zoom?.[zoomTarget]?.requested}
|
||||
@advanced-camera-card:zoom:change=${(ev: CustomEvent<ZoomSettingsObserved>) =>
|
||||
handleZoomSettingsObservedEvent(
|
||||
ev,
|
||||
this.viewManagerEpoch?.manager,
|
||||
zoomTarget,
|
||||
)}
|
||||
.settings=${view?.context?.zoom?.[zoomTarget]?.requested}
|
||||
@advanced-camera-card:zoom:change=${(
|
||||
ev: CustomEvent<ZoomSettingsObserved>,
|
||||
) =>
|
||||
handleZoomSettingsObservedEvent(
|
||||
ev,
|
||||
this.viewManagerEpoch?.manager,
|
||||
zoomTarget,
|
||||
)}
|
||||
>
|
||||
${template}
|
||||
</advanced-camera-card-zoomer>`
|
||||
: template}
|
||||
</div>`;
|
||||
>
|
||||
${intermediateTemplate}
|
||||
</advanced-camera-card-zoomer>`
|
||||
: intermediateTemplate}`;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
@@ -117,10 +97,6 @@ export class AdvancedCameraCardImage extends LitElement implements MediaPlayer {
|
||||
`);
|
||||
}
|
||||
|
||||
public updated(): void {
|
||||
this._dimensionsController.setContainer(this._refContainer.value);
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return unsafeCSS(imageStyle);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import { CameraEndpoints } from '../../camera-manager/types.js';
|
||||
import { MicrophoneState } from '../../card-controller/types.js';
|
||||
import { LazyLoadController } from '../../components-lib/lazy-load-controller.js';
|
||||
import { dispatchLiveErrorEvent } from '../../components-lib/live/utils/dispatch-live-error.js';
|
||||
import { MediaProviderDimensionsController } from '../../components-lib/media-provider-dimensions-controller.js';
|
||||
import { PartialZoomSettings } from '../../components-lib/zoom/types.js';
|
||||
import { CameraConfig, LiveProvider } from '../../config/schema/cameras.js';
|
||||
import { LiveConfig } from '../../config/schema/live.js';
|
||||
@@ -32,6 +31,7 @@ import {
|
||||
import { dispatchMediaUnloadedEvent } from '../../utils/media-info.js';
|
||||
import '../icon.js';
|
||||
import { renderMessage } from '../message.js';
|
||||
import './../media-dimensions-container';
|
||||
|
||||
@customElement('advanced-camera-card-live-provider')
|
||||
export class AdvancedCameraCardLiveProvider extends LitElement implements MediaPlayer {
|
||||
@@ -70,9 +70,8 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
protected _showStreamTroubleshooting = false;
|
||||
|
||||
protected _refProvider: Ref<MediaPlayerElement> = createRef();
|
||||
protected _refContainer: Ref<HTMLElement> = createRef();
|
||||
|
||||
protected _lazyLoadController: LazyLoadController = new LazyLoadController(this);
|
||||
protected _dimensionsController = new MediaProviderDimensionsController(this);
|
||||
|
||||
// A note on dynamic imports:
|
||||
//
|
||||
@@ -82,8 +81,8 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
// underlying code is not yet loaded.
|
||||
//
|
||||
// Test case: A card with a non-live view, but live pre-loaded, attempts to
|
||||
// call mute() when the <advanced-camera-card-live> element first renders in the
|
||||
// background. These calls fail without waiting for loading here.
|
||||
// call mute() when the <advanced-camera-card-live> element first renders in
|
||||
// the background. These calls fail without waiting for loading here.
|
||||
protected _importPromises: Promise<unknown>[] = [];
|
||||
|
||||
constructor() {
|
||||
@@ -186,8 +185,6 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
} else if (provider === 'go2rtc') {
|
||||
this._importPromises.push(import('./providers/go2rtc/index.js'));
|
||||
}
|
||||
|
||||
this._dimensionsController.setCameraConfig(this.cameraConfig?.dimensions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,29 +198,38 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
}
|
||||
|
||||
protected _renderContainer(template: TemplateResult): TemplateResult {
|
||||
// Place the zoomer in a separate div, as the zoom library misinterprets the
|
||||
// explicit width/height setting from the provider resizer as zooming.
|
||||
return html`<div class="container" ${ref(this._refContainer)}>
|
||||
${this.liveConfig?.zoomable
|
||||
? html` <advanced-camera-card-zoomer
|
||||
.defaultSettings=${guard([this.cameraConfig?.dimensions?.layout], () =>
|
||||
this.cameraConfig?.dimensions?.layout
|
||||
? {
|
||||
pan: this.cameraConfig.dimensions.layout.pan,
|
||||
zoom: this.cameraConfig.dimensions.layout.zoom,
|
||||
}
|
||||
: undefined,
|
||||
)}
|
||||
.settings=${this.zoomSettings}
|
||||
@advanced-camera-card:zoom:zoomed=${async () =>
|
||||
(await this.getMediaPlayerController())?.setControls(false)}
|
||||
@advanced-camera-card:zoom:unzoomed=${async () =>
|
||||
(await this.getMediaPlayerController())?.setControls()}
|
||||
>
|
||||
${template}
|
||||
</advanced-camera-card-zoomer>`
|
||||
: template}
|
||||
</div>`;
|
||||
const intermediateTemplate = html` <advanced-camera-card-media-dimensions-container
|
||||
.dimensionsConfig=${this.cameraConfig?.dimensions}
|
||||
@advanced-camera-card:media:loaded=${(ev: CustomEvent<MediaLoadedInfo>) => {
|
||||
if (ev.detail.placeholder) {
|
||||
ev.stopPropagation();
|
||||
} else {
|
||||
this._videoMediaShowHandler();
|
||||
}
|
||||
}}
|
||||
>
|
||||
${template}
|
||||
</advanced-camera-card-media-dimensions-container>`;
|
||||
|
||||
return html` ${this.liveConfig?.zoomable
|
||||
? html` <advanced-camera-card-zoomer
|
||||
.defaultSettings=${guard([this.cameraConfig?.dimensions?.layout], () =>
|
||||
this.cameraConfig?.dimensions?.layout
|
||||
? {
|
||||
pan: this.cameraConfig.dimensions.layout.pan,
|
||||
zoom: this.cameraConfig.dimensions.layout.zoom,
|
||||
}
|
||||
: undefined,
|
||||
)}
|
||||
.settings=${this.zoomSettings}
|
||||
@advanced-camera-card:zoom:zoomed=${async () =>
|
||||
(await this.getMediaPlayerController())?.setControls(false)}
|
||||
@advanced-camera-card:zoom:unzoomed=${async () =>
|
||||
(await this.getMediaPlayerController())?.setControls()}
|
||||
>
|
||||
${intermediateTemplate}
|
||||
</advanced-camera-card-zoomer>`
|
||||
: intermediateTemplate}`;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
@@ -304,17 +310,7 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
})}
|
||||
@advanced-camera-card:live:error=${() => this._providerErrorHandler()}
|
||||
@advanced-camera-card:media:loaded=${(ev: CustomEvent<MediaLoadedInfo>) => {
|
||||
if (provider === 'image') {
|
||||
// Only count the media has loaded if the required provider is
|
||||
// the image (not just the temporary image shown during
|
||||
// loading).
|
||||
this._videoMediaShowHandler();
|
||||
} else {
|
||||
// Manually call resize(), since the dimensions controller won't
|
||||
// receive the after that stopPropagation().
|
||||
this._dimensionsController.resize();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
ev.detail.placeholder = provider !== 'image';
|
||||
}}
|
||||
>
|
||||
</advanced-camera-card-live-image>`
|
||||
@@ -327,7 +323,6 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
.cameraConfig=${this.cameraConfig}
|
||||
?controls=${this.liveConfig.controls.builtin}
|
||||
@advanced-camera-card:live:error=${() => this._providerErrorHandler()}
|
||||
@advanced-camera-card:media:loaded=${this._videoMediaShowHandler.bind(this)}
|
||||
>
|
||||
</advanced-camera-card-live-ha>`
|
||||
: provider === 'go2rtc'
|
||||
@@ -341,9 +336,6 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
.microphoneConfig=${this.liveConfig.microphone}
|
||||
?controls=${this.liveConfig.controls.builtin}
|
||||
@advanced-camera-card:live:error=${() => this._providerErrorHandler()}
|
||||
@advanced-camera-card:media:loaded=${this._videoMediaShowHandler.bind(
|
||||
this,
|
||||
)}
|
||||
>
|
||||
</advanced-camera-card-live-go2rtc>`
|
||||
: provider === 'webrtc-card'
|
||||
@@ -356,9 +348,6 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
.cardWideConfig=${this.cardWideConfig}
|
||||
?controls=${this.liveConfig.controls.builtin}
|
||||
@advanced-camera-card:live:error=${() => this._providerErrorHandler()}
|
||||
@advanced-camera-card:media:loaded=${this._videoMediaShowHandler.bind(
|
||||
this,
|
||||
)}
|
||||
>
|
||||
</advanced-camera-card-live-webrtc-card>`
|
||||
: provider === 'jsmpeg'
|
||||
@@ -370,9 +359,6 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
.cameraEndpoints=${this.cameraEndpoints}
|
||||
.cardWideConfig=${this.cardWideConfig}
|
||||
@advanced-camera-card:live:error=${() => this._providerErrorHandler()}
|
||||
@advanced-camera-card:media:loaded=${this._videoMediaShowHandler.bind(
|
||||
this,
|
||||
)}
|
||||
>
|
||||
</advanced-camera-card-live-jsmpeg>`
|
||||
: html``}
|
||||
@@ -402,10 +388,6 @@ export class AdvancedCameraCardLiveProvider extends LitElement implements MediaP
|
||||
: ''}`;
|
||||
}
|
||||
|
||||
public updated(): void {
|
||||
this._dimensionsController.setContainer(this._refContainer.value);
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return unsafeCSS(liveProviderStyle);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import {
|
||||
CSSResultGroup,
|
||||
html,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
unsafeCSS,
|
||||
} from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { createRef, ref, Ref } from 'lit/directives/ref.js';
|
||||
import { MediaDimensionsContainerController } from '../components-lib/media-dimensions-container-controller.js';
|
||||
import { CameraDimensionsConfig } from '../config/schema/cameras';
|
||||
import mediaDimensionsContainerStyle from '../scss/media-dimensions-container.scss';
|
||||
|
||||
@customElement('advanced-camera-card-media-dimensions-container')
|
||||
export class AdvancedCameraCardMediaDimensionsContainer extends LitElement {
|
||||
@property({ attribute: false })
|
||||
public dimensionsConfig?: CameraDimensionsConfig;
|
||||
|
||||
protected _controller = new MediaDimensionsContainerController(this);
|
||||
|
||||
protected _refInnerContainer: Ref<HTMLElement> = createRef();
|
||||
protected _refOuterContainer: Ref<HTMLElement> = createRef();
|
||||
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
if (changedProps.has('dimensionsConfig')) {
|
||||
this._controller.setConfig(this.dimensionsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
return html`
|
||||
<div class="outer" ${ref(this._refOuterContainer)}>
|
||||
<div class="inner" ${ref(this._refInnerContainer)}>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return unsafeCSS(mediaDimensionsContainerStyle);
|
||||
}
|
||||
|
||||
public updated(): void {
|
||||
this._controller.setContainers(
|
||||
this._refInnerContainer.value,
|
||||
this._refOuterContainer.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'advanced-camera-card-media-dimensions-container': AdvancedCameraCardMediaDimensionsContainer;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
||||
import { CameraManager } from '../../camera-manager/manager.js';
|
||||
import { ViewManagerEpoch } from '../../card-controller/view/types.js';
|
||||
import { LazyLoadController } from '../../components-lib/lazy-load-controller.js';
|
||||
import { MediaProviderDimensionsController } from '../../components-lib/media-provider-dimensions-controller.js';
|
||||
import { ZoomSettingsObserved } from '../../components-lib/zoom/types.js';
|
||||
import { handleZoomSettingsObservedEvent } from '../../components-lib/zoom/zoom-view-context.js';
|
||||
import { CameraConfig } from '../../config/schema/cameras.js';
|
||||
@@ -38,6 +37,7 @@ import { QueryClassifier } from '../../view/query-classifier.js';
|
||||
import '../image-player.js';
|
||||
import { renderProgressIndicator } from '../progress-indicator.js';
|
||||
import '../video-player.js';
|
||||
import './../media-dimensions-container';
|
||||
|
||||
@customElement('advanced-camera-card-viewer-provider')
|
||||
export class AdvancedCameraCardViewerProvider extends LitElement implements MediaPlayer {
|
||||
@@ -65,7 +65,6 @@ export class AdvancedCameraCardViewerProvider extends LitElement implements Medi
|
||||
protected _refProvider: Ref<MediaPlayerElement> = createRef();
|
||||
protected _refContainer: Ref<HTMLElement> = createRef();
|
||||
protected _lazyLoadController: LazyLoadController = new LazyLoadController(this);
|
||||
protected _dimensionsController = new MediaProviderDimensionsController(this);
|
||||
|
||||
@state()
|
||||
protected _url: string | null = null;
|
||||
@@ -201,12 +200,6 @@ export class AdvancedCameraCardViewerProvider extends LitElement implements Medi
|
||||
if (changedProps.has('viewerConfig') && this.viewerConfig?.zoomable) {
|
||||
import('../zoomer.js');
|
||||
}
|
||||
|
||||
if (changedProps.has('media') || changedProps.has('cameraManager')) {
|
||||
this._dimensionsController.setCameraConfig(
|
||||
this._getRelevantCameraConfig()?.dimensions,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private _getRelevantCameraConfig(): CameraConfig | null {
|
||||
@@ -227,9 +220,13 @@ export class AdvancedCameraCardViewerProvider extends LitElement implements Medi
|
||||
: null;
|
||||
const view = this.viewManagerEpoch?.manager.getView();
|
||||
|
||||
// Place the zoomer in a separate div, as the zoom library misinterprets the
|
||||
// explicit width/height setting from the provider resizer as zooming.
|
||||
return html`<div class="container" ${ref(this._refContainer)}>
|
||||
const intermediateTemplate = html` <advanced-camera-card-media-dimensions-container
|
||||
.dimensionsConfig=${this._getRelevantCameraConfig()?.dimensions}
|
||||
>
|
||||
${template}
|
||||
</advanced-camera-card-media-dimensions-container>`;
|
||||
|
||||
return html`
|
||||
${this.viewerConfig?.zoomable
|
||||
? html`<advanced-camera-card-zoomer
|
||||
.defaultSettings=${guard([cameraConfig?.dimensions?.layout], () =>
|
||||
@@ -254,10 +251,10 @@ export class AdvancedCameraCardViewerProvider extends LitElement implements Medi
|
||||
mediaID,
|
||||
)}
|
||||
>
|
||||
${template}
|
||||
${intermediateTemplate}
|
||||
</advanced-camera-card-zoomer>`
|
||||
: template}
|
||||
</div>`;
|
||||
: intermediateTemplate}
|
||||
`;
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
@@ -319,10 +316,6 @@ export class AdvancedCameraCardViewerProvider extends LitElement implements Medi
|
||||
`);
|
||||
}
|
||||
|
||||
public updated(): void {
|
||||
this._dimensionsController.setContainer(this._refContainer.value);
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return unsafeCSS(viewerProviderStyle);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user