From b10a5e6b45ac20bd5c411953d946578ce34bd6cd Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 15 May 2022 08:37:19 -0700 Subject: [PATCH] Fix malformed Safari live carousel. --- src/components/live.ts | 14 +++++----- src/components/media-carousel.ts | 46 ++++++++------------------------ src/components/viewer.ts | 2 +- 3 files changed, 18 insertions(+), 44 deletions(-) diff --git a/src/components/live.ts b/src/components/live.ts index 6c78aa43..83ad8627 100644 --- a/src/components/live.ts +++ b/src/components/live.ts @@ -72,7 +72,7 @@ export class FrigateCardLive extends LitElement { @property({ attribute: false }) protected liveConfig?: LiveConfig; - @property({ attribute: false }) + @property({ attribute: false, hasChanged: contentsChanged }) protected liveOverrides?: LiveOverrides; @property({ attribute: false }) @@ -191,7 +191,7 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel { @property({ attribute: false }) protected liveConfig?: LiveConfig; - @property({ attribute: false }) + @property({ attribute: false, hasChanged: contentsChanged }) protected liveOverrides?: LiveOverrides; @property({ attribute: false }) @@ -275,13 +275,11 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel { * @returns An EmblaOptionsType object or undefined for no options. */ protected _getOptions(): EmblaOptionsType { - let startIndex = -1; - if (this.cameras && this.view) { - startIndex = Array.from(this.cameras.keys()).indexOf(this.view.camera); - } - 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, loop: true, }; diff --git a/src/components/media-carousel.ts b/src/components/media-carousel.ts index 2ff28371..414dd21a 100644 --- a/src/components/media-carousel.ts +++ b/src/components/media-carousel.ts @@ -187,9 +187,9 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel { * @param direction The direction requested, previous or next. */ protected _nextPreviousHandler(direction: 'previous' | 'next'): void { - if (direction == 'previous') { + if (direction === 'previous') { this._carousel?.scrollPrev(this._getTransitionEffect() === 'none'); - } else if (direction == 'next') { + } else if (direction === 'next') { 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 // rejected upstream (empty 1x1 images will be rejected here). if (mediaShowInfo && isValidMediaShowInfo(mediaShowInfo)) { - this._mediaShowInfo[slideIndex] = mediaShowInfo; - if (this._carousel && this._carousel?.selectedScrollSnap() == slideIndex) { - dispatchExistingMediaShowInfoAsEvent(this, mediaShowInfo); + if (!Object.keys(this._mediaShowInfo).length) { + // The carousel will be malformed on Safari unless we re-init the + // 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()); } - - /** - * Images need a width/height from initial load, and browsers will assume - * 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; - } - }); + this._mediaShowInfo[slideIndex] = mediaShowInfo; + if (this._carousel && this._carousel?.selectedScrollSnap() === slideIndex) { + dispatchExistingMediaShowInfoAsEvent(this, mediaShowInfo); } } } diff --git a/src/components/viewer.ts b/src/components/viewer.ts index 73c3fd26..0819b960 100644 --- a/src/components/viewer.ts +++ b/src/components/viewer.ts @@ -274,7 +274,7 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel { return { // Start the carousel on the selected child number. startIndex: this._getSlideForChild(this.view?.childIndex) ?? 0, - draggable: this.viewerConfig?.draggable, + draggable: this.viewerConfig?.draggable ?? true, }; }