123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- import { Component, OnDestroy, OnInit } from '@angular/core'
- import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'
- import { ComponentPaginationLight, DisableForReuseHook, MetaService, RedirectService, ServerService } from '@app/core'
- import { HooksService } from '@app/core/plugins/hooks.service'
- import { VideoService } from '@app/shared/shared-main'
- import { VideoFilters, VideoFilterScope } from '@app/shared/shared-video-miniature/video-filters.model'
- import { ClientFilterHookName, VideoSortField } from '@shared/models'
- import { Subscription } from 'rxjs'
- export type VideosListCommonPageRouteData = {
- sort: VideoSortField
- scope: VideoFilterScope
- hookParams: ClientFilterHookName
- hookResult: ClientFilterHookName
- }
- @Component({
- templateUrl: './videos-list-common-page.component.html'
- })
- export class VideosListCommonPageComponent implements OnInit, OnDestroy, DisableForReuseHook {
- getVideosObservableFunction = this.getVideosObservable.bind(this)
- getSyndicationItemsFunction = this.getSyndicationItems.bind(this)
- baseRouteBuilderFunction = this.baseRouteBuilder.bind(this)
- title: string
- titleTooltip: string
- groupByDate: boolean
- defaultSort: VideoSortField
- defaultScope: VideoFilterScope
- hookParams: ClientFilterHookName
- hookResult: ClientFilterHookName
- loadUserVideoPreferences = true
- displayFilters = true
- disabled = false
- private trendingDays: number
- private routeSub: Subscription
- constructor (
- private server: ServerService,
- private route: ActivatedRoute,
- private videoService: VideoService,
- private hooks: HooksService,
- private meta: MetaService,
- private redirectService: RedirectService
- ) {
- }
- ngOnInit () {
- this.trendingDays = this.server.getHTMLConfig().trending.videos.intervalDays
- this.routeSub = this.route.params.subscribe(params => {
- this.update(params['page'])
- })
- }
- ngOnDestroy () {
- if (this.routeSub) this.routeSub.unsubscribe()
- }
- getVideosObservable (pagination: ComponentPaginationLight, filters: VideoFilters) {
- const params = {
- ...filters.toVideosAPIObject(),
- videoPagination: pagination,
- skipCount: true
- }
- return this.hooks.wrapObsFun(
- this.videoService.getVideos.bind(this.videoService),
- params,
- 'common',
- this.hookParams,
- this.hookResult
- )
- }
- getSyndicationItems (filters: VideoFilters) {
- const result = filters.toVideosAPIObject()
- return this.videoService.getVideoFeedUrls(result.sort, result.isLocal)
- }
- onFiltersChanged (filters: VideoFilters) {
- this.buildTitle(filters.scope, filters.sort)
- this.updateGroupByDate(filters.sort)
- }
- baseRouteBuilder (filters: VideoFilters) {
- const sanitizedSort = this.getSanitizedSort(filters.sort)
- let suffix: string
- if (filters.scope === 'local') suffix = 'local'
- else if (sanitizedSort === 'publishedAt') suffix = 'recently-added'
- else suffix = 'trending'
- return [ '/videos', suffix ]
- }
- disableForReuse () {
- this.disabled = true
- }
- enabledForReuse () {
- this.disabled = false
- }
- update (page: string) {
- const data = this.getData(page)
- this.hookParams = data.hookParams
- this.hookResult = data.hookResult
- this.defaultSort = data.sort
- this.defaultScope = data.scope
- this.buildTitle()
- this.updateGroupByDate(this.defaultSort)
- this.meta.setTitle(this.title)
- }
- private getData (page: string) {
- if (page === 'trending') return this.generateTrendingData(this.route.snapshot)
- if (page === 'local') return this.generateLocalData()
- return this.generateRecentlyAddedData()
- }
- private generateRecentlyAddedData (): VideosListCommonPageRouteData {
- return {
- sort: '-publishedAt',
- scope: 'federated',
- hookParams: 'filter:api.recently-added-videos.videos.list.params',
- hookResult: 'filter:api.recently-added-videos.videos.list.result'
- }
- }
- private generateLocalData (): VideosListCommonPageRouteData {
- return {
- sort: '-publishedAt' as VideoSortField,
- scope: 'local',
- hookParams: 'filter:api.local-videos.videos.list.params',
- hookResult: 'filter:api.local-videos.videos.list.result'
- }
- }
- private generateTrendingData (route: ActivatedRouteSnapshot): VideosListCommonPageRouteData {
- const sort = route.queryParams['sort'] ?? this.parseTrendingAlgorithm(this.redirectService.getDefaultTrendingAlgorithm())
- return {
- sort,
- scope: 'federated',
- hookParams: 'filter:api.trending-videos.videos.list.params',
- hookResult: 'filter:api.trending-videos.videos.list.result'
- }
- }
- private parseTrendingAlgorithm (algorithm: string): VideoSortField {
- switch (algorithm) {
- case 'most-viewed':
- return '-trending'
- case 'most-liked':
- return '-likes'
- // We'll automatically apply "best" sort if using "hot" sort with a logged user
- case 'best':
- return '-hot'
- default:
- return '-' + algorithm as VideoSortField
- }
- }
- private updateGroupByDate (sort: VideoSortField) {
- this.groupByDate = sort === '-publishedAt' || sort === 'publishedAt'
- }
- private buildTitle (scope: VideoFilterScope = this.defaultScope, sort: VideoSortField = this.defaultSort) {
- const sanitizedSort = this.getSanitizedSort(sort)
- if (scope === 'local') {
- this.title = $localize`Local videos`
- this.titleTooltip = $localize`Only videos uploaded on this instance are displayed`
- return
- }
- if (sanitizedSort === 'publishedAt') {
- this.title = $localize`Recently added`
- this.titleTooltip = undefined
- return
- }
- if ([ 'hot', 'trending', 'likes', 'views' ].includes(sanitizedSort)) {
- this.title = $localize`Trending`
- if (sanitizedSort === 'hot') this.titleTooltip = $localize`Videos with the most interactions for recent videos`
- if (sanitizedSort === 'likes') this.titleTooltip = $localize`Videos that have the most likes`
- if (sanitizedSort === 'views') this.titleTooltip = undefined
- if (sanitizedSort === 'trending') {
- if (this.trendingDays === 1) this.titleTooltip = $localize`Videos with the most views during the last 24 hours`
- else this.titleTooltip = $localize`Videos with the most views during the last ${this.trendingDays} days`
- }
- return
- }
- }
- private getSanitizedSort (sort: VideoSortField) {
- return sort.replace(/^-/, '') as VideoSortField
- }
- }
|