Render the JSMPEG spinner until the last possible moment.
This commit is contained in:
+1
-1
@@ -22,7 +22,7 @@
|
||||
"@material/rtl": "^13.0.0",
|
||||
"custom-card-helpers": "^1.8.0",
|
||||
"dayjs": "^1.10.7",
|
||||
"embla-carousel": "^5.0.1",
|
||||
"embla-carousel": "^6.1.0",
|
||||
"home-assistant-js-websocket": "^5.11.1",
|
||||
"lit": "^2.0.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
|
||||
+37
-38
@@ -754,46 +754,46 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
||||
|
||||
/**
|
||||
* Create a JSMPEG player.
|
||||
* @param url The URL for the player to connect to.
|
||||
* @returns A JSMPEG player.
|
||||
*/
|
||||
protected _createJSMPEGPlayer(url: string): JSMpeg.VideoElement {
|
||||
let videoDecoded = false;
|
||||
|
||||
const jsmpegOptions = {
|
||||
pauseWhenHidden: false,
|
||||
protocols: [],
|
||||
audio: false,
|
||||
videoBufferSize: 1024 * 1024 * 4,
|
||||
onVideoDecode: () => {
|
||||
// This is the only callback that is called after the dimensions
|
||||
// are available. It's called on every frame decode, so just
|
||||
// ignore any subsequent calls.
|
||||
if (!videoDecoded && this._jsmpegCanvasElement) {
|
||||
videoDecoded = true;
|
||||
dispatchMediaShowEvent(this, this._jsmpegCanvasElement);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Override with user-specified options.
|
||||
Object.assign(jsmpegOptions, this.jsmpegConfig?.options);
|
||||
|
||||
return new JSMpeg.VideoElement(
|
||||
this,
|
||||
url,
|
||||
{
|
||||
canvas: this._jsmpegCanvasElement,
|
||||
hooks: {
|
||||
play: () => {
|
||||
dispatchPlayEvent(this);
|
||||
},
|
||||
pause: () => {
|
||||
dispatchPauseEvent(this);
|
||||
protected async _createJSMPEGPlayer(url: string): Promise<JSMpeg.VideoElement> {
|
||||
return new Promise<JSMpeg.VideoElement>((resolve) => {
|
||||
let videoDecoded = false;
|
||||
const player = new JSMpeg.VideoElement(
|
||||
this,
|
||||
url,
|
||||
{
|
||||
canvas: this._jsmpegCanvasElement,
|
||||
hooks: {
|
||||
play: () => {
|
||||
dispatchPlayEvent(this);
|
||||
},
|
||||
pause: () => {
|
||||
dispatchPauseEvent(this);
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
jsmpegOptions,
|
||||
);
|
||||
{
|
||||
pauseWhenHidden: false,
|
||||
protocols: [],
|
||||
audio: false,
|
||||
videoBufferSize: 1024 * 1024 * 4,
|
||||
// Override with user-specified options.
|
||||
...this.jsmpegConfig?.options,
|
||||
onVideoDecode: () => {
|
||||
// This is the only callback that is called after the dimensions
|
||||
// are available. It's called on every frame decode, so just
|
||||
// ignore any subsequent calls.
|
||||
if (!videoDecoded && this._jsmpegCanvasElement) {
|
||||
videoDecoded = true;
|
||||
dispatchMediaShowEvent(this, this._jsmpegCanvasElement);
|
||||
resolve(player);
|
||||
}
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -856,8 +856,7 @@ export class FrigateCardLiveJSMPEG extends LitElement {
|
||||
|
||||
const url = await this._getURL();
|
||||
if (url) {
|
||||
this._jsmpegVideoPlayer = this._createJSMPEGPlayer(url);
|
||||
|
||||
this._jsmpegVideoPlayer = await this._createJSMPEGPlayer(url);
|
||||
this._refreshPlayerTimerID = window.setTimeout(() => {
|
||||
this.requestUpdate();
|
||||
}, (URL_SIGN_EXPIRY_SECONDS - URL_SIGN_REFRESH_THRESHOLD_SECONDS) * 1000);
|
||||
|
||||
@@ -110,7 +110,7 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
|
||||
if (!this._carousel) {
|
||||
return;
|
||||
}
|
||||
this._carousel.containerNode().style.removeProperty('max-height')
|
||||
this._carousel.containerNode().style.removeProperty('max-height');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,20 +119,24 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
|
||||
* different aspect ratios).
|
||||
*/
|
||||
protected _adaptiveHeightSetHandler(): void {
|
||||
if (!this._carousel) {
|
||||
return;
|
||||
}
|
||||
const slides = this._carousel.slideNodes();
|
||||
const heights = this._carousel.slidesInView(true).map((index) => {
|
||||
const firstChild = slides[index].querySelector("*");
|
||||
return firstChild ? firstChild.getBoundingClientRect().height : 0;
|
||||
})
|
||||
const targetHeight = Math.max(...heights);
|
||||
if (targetHeight > 0) {
|
||||
this._carousel.containerNode().style.maxHeight = `${targetHeight}px`;
|
||||
} else {
|
||||
this._carousel.containerNode().style.removeProperty('max-height')
|
||||
}
|
||||
// Don't gather slide heights until the next browser re-paint to ensure the
|
||||
// measured heights are correct on the media that has (potentially) just
|
||||
// loaded.
|
||||
window.requestAnimationFrame(() => {
|
||||
if (!this._carousel) {
|
||||
return;
|
||||
}
|
||||
const slides = this._carousel.slideNodes();
|
||||
const heights = this._carousel.slidesInView(true).map((index) => {
|
||||
return slides[index].getBoundingClientRect().height;
|
||||
});
|
||||
const targetHeight = Math.max(...heights);
|
||||
if (targetHeight > 0) {
|
||||
this._carousel.containerNode().style.maxHeight = `${targetHeight}px`;
|
||||
} else {
|
||||
this._carousel.containerNode().style.removeProperty('max-height');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
--video-max-height: none;
|
||||
}
|
||||
|
||||
|
||||
.embla__container {
|
||||
// To support adaptive height animations.
|
||||
transition: max-height 0.5s ease;
|
||||
}
|
||||
|
||||
.embla__slide {
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
Reference in New Issue
Block a user