fix(discover): 🐛 Created new Image component to handle 429's from TMDB (#4698) and fixed #4635

This commit is contained in:
tidusjar 2022-07-25 21:10:18 +01:00
commit 55d0ae9c76
14 changed files with 80 additions and 17 deletions

View file

@ -68,7 +68,7 @@ import { TooltipModule } from "primeng/tooltip";
import { TranslateHttpLoader } from "@ngx-translate/http-loader"; import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { TranslateService } from "@ngx-translate/core"; import { TranslateService } from "@ngx-translate/core";
import { UnauthorizedInterceptor } from "./auth/unauthorized.interceptor"; import { UnauthorizedInterceptor } from "./auth/unauthorized.interceptor";
import { ImageBackgroundComponent } from "./components/"; import { ImageBackgroundComponent, ImageComponent } from "./components/";
import { environment } from "../environments/environment"; import { environment } from "../environments/environment";
const routes: Routes = [ const routes: Routes = [
@ -168,7 +168,8 @@ export function JwtTokenGetter() {
[ [
NgxsReduxDevtoolsPluginModule.forRoot(), NgxsReduxDevtoolsPluginModule.forRoot(),
], ],
ImageBackgroundComponent ImageBackgroundComponent,
ImageComponent,
], ],
declarations: [ declarations: [
AppComponent, AppComponent,

View file

@ -0,0 +1 @@
<img src="{{baseUrl + src}}" (onError)="onError($event)" [class]="class" [id]="id" [style]="style"/>

View file

@ -0,0 +1,57 @@
import { OmbiCommonModules } from "../modules";
import { ChangeDetectionStrategy, Component, ElementRef, Inject, Input, ViewEncapsulation } from "@angular/core";
import { RequestType } from "../../interfaces";
import { APP_BASE_HREF } from "@angular/common";
@Component({
standalone: true,
selector: 'ombi-image',
imports: [...OmbiCommonModules],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './image.component.html',
})
export class ImageComponent {
@Input() public src: string;
@Input() public type: RequestType;
// Attributes from the parent
@Input() public class: string;
@Input() public id: string;
@Input() public alt: string;
@Input() public style: string;
public baseUrl: string = "";
public defaultTv = "images/default_tv_poster.png";
private defaultMovie = "images/default_movie_poster.png";
private defaultMusic = "images/default-music-placeholder.png";
constructor (@Inject(APP_BASE_HREF) public href: string) {
if (this.href.length > 1) {
this.baseUrl = this.href;
}
}
public onError(event: any) {
// set to a placeholder
switch(this.type) {
case RequestType.movie:
event.target.src = this.defaultMovie;
break;
case RequestType.tvShow:
event.target.src = this.defaultTv;
break;
case RequestType.album:
event.target.src = this.defaultMusic;
break;
}
// Retry the original image
const timeout = setTimeout(() => {
event.target.src = this.src;
clearTimeout(timeout);
}, Math.floor(Math.random() * (7000 - 1000 + 1)) + 1000);
}
}

View file

@ -1 +1,2 @@
export * from "./image-background/image-background.component"; export * from "./image-background/image-background.component";
export * from "./image/image.component";

View file

@ -9,7 +9,7 @@
<span class="indicator"></span><span class="indicator-text" id="availabilityStatus{{result.id}}">{{getAvailabilityStatus()}}</span> <span class="indicator"></span><span class="indicator-text" id="availabilityStatus{{result.id}}">{{getAvailabilityStatus()}}</span>
</div> </div>
</div> </div>
<img [routerLink]="generateDetailsLink()" id="cardImage" src="{{result.posterPath}}" class="image" (error)="onImageError($event)" alt="{{result.title}}"> <ombi-image [src]="result.posterPath" [type]="result.type" [routerLink]="generateDetailsLink()" id="cardImage" class="image" alt="{{result.title}}"></ombi-image>
<div [ngClass]="result.posterPath.includes('images/') ? 'middle-show' : 'middle'"> <div [ngClass]="result.posterPath.includes('images/') ? 'middle-show' : 'middle'">
<a class="poster-overlay" [routerLink]="generateDetailsLink()"> <a class="poster-overlay" [routerLink]="generateDetailsLink()">
<div class="summary"> <div class="summary">

View file

@ -83,7 +83,7 @@ small {
} }
.image { ::ng-deep .image {
border-radius: 10px; border-radius: 10px;
opacity: 1; opacity: 1;
display: block; display: block;

View file

@ -8,6 +8,7 @@ import { PipeModule } from "../pipes/pipe.module";
import { RouterModule } from "@angular/router"; import { RouterModule } from "@angular/router";
import { SharedModule } from "../shared/shared.module"; import { SharedModule } from "../shared/shared.module";
import { SkeletonModule } from 'primeng/skeleton'; import { SkeletonModule } from 'primeng/skeleton';
import { ImageComponent } from 'app/components';
@NgModule({ @NgModule({
imports: [ imports: [
@ -18,6 +19,7 @@ import { SkeletonModule } from 'primeng/skeleton';
MatButtonToggleModule, MatButtonToggleModule,
InfiniteScrollModule, InfiniteScrollModule,
SkeletonModule, SkeletonModule,
ImageComponent
], ],
declarations: [ declarations: [
...fromComponents.components ...fromComponents.components

View file

@ -252,9 +252,9 @@
<div class="sidebar affixable affix-top preview-poster"> <div class="sidebar affixable affix-top preview-poster">
<div class="poster"> <div class="poster">
<a [routerLink]="'/details/movie/'+r.id"> <a [routerLink]="'/details/movie/'+r.id">
<img class="real grow" matTooltip="{{r.title}}" <ombi-image class="real grow" matTooltip="{{r.title}}"
src="https://image.tmdb.org/t/p/w300/{{r.poster_path}}" src="https://image.tmdb.org/t/p/w300/{{r.poster_path}}"
alt="Poster" style="display: block;"> alt="Poster" style="display: block;"> </ombi-image>
</a> </a>
</div> </div>
</div> </div>
@ -274,9 +274,9 @@
<div class="sidebar affixable affix-top preview-poster"> <div class="sidebar affixable affix-top preview-poster">
<div class="poster "> <div class="poster ">
<a [routerLink]="'/details/movie/'+r.id"> <a [routerLink]="'/details/movie/'+r.id">
<img class="real grow" matTooltip="{{r.title}}" <ombi-image class="real grow" matTooltip="{{r.title}}"
src="https://image.tmdb.org/t/p/w300/{{r.poster_path}}" src="https://image.tmdb.org/t/p/w300/{{r.poster_path}}"
alt="Poster" style="display: block;"> alt="Poster" style="display: block;"></ombi-image>
</a> </a>
</div> </div>
</div> </div>

View file

@ -6,10 +6,10 @@
<div class="row justify-content-md-center mat-card mat-card-flat carousel-item"> <div class="row justify-content-md-center mat-card mat-card-flat carousel-item">
<div class="bottom-space"> <div class="bottom-space">
<a *ngIf="item.image" [routerLink]="'/discover/actor/' + item.id"> <a *ngIf="item.image" [routerLink]="'/discover/actor/' + item.id">
<img class="cast-profile-img" src="https://image.tmdb.org/t/p/w300{{item.image}}"> <ombi-image class="cast-profile-img" src="https://image.tmdb.org/t/p/w300{{item.image}}"></ombi-image>
</a> </a>
<a *ngIf="item.profile_path" [routerLink]="'/discover/actor/' + item.id"> <a *ngIf="item.profile_path" [routerLink]="'/discover/actor/' + item.id">
<img class="cast-profile-img" src="https://image.tmdb.org/t/p/w300{{item.profile_path}}"> <ombi-image class="cast-profile-img" src="https://image.tmdb.org/t/p/w300{{item.profile_path}}"></ombi-image>
</a> </a>
<!-- TODO get profile image default --> <!-- TODO get profile image default -->

View file

@ -65,7 +65,7 @@ body .ui-carousel .ui-carousel-content .ui-carousel-next:not(.ui-state-disabled)
@media (min-width: 979px) { @media (min-width: 979px) {
.cast-profile-img { :host ::ng-deep .cast-profile-img {
border-radius: 100%; border-radius: 100%;
width: 200px; width: 200px;
max-height: 200px; max-height: 200px;
@ -74,7 +74,7 @@ body .ui-carousel .ui-carousel-content .ui-carousel-next:not(.ui-state-disabled)
} }
@media (max-width: 978px) { @media (max-width: 978px) {
.cast-profile-img { :host ::ng-deep .cast-profile-img {
border-radius: 100%; border-radius: 100%;
width: 100px; width: 100px;
max-height: 100px; max-height: 100px;

View file

@ -1,8 +1,8 @@
<div class="col-md-2 col-sm-3 hidden-xs"> <div class="col-md-2 col-sm-3 hidden-xs">
<div class="sidebar sidebar-poster affixable affix-top"> <div class="sidebar sidebar-poster affixable affix-top">
<div class="poster mobile-poster"> <div class="poster mobile-poster">
<img class="real" src="{{posterPath}}" alt="Poster" <ombi-image class="real" src="{{posterPath}}" alt="Poster"
style="display: block;"> style="display: block;"></ombi-image>
</div> </div>
<!--Underneith poster--> <!--Underneith poster-->
<br /> <br />

View file

@ -2,7 +2,6 @@
<section id="summary-wrapper"> <section id="summary-wrapper">
<div class="full-screenshot enabled" [style.background-image]="background"></div> <div class="full-screenshot enabled" [style.background-image]="background"></div>
<div class="full-screenshot enabled overlay"></div> <div class="full-screenshot enabled overlay"></div>
<!--<div class="shadow-base" [ngClass]="available ? 'available-bottom-border' : ''"></div>-->
<div class="container summary"> <div class="container summary">
<div class="container title-top-banner"> <div class="container title-top-banner">

View file

@ -2,7 +2,7 @@
<div> <div>
<div class="rating medium-font"> <div class="rating medium-font">
<span *ngIf="tv.rating"> <span *ngIf="tv.rating">
<img class="rating-small" src="{{baseUrl}}/images/tmdb-logo.svg"> {{tv.rating * 10}}% <img class="rating-small" src="{{baseUrl}}/images/tmdb-logo.svg"> {{tv.rating * 10 | number : '1.2-2'}}%
</span> </span>
<span *ngIf="ratings?.score && ratings?.class"> <span *ngIf="ratings?.score && ratings?.class">
<img class="rating-small" src="{{baseUrl}}/images/{{ratings.class === 'rotten' ? 'rotten-rotten.svg' : 'rotten-fresh.svg'}}"> {{ratings.score}}% <img class="rating-small" src="{{baseUrl}}/images/{{ratings.class === 'rotten' ? 'rotten-rotten.svg' : 'rotten-fresh.svg'}}"> {{ratings.score}}%

View file

@ -12,6 +12,7 @@ import * as fromComponents from './components';
import { AuthGuard } from "../auth/auth.guard"; import { AuthGuard } from "../auth/auth.guard";
import { ArtistDetailsComponent } from "./components/artist/artist-details.component"; import { ArtistDetailsComponent } from "./components/artist/artist-details.component";
import { ReactiveFormsModule } from "@angular/forms"; import { ReactiveFormsModule } from "@angular/forms";
import { ImageComponent } from "app/components";
const routes: Routes = [ const routes: Routes = [
@ -27,6 +28,7 @@ const routes: Routes = [
ReactiveFormsModule, ReactiveFormsModule,
PipeModule, PipeModule,
CarouselModule, CarouselModule,
ImageComponent,
], ],
declarations: [ declarations: [
...fromComponents.components ...fromComponents.components