mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-25 07:25:22 -07:00
modernise the discover
This commit is contained in:
parent
33e5706afa
commit
9524608c1f
4 changed files with 157 additions and 126 deletions
|
@ -1,21 +1,25 @@
|
||||||
<div class="right" *ngIf="discoverType !== DiscoverType.Seasonal">
|
@if (discoverType() !== DiscoverType.Seasonal) {
|
||||||
<mat-button-toggle-group name="discoverMode" (change)="toggleChanged($event)" value="{{discoverOptions}}" class="discover-filter-buttons-group">
|
<div class="right">
|
||||||
<mat-button-toggle id="{{id}}Combined" [ngClass]="{'button-active': discoverOptions === DiscoverOption.Combined}" value="{{DiscoverOption.Combined}}" class="discover-filter-button">{{'Discovery.Combined' | translate}}</mat-button-toggle>
|
<mat-button-toggle-group name="discoverMode" (change)="toggleChanged($event)" [value]="discoverOptions()" class="discover-filter-buttons-group">
|
||||||
<mat-button-toggle id="{{id}}Movie" [ngClass]="{'button-active': discoverOptions === DiscoverOption.Movie}" value="{{DiscoverOption.Movie}}" class="discover-filter-button">{{'Discovery.Movies' | translate}}</mat-button-toggle>
|
<mat-button-toggle [id]="id() + 'Combined'" [class.button-active]="discoverOptions() === DiscoverOption.Combined" [value]="DiscoverOption.Combined" class="discover-filter-button">{{'Discovery.Combined' | translate}}</mat-button-toggle>
|
||||||
<mat-button-toggle id="{{id}}Tv" [ngClass]="{'button-active': discoverOptions === DiscoverOption.Tv}" value="{{DiscoverOption.Tv}}" class="discover-filter-button">{{'Discovery.Tv' | translate}}</mat-button-toggle>
|
<mat-button-toggle [id]="id() + 'Movie'" [class.button-active]="discoverOptions() === DiscoverOption.Movie" [value]="DiscoverOption.Movie" class="discover-filter-button">{{'Discovery.Movies' | translate}}</mat-button-toggle>
|
||||||
|
<mat-button-toggle [id]="id() + 'Tv'" [class.button-active]="discoverOptions() === DiscoverOption.Tv" [value]="DiscoverOption.Tv" class="discover-filter-button">{{'Discovery.Tv' | translate}}</mat-button-toggle>
|
||||||
</mat-button-toggle-group>
|
</mat-button-toggle-group>
|
||||||
</div>
|
</div>
|
||||||
@defer (when discoverResults.length > 0; prefetch on idle) {
|
}
|
||||||
<p-carousel #carousel [numVisible]="10" [numScroll]="10" [page]="0" [value]="discoverResults" [responsiveOptions]="responsiveOptions" (onPage)="newPage()">
|
|
||||||
|
@defer (when hasResults(); prefetch on idle) {
|
||||||
|
<p-carousel #carousel [numVisible]="10" [numScroll]="10" [page]="0" [value]="discoverResults()" [responsiveOptions]="responsiveOptions" (onPage)="newPage()">
|
||||||
<ng-template let-result pTemplate="item">
|
<ng-template let-result pTemplate="item">
|
||||||
<discover-card [discoverType]="discoverType" [isAdmin]="isAdmin" [result]="result" [is4kEnabled]="is4kEnabled"></discover-card>
|
<discover-card [discoverType]="discoverType()" [isAdmin]="isAdmin()" [result]="result" [is4kEnabled]="is4kEnabled()"></discover-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-carousel>
|
</p-carousel>
|
||||||
}
|
} @placeholder(minimum 300) {
|
||||||
@placeholder(minimum 300) {
|
|
||||||
<div class="row loading-container">
|
<div class="row loading-container">
|
||||||
<div class="col-2" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
@for (item of [1,2,3,4,5,6,7,8,9,10]; track item) {
|
||||||
|
<div class="col-2">
|
||||||
<p-skeleton width="100%" height="270px"></p-skeleton>
|
<p-skeleton width="100%" height="270px"></p-skeleton>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, OnInit, Input, ViewChild, Output, EventEmitter, Inject } from "@angular/core";
|
import { Component, ViewChild, Inject, input, output, signal, computed, inject, ChangeDetectionStrategy } from "@angular/core";
|
||||||
import { DiscoverOption, IDiscoverCardResult } from "../../interfaces";
|
import { DiscoverOption, IDiscoverCardResult } from "../../interfaces";
|
||||||
import { ISearchMovieResult, ISearchTvResult, RequestType } from "../../../interfaces";
|
import { ISearchMovieResult, ISearchTvResult, RequestType } from "../../../interfaces";
|
||||||
import { SearchV2Service } from "../../../services";
|
import { SearchV2Service } from "../../../services";
|
||||||
|
@ -21,42 +21,51 @@ export enum DiscoverType {
|
||||||
selector: "carousel-list",
|
selector: "carousel-list",
|
||||||
templateUrl: "./carousel-list.component.html",
|
templateUrl: "./carousel-list.component.html",
|
||||||
styleUrls: ["./carousel-list.component.scss"],
|
styleUrls: ["./carousel-list.component.scss"],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class CarouselListComponent implements OnInit {
|
export class CarouselListComponent {
|
||||||
|
// Inputs using new input() function
|
||||||
|
public discoverType = input.required<DiscoverType>();
|
||||||
|
public id = input.required<string>();
|
||||||
|
public isAdmin = input<boolean>(false);
|
||||||
|
|
||||||
|
// Output using new output() function
|
||||||
|
public movieCount = output<number>();
|
||||||
|
|
||||||
@Input() public discoverType: DiscoverType;
|
|
||||||
@Input() public id: string;
|
|
||||||
@Input() public isAdmin: boolean;
|
|
||||||
@Output() public movieCount: EventEmitter<number> = new EventEmitter();
|
|
||||||
@ViewChild('carousel', {static: false}) carousel: Carousel;
|
@ViewChild('carousel', {static: false}) carousel: Carousel;
|
||||||
|
|
||||||
|
// Services using inject() function
|
||||||
|
private searchService = inject(SearchV2Service);
|
||||||
|
private storageService = inject(StorageService);
|
||||||
|
private featureFacade = inject(FeaturesFacade);
|
||||||
|
private baseUrl = inject(APP_BASE_HREF);
|
||||||
|
|
||||||
|
// Public constants
|
||||||
public DiscoverOption = DiscoverOption;
|
public DiscoverOption = DiscoverOption;
|
||||||
public discoverOptions: DiscoverOption = DiscoverOption.Combined;
|
|
||||||
public discoverResults: IDiscoverCardResult[] = [];
|
|
||||||
public movies: ISearchMovieResult[] = [];
|
|
||||||
public tvShows: ISearchTvResult[] = [];
|
|
||||||
public responsiveOptions: any;
|
|
||||||
public RequestType = RequestType;
|
public RequestType = RequestType;
|
||||||
public loadingFlag: boolean;
|
|
||||||
public DiscoverType = DiscoverType;
|
public DiscoverType = DiscoverType;
|
||||||
public is4kEnabled = false;
|
|
||||||
|
// State using signals
|
||||||
|
public discoverOptions = signal<DiscoverOption>(DiscoverOption.Combined);
|
||||||
|
public discoverResults = signal<IDiscoverCardResult[]>([]);
|
||||||
|
public movies = signal<ISearchMovieResult[]>([]);
|
||||||
|
public tvShows = signal<ISearchTvResult[]>([]);
|
||||||
|
public loadingFlag = signal<boolean>(false);
|
||||||
|
public is4kEnabled = signal<boolean>(false);
|
||||||
|
|
||||||
|
// Computed properties
|
||||||
|
public hasResults = computed(() => this.discoverResults().length > 0);
|
||||||
|
public totalResults = computed(() => this.discoverResults().length);
|
||||||
|
|
||||||
get mediaTypeStorageKey() {
|
get mediaTypeStorageKey() {
|
||||||
return "DiscoverOptions" + this.discoverType.toString();
|
return "DiscoverOptions" + this.discoverType().toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
private amountToLoad = 10;
|
private amountToLoad = 10;
|
||||||
private currentlyLoaded = 0;
|
private currentlyLoaded = 0;
|
||||||
private baseUrl: string = "";
|
public responsiveOptions: any;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
constructor(private searchService: SearchV2Service,
|
|
||||||
private storageService: StorageService,
|
|
||||||
private featureFacade: FeaturesFacade,
|
|
||||||
@Inject(APP_BASE_HREF) private href: string) {
|
|
||||||
|
|
||||||
if (this.href.length > 1) {
|
|
||||||
this.baseUrl = this.href;
|
|
||||||
}
|
|
||||||
|
|
||||||
Carousel.prototype.onTouchMove = () => { },
|
Carousel.prototype.onTouchMove = () => { },
|
||||||
this.responsiveOptions = [
|
this.responsiveOptions = [
|
||||||
|
@ -149,12 +158,14 @@ export class CarouselListComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ngOnInit() {
|
public async ngOnInit() {
|
||||||
|
// Initialize 4K feature flag
|
||||||
this.is4kEnabled = this.featureFacade.is4kEnabled();
|
this.is4kEnabled.set(this.featureFacade.is4kEnabled());
|
||||||
this.currentlyLoaded = 0;
|
this.currentlyLoaded = 0;
|
||||||
|
|
||||||
|
// Load saved discover options from storage
|
||||||
const localDiscoverOptions = +this.storageService.get(this.mediaTypeStorageKey);
|
const localDiscoverOptions = +this.storageService.get(this.mediaTypeStorageKey);
|
||||||
if (localDiscoverOptions) {
|
if (localDiscoverOptions) {
|
||||||
this.discoverOptions = DiscoverOption[DiscoverOption[localDiscoverOptions]];
|
this.discoverOptions.set(DiscoverOption[DiscoverOption[localDiscoverOptions]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load initial data - just enough to fill the first carousel page
|
// Load initial data - just enough to fill the first carousel page
|
||||||
|
@ -162,10 +173,9 @@ export class CarouselListComponent implements OnInit {
|
||||||
await this.loadData(false);
|
await this.loadData(false);
|
||||||
|
|
||||||
// If we don't have enough results to fill the carousel, load one more batch
|
// If we don't have enough results to fill the carousel, load one more batch
|
||||||
if (this.discoverResults.length < 10) {
|
if (this.discoverResults().length < 10) {
|
||||||
await this.loadData(false);
|
await this.loadData(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async toggleChanged(event: MatButtonToggleChange) {
|
public async toggleChanged(event: MatButtonToggleChange) {
|
||||||
|
@ -183,7 +193,7 @@ export class CarouselListComponent implements OnInit {
|
||||||
if (end) {
|
if (end) {
|
||||||
var moviePromise: Promise<void>;
|
var moviePromise: Promise<void>;
|
||||||
var tvPromise: Promise<void>;
|
var tvPromise: Promise<void>;
|
||||||
switch (+this.discoverOptions) {
|
switch (+this.discoverOptions()) {
|
||||||
case DiscoverOption.Combined:
|
case DiscoverOption.Combined:
|
||||||
moviePromise = this.loadMovies();
|
moviePromise = this.loadMovies();
|
||||||
tvPromise = this.loadTv();
|
tvPromise = this.loadTv();
|
||||||
|
@ -205,7 +215,7 @@ export class CarouselListComponent implements OnInit {
|
||||||
private async loadData(clearExisting: boolean = true) {
|
private async loadData(clearExisting: boolean = true) {
|
||||||
var moviePromise: Promise<void>;
|
var moviePromise: Promise<void>;
|
||||||
var tvPromise: Promise<void>;
|
var tvPromise: Promise<void>;
|
||||||
switch (+this.discoverOptions) {
|
switch (+this.discoverOptions()) {
|
||||||
case DiscoverOption.Combined:
|
case DiscoverOption.Combined:
|
||||||
moviePromise = this.loadMovies();
|
moviePromise = this.loadMovies();
|
||||||
tvPromise = this.loadTv();
|
tvPromise = this.loadTv();
|
||||||
|
@ -223,50 +233,50 @@ export class CarouselListComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async switchDiscoverMode(newMode: DiscoverOption) {
|
private async switchDiscoverMode(newMode: DiscoverOption) {
|
||||||
if (this.discoverOptions === newMode) {
|
if (this.discoverOptions() === newMode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.loading();
|
this.loading();
|
||||||
this.currentlyLoaded = 0;
|
this.currentlyLoaded = 0;
|
||||||
this.discoverOptions = +newMode;
|
this.discoverOptions.set(+newMode);
|
||||||
this.storageService.save(this.mediaTypeStorageKey, newMode.toString());
|
this.storageService.save(this.mediaTypeStorageKey, newMode.toString());
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
this.finishLoading();
|
this.finishLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadMovies() {
|
private async loadMovies() {
|
||||||
switch (this.discoverType) {
|
switch (this.discoverType()) {
|
||||||
case DiscoverType.Popular:
|
case DiscoverType.Popular:
|
||||||
this.movies = await this.searchService.popularMoviesByPage(this.currentlyLoaded, this.amountToLoad);
|
this.movies.set(await this.searchService.popularMoviesByPage(this.currentlyLoaded, this.amountToLoad));
|
||||||
break;
|
break;
|
||||||
case DiscoverType.Trending:
|
case DiscoverType.Trending:
|
||||||
this.movies = await this.searchService.nowPlayingMoviesByPage(this.currentlyLoaded, this.amountToLoad);
|
this.movies.set(await this.searchService.nowPlayingMoviesByPage(this.currentlyLoaded, this.amountToLoad));
|
||||||
break;
|
break;
|
||||||
case DiscoverType.Upcoming:
|
case DiscoverType.Upcoming:
|
||||||
this.movies = await this.searchService.upcomingMoviesByPage(this.currentlyLoaded, this.amountToLoad);
|
this.movies.set(await this.searchService.upcomingMoviesByPage(this.currentlyLoaded, this.amountToLoad));
|
||||||
break
|
break;
|
||||||
case DiscoverType.RecentlyRequested:
|
case DiscoverType.RecentlyRequested:
|
||||||
this.movies = await this.searchService.recentlyRequestedMoviesByPage(this.currentlyLoaded, this.amountToLoad);
|
this.movies.set(await this.searchService.recentlyRequestedMoviesByPage(this.currentlyLoaded, this.amountToLoad));
|
||||||
break;
|
break;
|
||||||
case DiscoverType.Seasonal:
|
case DiscoverType.Seasonal:
|
||||||
this.movies = await this.searchService.seasonalMoviesByPage(this.currentlyLoaded, this.amountToLoad);
|
this.movies.set(await this.searchService.seasonalMoviesByPage(this.currentlyLoaded, this.amountToLoad));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.movieCount.emit(this.movies.length);
|
this.movieCount.emit(this.movies().length);
|
||||||
this.currentlyLoaded += this.amountToLoad;
|
this.currentlyLoaded += this.amountToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async loadTv() {
|
private async loadTv() {
|
||||||
switch (this.discoverType) {
|
switch (this.discoverType()) {
|
||||||
case DiscoverType.Popular:
|
case DiscoverType.Popular:
|
||||||
this.tvShows = await this.searchService.popularTvByPage(this.currentlyLoaded, this.amountToLoad);
|
this.tvShows.set(await this.searchService.popularTvByPage(this.currentlyLoaded, this.amountToLoad));
|
||||||
break;
|
break;
|
||||||
case DiscoverType.Trending:
|
case DiscoverType.Trending:
|
||||||
this.tvShows = await this.searchService.trendingTvByPage(this.currentlyLoaded, this.amountToLoad);
|
this.tvShows.set(await this.searchService.trendingTvByPage(this.currentlyLoaded, this.amountToLoad));
|
||||||
break;
|
break;
|
||||||
case DiscoverType.Upcoming:
|
case DiscoverType.Upcoming:
|
||||||
this.tvShows = await this.searchService.anticipatedTvByPage(this.currentlyLoaded, this.amountToLoad);
|
this.tvShows.set(await this.searchService.anticipatedTvByPage(this.currentlyLoaded, this.amountToLoad));
|
||||||
break
|
break;
|
||||||
case DiscoverType.RecentlyRequested:
|
case DiscoverType.RecentlyRequested:
|
||||||
// this.tvShows = await this.searchService.recentlyRequestedMoviesByPage(this.currentlyLoaded, this.amountToLoad); // TODO need to do some more mapping
|
// this.tvShows = await this.searchService.recentlyRequestedMoviesByPage(this.currentlyLoaded, this.amountToLoad); // TODO need to do some more mapping
|
||||||
break;
|
break;
|
||||||
|
@ -284,7 +294,7 @@ export class CarouselListComponent implements OnInit {
|
||||||
private createModel() {
|
private createModel() {
|
||||||
const tempResults = <IDiscoverCardResult[]>[];
|
const tempResults = <IDiscoverCardResult[]>[];
|
||||||
|
|
||||||
switch (+this.discoverOptions) {
|
switch (+this.discoverOptions()) {
|
||||||
case DiscoverOption.Combined:
|
case DiscoverOption.Combined:
|
||||||
tempResults.push(...this.mapMovieModel());
|
tempResults.push(...this.mapMovieModel());
|
||||||
tempResults.push(...this.mapTvModel());
|
tempResults.push(...this.mapTvModel());
|
||||||
|
@ -298,14 +308,14 @@ export class CarouselListComponent implements OnInit {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.discoverResults.push(...tempResults);
|
this.discoverResults.update(current => [...current, ...tempResults]);
|
||||||
|
|
||||||
this.finishLoading();
|
this.finishLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
private mapMovieModel(): IDiscoverCardResult[] {
|
private mapMovieModel(): IDiscoverCardResult[] {
|
||||||
const tempResults = <IDiscoverCardResult[]>[];
|
const tempResults = <IDiscoverCardResult[]>[];
|
||||||
this.movies.forEach(m => {
|
this.movies().forEach(m => {
|
||||||
tempResults.push({
|
tempResults.push({
|
||||||
available: m.available,
|
available: m.available,
|
||||||
posterPath: m.posterPath ? `https://image.tmdb.org/t/p/w500/${m.posterPath}` : this.baseUrl + "/images/default_movie_poster.png",
|
posterPath: m.posterPath ? `https://image.tmdb.org/t/p/w500/${m.posterPath}` : this.baseUrl + "/images/default_movie_poster.png",
|
||||||
|
@ -327,7 +337,7 @@ export class CarouselListComponent implements OnInit {
|
||||||
|
|
||||||
private mapTvModel(): IDiscoverCardResult[] {
|
private mapTvModel(): IDiscoverCardResult[] {
|
||||||
const tempResults = <IDiscoverCardResult[]>[];
|
const tempResults = <IDiscoverCardResult[]>[];
|
||||||
this.tvShows.forEach(m => {
|
this.tvShows().forEach(m => {
|
||||||
tempResults.push({
|
tempResults.push({
|
||||||
available: m.fullyAvailable,
|
available: m.fullyAvailable,
|
||||||
posterPath: m.backdropPath ? `https://image.tmdb.org/t/p/w500/${m.backdropPath}` : this.baseUrl + "/images/default_tv_poster.png",
|
posterPath: m.backdropPath ? `https://image.tmdb.org/t/p/w500/${m.backdropPath}` : this.baseUrl + "/images/default_tv_poster.png",
|
||||||
|
@ -348,7 +358,7 @@ export class CarouselListComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private clear() {
|
private clear() {
|
||||||
this.discoverResults = [];
|
this.discoverResults.set([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private shuffle(discover: IDiscoverCardResult[]): IDiscoverCardResult[] {
|
private shuffle(discover: IDiscoverCardResult[]): IDiscoverCardResult[] {
|
||||||
|
@ -360,11 +370,11 @@ export class CarouselListComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private loading() {
|
private loading() {
|
||||||
this.loadingFlag = true;
|
this.loadingFlag.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private finishLoading() {
|
private finishLoading() {
|
||||||
this.loadingFlag = false;
|
this.loadingFlag.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,20 +22,23 @@
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.RecentlyRequestedTab' | translate }}</h2>
|
<h2>{{ 'Discovery.RecentlyRequestedTab' | translate }}</h2>
|
||||||
<div class="row loading-container">
|
<div class="row loading-container">
|
||||||
<div class="col-2" *ngFor="let item of [1,2,3,4,5]">
|
@for (item of [1,2,3,4,5]; track item) {
|
||||||
|
<div class="col-2">
|
||||||
<p-skeleton width="100%" height="270px"></p-skeleton>
|
<p-skeleton width="100%" height="270px"></p-skeleton>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (showSeasonal()) {
|
||||||
@defer (on viewport; prefetch on idle) {
|
@defer (on viewport; prefetch on idle) {
|
||||||
<div class="section" [hidden]="!showSeasonal">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.SeasonalTab' | translate }}</h2>
|
<h2>{{ 'Discovery.SeasonalTab' | translate }}</h2>
|
||||||
<div>
|
<div>
|
||||||
<carousel-list
|
<carousel-list
|
||||||
[id]="'seasonal'"
|
[id]="'seasonal'"
|
||||||
[isAdmin]="isAdmin"
|
[isAdmin]="isAdmin()"
|
||||||
[discoverType]="DiscoverType.Seasonal"
|
[discoverType]="DiscoverType.Seasonal"
|
||||||
(movieCount)="setSeasonalMovieCount($event)"
|
(movieCount)="setSeasonalMovieCount($event)"
|
||||||
></carousel-list>
|
></carousel-list>
|
||||||
|
@ -45,27 +48,32 @@
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.SeasonalTab' | translate }}</h2>
|
<h2>{{ 'Discovery.SeasonalTab' | translate }}</h2>
|
||||||
<div class="row loading-container">
|
<div class="row loading-container">
|
||||||
<div class="col-2" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
@for (item of [1,2,3,4,5,6,7,8,9,10]; track item) {
|
||||||
|
<div class="col-2">
|
||||||
<p-skeleton width="100%" height="270px"></p-skeleton>
|
<p-skeleton width="100%" height="270px"></p-skeleton>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@defer (on viewport; prefetch on idle) {
|
@defer (on viewport; prefetch on idle) {
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.PopularTab' | translate }}</h2>
|
<h2>{{ 'Discovery.PopularTab' | translate }}</h2>
|
||||||
<div>
|
<div>
|
||||||
<carousel-list [id]="'popular'" [isAdmin]="isAdmin" [discoverType]="DiscoverType.Popular"></carousel-list>
|
<carousel-list [id]="'popular'" [isAdmin]="isAdmin()" [discoverType]="DiscoverType.Popular"></carousel-list>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} @placeholder(minimum 300) {
|
} @placeholder(minimum 300) {
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.PopularTab' | translate }}</h2>
|
<h2>{{ 'Discovery.PopularTab' | translate }}</h2>
|
||||||
<div class="row loading-container">
|
<div class="row loading-container">
|
||||||
<div class="col-2" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
@for (item of [1,2,3,4,5,6,7,8,9,10]; track item) {
|
||||||
|
<div class="col-2">
|
||||||
<p-skeleton width="100%" height="270px"></p-skeleton>
|
<p-skeleton width="100%" height="270px"></p-skeleton>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -74,16 +82,18 @@
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.TrendingTab' | translate }}</h2>
|
<h2>{{ 'Discovery.TrendingTab' | translate }}</h2>
|
||||||
<div>
|
<div>
|
||||||
<carousel-list [id]="'trending'" [isAdmin]="isAdmin" [discoverType]="DiscoverType.Trending"></carousel-list>
|
<carousel-list [id]="'trending'" [isAdmin]="isAdmin()" [discoverType]="DiscoverType.Trending"></carousel-list>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} @placeholder(minimum 300) {
|
} @placeholder(minimum 300) {
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.TrendingTab' | translate }}</h2>
|
<h2>{{ 'Discovery.TrendingTab' | translate }}</h2>
|
||||||
<div class="row loading-container">
|
<div class="row loading-container">
|
||||||
<div class="col-2" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
@for (item of [1,2,3,4,5,6,7,8,9,10]; track item) {
|
||||||
|
<div class="col-2">
|
||||||
<p-skeleton width="100%" height="270px"></p-skeleton>
|
<p-skeleton width="100%" height="270px"></p-skeleton>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -92,16 +102,18 @@
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.UpcomingTab' | translate }}</h2>
|
<h2>{{ 'Discovery.UpcomingTab' | translate }}</h2>
|
||||||
<div>
|
<div>
|
||||||
<carousel-list [id]="'upcoming'" [isAdmin]="isAdmin" [discoverType]="DiscoverType.Upcoming"></carousel-list>
|
<carousel-list [id]="'upcoming'" [isAdmin]="isAdmin()" [discoverType]="DiscoverType.Upcoming"></carousel-list>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
} @placeholder(minimum 300) {
|
} @placeholder(minimum 300) {
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<h2>{{ 'Discovery.UpcomingTab' | translate }}</h2>
|
<h2>{{ 'Discovery.UpcomingTab' | translate }}</h2>
|
||||||
<div class="row loading-container">
|
<div class="row loading-container">
|
||||||
<div class="col-2" *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
|
@for (item of [1,2,3,4,5,6,7,8,9,10]; track item) {
|
||||||
|
<div class="col-2">
|
||||||
<p-skeleton width="100%" height="270px"></p-skeleton>
|
<p-skeleton width="100%" height="270px"></p-skeleton>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, computed, inject, signal, ChangeDetectionStrategy } from "@angular/core";
|
||||||
|
|
||||||
import { AuthService } from "../../../auth/auth.service";
|
import { AuthService } from "../../../auth/auth.service";
|
||||||
import { DiscoverType } from "../carousel-list/carousel-list.component";
|
import { DiscoverType } from "../carousel-list/carousel-list.component";
|
||||||
|
@ -7,23 +7,28 @@ import { DiscoverType } from "../carousel-list/carousel-list.component";
|
||||||
standalone: false,
|
standalone: false,
|
||||||
templateUrl: "./discover.component.html",
|
templateUrl: "./discover.component.html",
|
||||||
styleUrls: ["./discover.component.scss"],
|
styleUrls: ["./discover.component.scss"],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class DiscoverComponent implements OnInit {
|
export class DiscoverComponent {
|
||||||
|
// Services using inject() function
|
||||||
|
private authService = inject(AuthService);
|
||||||
|
|
||||||
|
// Public constants
|
||||||
public DiscoverType = DiscoverType;
|
public DiscoverType = DiscoverType;
|
||||||
public isAdmin: boolean;
|
|
||||||
public showSeasonal: boolean;
|
|
||||||
|
|
||||||
constructor(private authService: AuthService) { }
|
// State using signals
|
||||||
|
public isAdmin = signal<boolean>(false);
|
||||||
|
public seasonalMovieCount = signal<number>(0);
|
||||||
|
|
||||||
public ngOnInit(): void {
|
// Computed properties
|
||||||
this.isAdmin = this.authService.isAdmin();
|
public showSeasonal = computed(() => this.seasonalMovieCount() > 0);
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// Initialize admin status
|
||||||
|
this.isAdmin.set(this.authService.isAdmin());
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSeasonalMovieCount(count: number) {
|
public setSeasonalMovieCount(count: number): void {
|
||||||
if (count > 0) {
|
this.seasonalMovieCount.set(count);
|
||||||
this.showSeasonal = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue