From 111fdc267b36201cf1be1fdf91017005102b4a5e Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 11 Mar 2020 16:41:38 +0100 Subject: [PATCH] Handle overview pagination in client --- client/src/app/core/server/server.service.ts | 24 ++++--- .../app/menu/language-chooser.component.ts | 1 + client/src/app/menu/menu.component.ts | 50 +++++++++----- .../app/shared/overview/overview.service.ts | 9 ++- .../video-list/video-overview.component.html | 55 ++++++++------- .../video-list/video-overview.component.ts | 67 +++++++++++++------ 6 files changed, 135 insertions(+), 71 deletions(-) diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index e015d0e14..da7832b32 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts @@ -263,17 +263,19 @@ export class ServerService { .pipe(map(data => ({ data, translations }))) }), map(({ data, translations }) => { - const hashToPopulate: VideoConstant[] = [] - - Object.keys(data) - .forEach(dataKey => { - const label = data[ dataKey ] - - hashToPopulate.push({ - id: (attributeName === 'languages' ? dataKey : parseInt(dataKey, 10)) as T, - label: peertubeTranslate(label, translations) - }) - }) + const hashToPopulate: VideoConstant[] = Object.keys(data) + .map(dataKey => { + const label = data[ dataKey ] + + const id = attributeName === 'languages' + ? dataKey as T + : parseInt(dataKey, 10) as T + + return { + id, + label: peertubeTranslate(label, translations) + } + }) if (sort === true) sortBy(hashToPopulate, 'label') diff --git a/client/src/app/menu/language-chooser.component.ts b/client/src/app/menu/language-chooser.component.ts index fb74cdf19..9bc934ad4 100644 --- a/client/src/app/menu/language-chooser.component.ts +++ b/client/src/app/menu/language-chooser.component.ts @@ -36,6 +36,7 @@ export class LanguageChooserComponent { getCurrentLanguage () { const english = 'English' const locale = isOnDevLocale() ? getDevLocale() : getCompleteLocale(this.localeId) + if (locale) return I18N_LOCALES[locale] || english return english } diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts index ce209457c..37702e975 100644 --- a/client/src/app/menu/menu.component.ts +++ b/client/src/app/menu/menu.component.ts @@ -23,8 +23,10 @@ export class MenuComponent implements OnInit { userHasAdminAccess = false helpVisible = false - languages: VideoConstant[] = [] + videoLanguages: string[] = [] + + private languages: VideoConstant[] = [] private serverConfig: ServerConfig private routesPerRight: { [ role in UserRight ]?: string } = { [UserRight.MANAGE_USERS]: '/admin/users', @@ -71,30 +73,32 @@ export class MenuComponent implements OnInit { } ) - this.hotkeysService.cheatSheetToggle.subscribe(isOpen => this.helpVisible = isOpen) + this.hotkeysService.cheatSheetToggle + .subscribe(isOpen => this.helpVisible = isOpen) + + this.serverService.getVideoLanguages() + .subscribe(languages => { + this.languages = languages - this.serverService.getVideoLanguages().subscribe(languages => this.languages = languages) + this.authService.userInformationLoaded + .subscribe(() => this.buildUserLanguages()) + }) } get language () { return this.languageChooserModal.getCurrentLanguage() } - get videoLanguages (): string[] { - if (!this.user) return - if (!this.user.videoLanguages) return [this.i18n('any language')] - return this.user.videoLanguages - .map(locale => this.langForLocale(locale)) - .map(value => value === undefined ? '?' : value) - } - get nsfwPolicy () { if (!this.user) return + switch (this.user.nsfwPolicy) { case 'do_not_list': return this.i18n('hide') + case 'blur': return this.i18n('blur') + case 'display': return this.i18n('display') } @@ -156,13 +160,29 @@ export class MenuComponent implements OnInit { toggleUseP2P () { if (!this.user) return this.user.webTorrentEnabled = !this.user.webTorrentEnabled - this.userService.updateMyProfile({ - webTorrentEnabled: this.user.webTorrentEnabled - }).subscribe(() => this.authService.refreshUserInformation()) + + this.userService.updateMyProfile({ webTorrentEnabled: this.user.webTorrentEnabled }) + .subscribe(() => this.authService.refreshUserInformation()) } langForLocale (localeId: string) { - return this.languages.find(lang => lang.id = localeId).label + return this.languages.find(lang => lang.id === localeId).label + } + + private buildUserLanguages () { + if (!this.user) { + this.videoLanguages = [] + return + } + + if (!this.user.videoLanguages) { + this.videoLanguages = [ this.i18n('any language') ] + return + } + + this.videoLanguages = this.user.videoLanguages + .map(locale => this.langForLocale(locale)) + .map(value => value === undefined ? '?' : value) } private computeIsUserHasAdminAccess () { diff --git a/client/src/app/shared/overview/overview.service.ts b/client/src/app/shared/overview/overview.service.ts index 79cb781f7..6d8af8052 100644 --- a/client/src/app/shared/overview/overview.service.ts +++ b/client/src/app/shared/overview/overview.service.ts @@ -1,5 +1,5 @@ import { catchError, map, switchMap, tap } from 'rxjs/operators' -import { HttpClient } from '@angular/common/http' +import { HttpClient, HttpParams } from '@angular/common/http' import { Injectable } from '@angular/core' import { forkJoin, Observable, of } from 'rxjs' import { VideosOverview as VideosOverviewServer, peertubeTranslate } from '../../../../../shared/models' @@ -21,9 +21,12 @@ export class OverviewService { private serverService: ServerService ) {} - getVideosOverview (): Observable { + getVideosOverview (page: number): Observable { + let params = new HttpParams() + params = params.append('page', page + '') + return this.authHttp - .get(OverviewService.BASE_OVERVIEW_URL + 'videos') + .get(OverviewService.BASE_OVERVIEW_URL + 'videos', { params }) .pipe( switchMap(serverVideosOverview => this.updateVideosOverview(serverVideosOverview)), catchError(err => this.restExtractor.handleError(err)) diff --git a/client/src/app/videos/video-list/video-overview.component.html b/client/src/app/videos/video-list/video-overview.component.html index 5fe1f5c80..84999cfb2 100644 --- a/client/src/app/videos/video-list/video-overview.component.html +++ b/client/src/app/videos/video-list/video-overview.component.html @@ -2,35 +2,44 @@
No results.
- diff --git a/client/src/app/videos/video-list/video-overview.component.ts b/client/src/app/videos/video-list/video-overview.component.ts index 4fee92d54..101073949 100644 --- a/client/src/app/videos/video-list/video-overview.component.ts +++ b/client/src/app/videos/video-list/video-overview.component.ts @@ -5,6 +5,7 @@ import { VideosOverview } from '@app/shared/overview/videos-overview.model' import { OverviewService } from '@app/shared/overview' import { Video } from '@app/shared/video/video.model' import { ScreenService } from '@app/shared/misc/screen.service' +import { Subject } from 'rxjs' @Component({ selector: 'my-video-overview', @@ -12,13 +13,17 @@ import { ScreenService } from '@app/shared/misc/screen.service' styleUrls: [ './video-overview.component.scss' ] }) export class VideoOverviewComponent implements OnInit { - overview: VideosOverview = { - categories: [], - channels: [], - tags: [] - } + onDataSubject = new Subject() + + overviews: VideosOverview[] = [] notResults = false + private loaded = false + private currentPage = 1 + private maxPage = 20 + private lastWasEmpty = false + private isLoading = false + constructor ( private i18n: I18n, private notifier: Notifier, @@ -32,20 +37,7 @@ export class VideoOverviewComponent implements OnInit { } ngOnInit () { - this.overviewService.getVideosOverview() - .subscribe( - overview => { - this.overview = overview - - if ( - this.overview.categories.length === 0 && - this.overview.channels.length === 0 && - this.overview.tags.length === 0 - ) this.notResults = true - }, - - err => this.notifier.error(err.message) - ) + this.loadMoreResults() } buildVideoChannelBy (object: { videos: Video[] }) { @@ -61,4 +53,41 @@ export class VideoOverviewComponent implements OnInit { return videos.slice(0, numberOfVideos * 2) } + + onNearOfBottom () { + if (this.currentPage >= this.maxPage) return + if (this.lastWasEmpty) return + if (this.isLoading) return + + this.currentPage++ + this.loadMoreResults() + } + + private loadMoreResults () { + this.isLoading = true + + this.overviewService.getVideosOverview(this.currentPage) + .subscribe( + overview => { + this.isLoading = false + + if (overview.tags.length === 0 && overview.channels.length === 0 && overview.categories.length === 0) { + this.lastWasEmpty = true + if (this.loaded === false) this.notResults = true + + return + } + + this.loaded = true + this.onDataSubject.next(overview) + + this.overviews.push(overview) + }, + + err => { + this.notifier.error(err.message) + this.isLoading = false + } + ) + } } -- 2.25.1