From c616ffeb6c8130b626e1bcf24d4155d997d9a181 Mon Sep 17 00:00:00 2001 From: trivernis Date: Wed, 29 May 2024 19:37:32 +0200 Subject: [PATCH] Fix retry logic for image urls --- .../content-aware-image.component.ts | 190 ++++++++++-------- 1 file changed, 103 insertions(+), 87 deletions(-) diff --git a/mediarepo-ui/src/app/components/shared/app-common/content-aware-image/content-aware-image.component.ts b/mediarepo-ui/src/app/components/shared/app-common/content-aware-image/content-aware-image.component.ts index 22b7187..768e608 100644 --- a/mediarepo-ui/src/app/components/shared/app-common/content-aware-image/content-aware-image.component.ts +++ b/mediarepo-ui/src/app/components/shared/app-common/content-aware-image/content-aware-image.component.ts @@ -1,106 +1,122 @@ import { - ChangeDetectionStrategy, - ChangeDetectorRef, - Component, - DoCheck, - ElementRef, - EventEmitter, - Input, - OnDestroy, - OnInit, - Output, - ViewChild + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + DoCheck, + ElementRef, + EventEmitter, + Input, + OnDestroy, + OnInit, + Output, + ViewChild, } from "@angular/core"; -import {SafeResourceUrl} from "@angular/platform-browser"; +import { SafeResourceUrl } from "@angular/platform-browser"; @Component({ - selector: "app-content-aware-image", - templateUrl: "./content-aware-image.component.html", - styleUrls: ["./content-aware-image.component.scss"], - changeDetection: ChangeDetectionStrategy.OnPush, + selector: "app-content-aware-image", + templateUrl: "./content-aware-image.component.html", + styleUrls: ["./content-aware-image.component.scss"], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class ContentAwareImageComponent implements OnInit, DoCheck, OnDestroy { - @Input() imageSrc!: string | SafeResourceUrl; - @Input() maximizeHeight: boolean = true; - @Input() maximizeWidth: boolean = true; - @Input() borderRadius: string | undefined; - @Input() decoding: "async" | "sync" | "auto" = "auto"; - @Input() maxRetry = 3; - @Input() retryDelay = 200; - @ViewChild("image") imageElement?: ElementRef; - @ViewChild("imageContainer") imageContainer?: ElementRef; - @Output() appLoadEnd = new EventEmitter(); - @Output() appLoadError = new EventEmitter(); + @Input() imageSrc!: string | SafeResourceUrl; + @Input() maximizeHeight: boolean = true; + @Input() maximizeWidth: boolean = true; + @Input() borderRadius: string | undefined; + @Input() decoding: "async" | "sync" | "auto" = "auto"; + @Input() maxRetry = 3; + @Input() retryDelay = 200; + @ViewChild("image") imageElement?: ElementRef; + @ViewChild("imageContainer") imageContainer?: ElementRef; + @Output() appLoadEnd = new EventEmitter(); + @Output() appLoadError = new EventEmitter(); - scaleWidth = false; - private previousHeight = 0; - private previousWidth = 0; - private retryCount = 0; - private readonly checkInterval?: number; + scaleWidth = false; + private previousHeight = 0; + private previousWidth = 0; + private retryCount = 0; + private readonly checkInterval?: number; - constructor(private changeDetector: ChangeDetectorRef) { - this.checkInterval = setInterval(() => this.checkSize(), 1000); - } + constructor(private changeDetector: ChangeDetectorRef) { + this.checkInterval = setInterval(() => this.checkSize(), 1000); + } - public ngOnInit(): void { - if (this.imageElement) { - this.imageElement.nativeElement.decoding = this.decoding; - this.changeDetector.detach(); - } - } + public ngOnInit(): void { + if (this.imageElement) { + this.imageElement.nativeElement.decoding = this.decoding; + this.changeDetector.detach(); + } + } - public ngOnDestroy(): void { - clearInterval(this.checkInterval); - } + public ngOnDestroy(): void { + clearInterval(this.checkInterval); + } - public ngDoCheck(): void { - this.checkSize(); - } + public ngDoCheck(): void { + this.checkSize(); + } - public checkSize(): void { - if (this.imageElement?.nativeElement && this.imageContainer?.nativeElement) { - this.adjustSize(this.imageElement.nativeElement, this.imageContainer.nativeElement); - } - } + public checkSize(): void { + if ( + this.imageElement?.nativeElement && + this.imageContainer?.nativeElement + ) { + this.adjustSize( + this.imageElement.nativeElement, + this.imageContainer.nativeElement, + ); + } + } - public onImageLoad(image: HTMLImageElement, imageContainer: HTMLDivElement): void { - this.adjustSize(image, imageContainer); - this.appLoadEnd.emit(); - } + public onImageLoad( + image: HTMLImageElement, + imageContainer: HTMLDivElement, + ): void { + this.adjustSize(image, imageContainer); + this.appLoadEnd.emit(); + } - /** - * Fits the image into the container - * @param {HTMLImageElement} image - * @param {HTMLDivElement} imageContainer - */ - public adjustSize(image: HTMLImageElement, imageContainer: HTMLDivElement): void { - const containerHeight = Math.abs(imageContainer.clientHeight); - const containerWidth = Math.abs(imageContainer.clientWidth); + /** + * Fits the image into the container + * @param {HTMLImageElement} image + * @param {HTMLDivElement} imageContainer + */ + public adjustSize( + image: HTMLImageElement, + imageContainer: HTMLDivElement, + ): void { + const containerHeight = Math.abs(imageContainer.clientHeight); + const containerWidth = Math.abs(imageContainer.clientWidth); - if (this.previousWidth != containerWidth || this.previousHeight != containerHeight) { - this.previousHeight = containerHeight; - this.previousWidth = containerWidth; - const imageRelativeHeight = image.naturalHeight / containerHeight; - const imageRelativeWidth = image.naturalWidth / containerWidth; - const scaleWidth = imageRelativeWidth > imageRelativeHeight; + if ( + this.previousWidth !== containerWidth || + this.previousHeight !== containerHeight + ) { + this.previousHeight = containerHeight; + this.previousWidth = containerWidth; + const imageRelativeHeight = image.naturalHeight / containerHeight; + const imageRelativeWidth = image.naturalWidth / containerWidth; + const scaleWidth = imageRelativeWidth > imageRelativeHeight; - if (scaleWidth != this.scaleWidth) { - this.scaleWidth = scaleWidth; - this.changeDetector.detectChanges(); - } - } - } + if (scaleWidth !== this.scaleWidth) { + this.scaleWidth = scaleWidth; + this.changeDetector.detectChanges(); + } + } + } - public onImageLoadError(error: ErrorEvent, image: HTMLImageElement): void { - const imageSrc = image.src; + public onImageLoadError(error: ErrorEvent, image: HTMLImageElement): void { + const imageSrc = image.src; - if (this.retryCount < this.maxRetry) { - this.retryCount++; - setTimeout(() => { - image.src = imageSrc; - }, this.retryDelay * this.retryCount); - } else { - this.appLoadError.emit(); - } - } + if (this.retryCount < this.maxRetry) { + this.retryCount++; + image.src = ""; + setTimeout(() => { + image.src = imageSrc; + }, this.retryDelay * this.retryCount); + } else { + this.appLoadError.emit(); + } + } }