]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/+videos/video-list/videos-list-common-page.component.ts
Support ICU in TS components
[github/Chocobozzz/PeerTube.git] / client / src / app / +videos / video-list / videos-list-common-page.component.ts
CommitLineData
dd24f1bb
C
1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'
3import { ComponentPaginationLight, DisableForReuseHook, MetaService, RedirectService, ServerService } from '@app/core'
4import { HooksService } from '@app/core/plugins/hooks.service'
5import { VideoService } from '@app/shared/shared-main'
6import { VideoFilters, VideoFilterScope } from '@app/shared/shared-video-miniature/video-filters.model'
7import { ClientFilterHookName, VideoSortField } from '@shared/models'
8import { Subscription } from 'rxjs'
9
10export type VideosListCommonPageRouteData = {
11 sort: VideoSortField
12
13 scope: VideoFilterScope
14 hookParams: ClientFilterHookName
15 hookResult: ClientFilterHookName
16}
17
18@Component({
19 templateUrl: './videos-list-common-page.component.html'
20})
21export class VideosListCommonPageComponent implements OnInit, OnDestroy, DisableForReuseHook {
22 getVideosObservableFunction = this.getVideosObservable.bind(this)
23 getSyndicationItemsFunction = this.getSyndicationItems.bind(this)
24 baseRouteBuilderFunction = this.baseRouteBuilder.bind(this)
25
26 title: string
27 titleTooltip: string
28
29 groupByDate: boolean
30
31 defaultSort: VideoSortField
32 defaultScope: VideoFilterScope
33
34 hookParams: ClientFilterHookName
35 hookResult: ClientFilterHookName
36
37 loadUserVideoPreferences = true
38
39 displayFilters = true
40
41 disabled = false
42
43 private trendingDays: number
44 private routeSub: Subscription
45
46 constructor (
47 private server: ServerService,
48 private route: ActivatedRoute,
49 private videoService: VideoService,
50 private hooks: HooksService,
51 private meta: MetaService,
52 private redirectService: RedirectService
53 ) {
54 }
55
56 ngOnInit () {
57 this.trendingDays = this.server.getHTMLConfig().trending.videos.intervalDays
58
59 this.routeSub = this.route.params.subscribe(params => {
60 this.update(params['page'])
61 })
62 }
63
64 ngOnDestroy () {
65 if (this.routeSub) this.routeSub.unsubscribe()
66 }
67
68 getVideosObservable (pagination: ComponentPaginationLight, filters: VideoFilters) {
69 const params = {
70 ...filters.toVideosAPIObject(),
71
72 videoPagination: pagination,
73 skipCount: true
74 }
75
76 return this.hooks.wrapObsFun(
77 this.videoService.getVideos.bind(this.videoService),
78 params,
79 'common',
80 this.hookParams,
81 this.hookResult
82 )
83 }
84
85 getSyndicationItems (filters: VideoFilters) {
86 const result = filters.toVideosAPIObject()
87
2760b454 88 return this.videoService.getVideoFeedUrls(result.sort, result.isLocal)
dd24f1bb
C
89 }
90
91 onFiltersChanged (filters: VideoFilters) {
92 this.buildTitle(filters.scope, filters.sort)
93 this.updateGroupByDate(filters.sort)
94 }
95
96 baseRouteBuilder (filters: VideoFilters) {
97 const sanitizedSort = this.getSanitizedSort(filters.sort)
98
99 let suffix: string
100
101 if (filters.scope === 'local') suffix = 'local'
102 else if (sanitizedSort === 'publishedAt') suffix = 'recently-added'
103 else suffix = 'trending'
104
105 return [ '/videos', suffix ]
106 }
107
108 disableForReuse () {
109 this.disabled = true
110 }
111
112 enabledForReuse () {
113 this.disabled = false
114 }
115
116 update (page: string) {
117 const data = this.getData(page)
118
119 this.hookParams = data.hookParams
120 this.hookResult = data.hookResult
121
122 this.defaultSort = data.sort
123 this.defaultScope = data.scope
124
125 this.buildTitle()
126 this.updateGroupByDate(this.defaultSort)
127
128 this.meta.setTitle(this.title)
129 }
130
131 private getData (page: string) {
132 if (page === 'trending') return this.generateTrendingData(this.route.snapshot)
133
134 if (page === 'local') return this.generateLocalData()
135
136 return this.generateRecentlyAddedData()
137 }
138
139 private generateRecentlyAddedData (): VideosListCommonPageRouteData {
140 return {
141 sort: '-publishedAt',
142 scope: 'federated',
143 hookParams: 'filter:api.recently-added-videos.videos.list.params',
144 hookResult: 'filter:api.recently-added-videos.videos.list.result'
145 }
146 }
147
148 private generateLocalData (): VideosListCommonPageRouteData {
149 return {
150 sort: '-publishedAt' as VideoSortField,
151 scope: 'local',
152 hookParams: 'filter:api.local-videos.videos.list.params',
153 hookResult: 'filter:api.local-videos.videos.list.result'
154 }
155 }
156
157 private generateTrendingData (route: ActivatedRouteSnapshot): VideosListCommonPageRouteData {
158 const sort = route.queryParams['sort'] ?? this.parseTrendingAlgorithm(this.redirectService.getDefaultTrendingAlgorithm())
159
160 return {
161 sort,
162 scope: 'federated',
163 hookParams: 'filter:api.trending-videos.videos.list.params',
164 hookResult: 'filter:api.trending-videos.videos.list.result'
165 }
166 }
167
168 private parseTrendingAlgorithm (algorithm: string): VideoSortField {
169 switch (algorithm) {
170 case 'most-viewed':
171 return '-trending'
172
173 case 'most-liked':
174 return '-likes'
175
010382b6
C
176 // We'll automatically apply "best" sort if using "hot" sort with a logged user
177 case 'best':
178 return '-hot'
179
dd24f1bb
C
180 default:
181 return '-' + algorithm as VideoSortField
182 }
183 }
184
185 private updateGroupByDate (sort: VideoSortField) {
186 this.groupByDate = sort === '-publishedAt' || sort === 'publishedAt'
187 }
188
189 private buildTitle (scope: VideoFilterScope = this.defaultScope, sort: VideoSortField = this.defaultSort) {
190 const sanitizedSort = this.getSanitizedSort(sort)
191
192 if (scope === 'local') {
193 this.title = $localize`Local videos`
194 this.titleTooltip = $localize`Only videos uploaded on this instance are displayed`
195 return
196 }
197
198 if (sanitizedSort === 'publishedAt') {
199 this.title = $localize`Recently added`
200 this.titleTooltip = undefined
201 return
202 }
203
db19581f 204 if ([ 'hot', 'trending', 'likes', 'views' ].includes(sanitizedSort)) {
dd24f1bb
C
205 this.title = $localize`Trending`
206
eaa52952
C
207 if (sanitizedSort === 'hot') {
208 this.titleTooltip = $localize`Videos with the most interactions for recent videos`
209 return
210 }
211
212 if (sanitizedSort === 'likes') {
213 this.titleTooltip = $localize`Videos that have the most likes`
214 return
215 }
216
217 if (sanitizedSort === 'views') {
218 this.titleTooltip = undefined
219 return
220 }
dd24f1bb
C
221
222 if (sanitizedSort === 'trending') {
eaa52952
C
223 if (this.trendingDays === 1) {
224 this.titleTooltip = $localize`Videos with the most views during the last 24 hours`
225 return
226 }
227
228 this.titleTooltip = $localize`Videos with the most views during the last ${this.trendingDays} days`
dd24f1bb
C
229 }
230
231 return
232 }
233 }
234
235 private getSanitizedSort (sort: VideoSortField) {
236 return sort.replace(/^-/, '') as VideoSortField
237 }
238}