Fix malformed Safari live carousel.

This commit is contained in:
Dermot Duffy
2022-05-15 08:37:19 -07:00
parent ad29c3e384
commit b10a5e6b45
3 changed files with 18 additions and 44 deletions
+6 -8
View File
@@ -72,7 +72,7 @@ export class FrigateCardLive extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
protected liveConfig?: LiveConfig; protected liveConfig?: LiveConfig;
@property({ attribute: false }) @property({ attribute: false, hasChanged: contentsChanged })
protected liveOverrides?: LiveOverrides; protected liveOverrides?: LiveOverrides;
@property({ attribute: false }) @property({ attribute: false })
@@ -191,7 +191,7 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
@property({ attribute: false }) @property({ attribute: false })
protected liveConfig?: LiveConfig; protected liveConfig?: LiveConfig;
@property({ attribute: false }) @property({ attribute: false, hasChanged: contentsChanged })
protected liveOverrides?: LiveOverrides; protected liveOverrides?: LiveOverrides;
@property({ attribute: false }) @property({ attribute: false })
@@ -275,13 +275,11 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
* @returns An EmblaOptionsType object or undefined for no options. * @returns An EmblaOptionsType object or undefined for no options.
*/ */
protected _getOptions(): EmblaOptionsType { protected _getOptions(): EmblaOptionsType {
let startIndex = -1;
if (this.cameras && this.view) {
startIndex = Array.from(this.cameras.keys()).indexOf(this.view.camera);
}
return { return {
startIndex: startIndex < 0 ? undefined : startIndex, startIndex:
this.cameras && this.view
? Math.max(0, Array.from(this.cameras.keys()).indexOf(this.view.camera))
: 0,
draggable: this.liveConfig?.draggable, draggable: this.liveConfig?.draggable,
loop: true, loop: true,
}; };
+11 -35
View File
@@ -187,9 +187,9 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
* @param direction The direction requested, previous or next. * @param direction The direction requested, previous or next.
*/ */
protected _nextPreviousHandler(direction: 'previous' | 'next'): void { protected _nextPreviousHandler(direction: 'previous' | 'next'): void {
if (direction == 'previous') { if (direction === 'previous') {
this._carousel?.scrollPrev(this._getTransitionEffect() === 'none'); this._carousel?.scrollPrev(this._getTransitionEffect() === 'none');
} else if (direction == 'next') { } else if (direction === 'next') {
this._carousel?.scrollNext(this._getTransitionEffect() === 'none'); this._carousel?.scrollNext(this._getTransitionEffect() === 'none');
} }
} }
@@ -237,40 +237,16 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
// isValidMediaShowInfo is used to prevent saving media info that will be // isValidMediaShowInfo is used to prevent saving media info that will be
// rejected upstream (empty 1x1 images will be rejected here). // rejected upstream (empty 1x1 images will be rejected here).
if (mediaShowInfo && isValidMediaShowInfo(mediaShowInfo)) { if (mediaShowInfo && isValidMediaShowInfo(mediaShowInfo)) {
this._mediaShowInfo[slideIndex] = mediaShowInfo; if (!Object.keys(this._mediaShowInfo).length) {
if (this._carousel && this._carousel?.selectedScrollSnap() == slideIndex) { // The carousel will be malformed on Safari unless we re-init the
dispatchExistingMediaShowInfoAsEvent(this, mediaShowInfo); // carousel after the first media load. The original options are
// included here, although this should not be necessary (without
// including them, Safari ends up not having a looping live carousel).
this._carousel?.reInit(this._getOptions());
} }
this._mediaShowInfo[slideIndex] = mediaShowInfo;
/** if (this._carousel && this._carousel?.selectedScrollSnap() === slideIndex) {
* Images need a width/height from initial load, and browsers will assume dispatchExistingMediaShowInfoAsEvent(this, mediaShowInfo);
* that the aspect ratio of the initial dummy-image load will persist. In
* lazy-loading, this can cause a 1x1 pixel dummy image to cause the
* browser to assume all images will be square, so the whole carousel will
* have the wrong aspect-ratio until every single image has been lazily
* loaded. Adaptive height helps in that the carousel gets resized on each
* img display to the correct size, but it still causes a minor noticeable
* flicker until the height change is complete.
*
* To avoid this, we use a 16:9 dummy image at first (most
* likely?) and once the first piece of real media has been loaded, all
* dummy images are replaced with dummy images that match the aspect ratio
* of the real image. It still might be wrong, but it's the best option
* available.
*/
const firstMediaLoad = !Object.keys(this._mediaShowInfo).length;
if (firstMediaLoad) {
const replacementImageSrc = getEmptyImageSrc(
mediaShowInfo.width,
mediaShowInfo.height,
);
this.renderRoot.querySelectorAll('.embla__container img').forEach((img) => {
const imageElement = img as HTMLImageElement;
if (imageElement.src === IMG_EMPTY) {
imageElement.src = replacementImageSrc;
}
});
} }
} }
} }
+1 -1
View File
@@ -274,7 +274,7 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
return { return {
// Start the carousel on the selected child number. // Start the carousel on the selected child number.
startIndex: this._getSlideForChild(this.view?.childIndex) ?? 0, startIndex: this._getSlideForChild(this.view?.childIndex) ?? 0,
draggable: this.viewerConfig?.draggable, draggable: this.viewerConfig?.draggable ?? true,
}; };
} }