X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=client%2Fsrc%2Fapp%2Fshared%2Fshared-video-miniature%2Fabstract-video-list.ts;h=3e84589cd145ea7ce728ca7a147fe0a4e98b4229;hb=5bcbcbe338ef5a1ed14f084311d013fbb25dabcf;hp=0ef8426528a6bf6c1abf477f84963efed2bd0cc9;hpb=67ed6552b831df66713bac9e672738796128d33f;p=github%2FChocobozzz%2FPeerTube.git diff --git a/client/src/app/shared/shared-video-miniature/abstract-video-list.ts b/client/src/app/shared/shared-video-miniature/abstract-video-list.ts index 0ef842652..3e84589cd 100644 --- a/client/src/app/shared/shared-video-miniature/abstract-video-list.ts +++ b/client/src/app/shared/shared-video-miniature/abstract-video-list.ts @@ -1,6 +1,16 @@ import { fromEvent, Observable, Subject, Subscription } from 'rxjs' import { debounceTime, switchMap, tap } from 'rxjs/operators' -import { OnDestroy, OnInit } from '@angular/core' +import { + AfterContentInit, + ComponentFactoryResolver, + Directive, + Injector, + OnDestroy, + OnInit, + Type, + ViewChild, + ViewContainerRef +} from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { AuthService, @@ -14,23 +24,31 @@ import { } from '@app/core' import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' import { GlobalIconName } from '@app/shared/shared-icons' -import { I18n } from '@ngx-translate/i18n-polyfill' -import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' -import { ServerConfig, VideoSortField } from '@shared/models' +import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@shared/core-utils/miscs/date' +import { ServerConfig, UserRight, VideoFilter, VideoSortField } from '@shared/models' import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' import { Syndication, Video } from '../shared-main' import { MiniatureDisplayOptions, OwnerDisplayType } from './video-miniature.component' +import { GenericHeaderComponent, VideoListHeaderComponent } from './video-list-header.component' enum GroupDate { UNKNOWN = 0, TODAY = 1, YESTERDAY = 2, - LAST_WEEK = 3, - LAST_MONTH = 4, - OLDER = 5 + THIS_WEEK = 3, + THIS_MONTH = 4, + LAST_MONTH = 5, + OLDER = 6 } -export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableForReuseHook { +@Directive() +// tslint:disable-next-line: directive-class-suffix +export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterContentInit, DisableForReuseHook { + @ViewChild('videoListHeader', { static: true, read: ViewContainerRef }) videoListHeader: ViewContainerRef + + HeaderComponent: Type = VideoListHeaderComponent + headerComponentInjector: Injector + pagination: ComponentPaginationLight = { currentPage: 1, itemsPerPage: 25 @@ -68,9 +86,12 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor } actions: { - routerLink: string iconName: GlobalIconName label: string + justIcon?: boolean + routerLink?: string + href?: string + click?: (e: Event) => void }[] = [] onDataSubject = new Subject() @@ -87,7 +108,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor protected abstract screenService: ScreenService protected abstract storageService: LocalStorageService protected abstract router: Router - protected abstract i18n: I18n + protected abstract cfr: ComponentFactoryResolver abstract titlePage: string private resizeSubscription: Subscription @@ -109,11 +130,12 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor this.groupedDateLabels = { [GroupDate.UNKNOWN]: null, - [GroupDate.TODAY]: this.i18n('Today'), - [GroupDate.YESTERDAY]: this.i18n('Yesterday'), - [GroupDate.LAST_WEEK]: this.i18n('Last week'), - [GroupDate.LAST_MONTH]: this.i18n('Last month'), - [GroupDate.OLDER]: this.i18n('Older') + [GroupDate.TODAY]: $localize`Today`, + [GroupDate.YESTERDAY]: $localize`Yesterday`, + [GroupDate.THIS_WEEK]: $localize`This week`, + [GroupDate.THIS_MONTH]: $localize`This month`, + [GroupDate.LAST_MONTH]: $localize`Last month`, + [GroupDate.OLDER]: $localize`Older` } // Subscribe to route changes @@ -148,6 +170,13 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor if (this.resizeSubscription) this.resizeSubscription.unsubscribe() } + ngAfterContentInit () { + if (this.videoListHeader) { + // some components don't use the header: they use their own template, like my-history.component.html + this.setHeader.apply(this, [ this.HeaderComponent, this.headerComponentInjector ]) + } + } + disableForReuse () { this.disabled = true } @@ -190,7 +219,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor }, error => { - const message = this.i18n('Cannot load more videos. Try again later.') + const message = $localize`Cannot load more videos. Try again later.` console.error(message, { error }) this.notifier.error(message) @@ -203,10 +232,6 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor this.loadMoreVideos(true) } - toggleModerationDisplay () { - throw new Error('toggleModerationDisplay is not implemented') - } - removeVideoFromArray (video: Video) { this.videos = this.videos.filter(v => v.id !== video.id) } @@ -214,46 +239,48 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor buildGroupedDateLabels () { let currentGroupedDate: GroupDate = GroupDate.UNKNOWN - for (const video of this.videos) { - const publishedDate = video.publishedAt - - if (currentGroupedDate <= GroupDate.TODAY && isToday(publishedDate)) { - if (currentGroupedDate === GroupDate.TODAY) continue - - currentGroupedDate = GroupDate.TODAY - this.groupedDates[ video.id ] = currentGroupedDate - continue - } - - if (currentGroupedDate <= GroupDate.YESTERDAY && isYesterday(publishedDate)) { - if (currentGroupedDate === GroupDate.YESTERDAY) continue - - currentGroupedDate = GroupDate.YESTERDAY - this.groupedDates[ video.id ] = currentGroupedDate - continue + const periods = [ + { + value: GroupDate.TODAY, + validator: (d: Date) => isToday(d) + }, + { + value: GroupDate.YESTERDAY, + validator: (d: Date) => isYesterday(d) + }, + { + value: GroupDate.THIS_WEEK, + validator: (d: Date) => isLastWeek(d) + }, + { + value: GroupDate.THIS_MONTH, + validator: (d: Date) => isThisMonth(d) + }, + { + value: GroupDate.LAST_MONTH, + validator: (d: Date) => isLastMonth(d) + }, + { + value: GroupDate.OLDER, + validator: () => true } + ] - if (currentGroupedDate <= GroupDate.LAST_WEEK && isLastWeek(publishedDate)) { - if (currentGroupedDate === GroupDate.LAST_WEEK) continue - - currentGroupedDate = GroupDate.LAST_WEEK - this.groupedDates[ video.id ] = currentGroupedDate - continue - } + for (const video of this.videos) { + const publishedDate = video.publishedAt - if (currentGroupedDate <= GroupDate.LAST_MONTH && isLastMonth(publishedDate)) { - if (currentGroupedDate === GroupDate.LAST_MONTH) continue + for (let i = 0; i < periods.length; i++) { + const period = periods[i] - currentGroupedDate = GroupDate.LAST_MONTH - this.groupedDates[ video.id ] = currentGroupedDate - continue - } + if (currentGroupedDate <= period.value && period.validator(publishedDate)) { - if (currentGroupedDate <= GroupDate.OLDER) { - if (currentGroupedDate === GroupDate.OLDER) continue + if (currentGroupedDate !== period.value) { + currentGroupedDate = period.value + this.groupedDates[ video.id ] = currentGroupedDate + } - currentGroupedDate = GroupDate.OLDER - this.groupedDates[ video.id ] = currentGroupedDate + break + } } } } @@ -264,6 +291,30 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor return this.groupedDateLabels[this.groupedDates[video.id]] } + toggleModerationDisplay () { + throw new Error('toggleModerationDisplay ' + $localize`function is not implemented`) + } + + setHeader ( + t: Type = this.HeaderComponent, + i: Injector = this.headerComponentInjector + ) { + const injector = i || Injector.create({ + providers: [{ + provide: 'data', + useValue: { + titlePage: this.titlePage, + titleTooltip: this.titleTooltip + } + }] + }) + const viewContainerRef = this.videoListHeader + viewContainerRef.clear() + + const componentFactory = this.cfr.resolveComponentFactory(t) + viewContainerRef.createComponent(componentFactory, 0, injector) + } + // On videos hook for children that want to do something protected onMoreVideos () { /* empty */ } @@ -273,6 +324,28 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor this.angularState = routeParams[ 'a-state' ] } + protected buildLocalFilter (existing: VideoFilter, base: VideoFilter) { + if (base === 'local') { + return existing === 'local' + ? 'all-local' as 'all-local' + : 'local' as 'local' + } + + return existing === 'all' + ? null + : 'all' + } + + protected enableAllFilterIfPossible () { + if (!this.authService.isLoggedIn()) return + + this.authService.userInformationLoaded + .subscribe(() => { + const user = this.authService.getUser() + this.displayModerationBlock = user.hasRight(UserRight.SEE_ALL_VIDEOS) + }) + } + private calcPageSizes () { if (this.screenService.isInMobileView()) { this.pagination.itemsPerPage = 5