]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-video-miniature/video-miniature.component.ts
Update build steps for localization
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-video-miniature / video-miniature.component.ts
1 import { switchMap } from 'rxjs/operators'
2 import {
3 ChangeDetectionStrategy,
4 ChangeDetectorRef,
5 Component,
6 EventEmitter,
7 Inject,
8 Input,
9 LOCALE_ID,
10 OnInit,
11 Output
12 } from '@angular/core'
13 import { AuthService, ScreenService, ServerService, User } from '@app/core'
14 import { I18n } from '@ngx-translate/i18n-polyfill'
15 import { ServerConfig, VideoPlaylistType, VideoPrivacy, VideoState } from '@shared/models'
16 import { Video } from '../shared-main'
17 import { VideoPlaylistService } from '../shared-video-playlist'
18 import { VideoActionsDisplayType } from './video-actions-dropdown.component'
19
20 export type OwnerDisplayType = 'account' | 'videoChannel' | 'auto'
21 export type MiniatureDisplayOptions = {
22 date?: boolean
23 views?: boolean
24 by?: boolean
25 avatar?: boolean
26 privacyLabel?: boolean
27 privacyText?: boolean
28 state?: boolean
29 blacklistInfo?: boolean
30 nsfw?: boolean
31 }
32 export type VideoLinkType = 'internal' | 'lazy-load' | 'external'
33
34 @Component({
35 selector: 'my-video-miniature',
36 styleUrls: [ './video-miniature.component.scss' ],
37 templateUrl: './video-miniature.component.html',
38 changeDetection: ChangeDetectionStrategy.OnPush
39 })
40 export class VideoMiniatureComponent implements OnInit {
41 @Input() user: User
42 @Input() video: Video
43
44 @Input() ownerDisplayType: OwnerDisplayType = 'account'
45 @Input() displayOptions: MiniatureDisplayOptions = {
46 date: true,
47 views: true,
48 by: true,
49 avatar: false,
50 privacyLabel: false,
51 privacyText: false,
52 state: false,
53 blacklistInfo: false
54 }
55 @Input() displayAsRow = false
56 @Input() displayVideoActions = true
57 @Input() fitWidth = false
58
59 @Input() videoLinkType: VideoLinkType = 'internal'
60
61 @Output() videoBlocked = new EventEmitter()
62 @Output() videoUnblocked = new EventEmitter()
63 @Output() videoRemoved = new EventEmitter()
64 @Output() videoAccountMuted = new EventEmitter()
65
66 videoActionsDisplayOptions: VideoActionsDisplayType = {
67 playlist: true,
68 download: false,
69 update: true,
70 blacklist: true,
71 delete: true,
72 report: true,
73 duplicate: true,
74 mute: true
75 }
76 showActions = false
77 serverConfig: ServerConfig
78
79 addToWatchLaterText: string
80 addedToWatchLaterText: string
81 inWatchLaterPlaylist: boolean
82 channelLinkTitle = ''
83
84 watchLaterPlaylist: {
85 id: number
86 playlistElementId?: number
87 }
88
89 videoRouterLink: any[] = []
90 videoHref: string
91 videoTarget: string
92
93 private ownerDisplayTypeChosen: 'account' | 'videoChannel'
94
95 constructor (
96 private screenService: ScreenService,
97 private serverService: ServerService,
98 private i18n: I18n,
99 private authService: AuthService,
100 private videoPlaylistService: VideoPlaylistService,
101 private cd: ChangeDetectorRef,
102 @Inject(LOCALE_ID) private localeId: string
103 ) {}
104
105 get isVideoBlur () {
106 return this.video.isVideoNSFWForUser(this.user, this.serverConfig)
107 }
108
109 ngOnInit () {
110 this.serverConfig = this.serverService.getTmpConfig()
111 this.serverService.getConfig()
112 .subscribe(config => {
113 this.serverConfig = config
114 this.buildVideoLink()
115 })
116
117 this.setUpBy()
118
119 this.channelLinkTitle = this.i18n(
120 '{{name}} (channel page)',
121 { name: this.video.channel.name, handle: this.video.byVideoChannel }
122 )
123
124 // We rely on mouseenter to lazy load actions
125 if (this.screenService.isInTouchScreen()) {
126 this.loadActions()
127 }
128 }
129
130 buildVideoLink () {
131 if (this.videoLinkType === 'internal' || !this.video.url) {
132 this.videoRouterLink = [ '/videos/watch', this.video.uuid ]
133 return
134 }
135
136 if (this.videoLinkType === 'external') {
137 this.videoRouterLink = null
138 this.videoHref = this.video.url
139 this.videoTarget = '_blank'
140 return
141 }
142
143 // Lazy load
144 this.videoRouterLink = [ '/search/lazy-load-video', { url: this.video.url } ]
145 }
146
147 displayOwnerAccount () {
148 return this.ownerDisplayTypeChosen === 'account'
149 }
150
151 displayOwnerVideoChannel () {
152 return this.ownerDisplayTypeChosen === 'videoChannel'
153 }
154
155 isUnlistedVideo () {
156 return this.video.privacy.id === VideoPrivacy.UNLISTED
157 }
158
159 isPrivateVideo () {
160 return this.video.privacy.id === VideoPrivacy.PRIVATE
161 }
162
163 getStateLabel (video: Video) {
164 if (!video.state) return ''
165
166 if (video.privacy.id !== VideoPrivacy.PRIVATE && video.state.id === VideoState.PUBLISHED) {
167 return this.i18n('Published')
168 }
169
170 if (video.scheduledUpdate) {
171 const updateAt = new Date(video.scheduledUpdate.updateAt.toString()).toLocaleString(this.localeId)
172 return this.i18n('Publication scheduled on ') + updateAt
173 }
174
175 if (video.state.id === VideoState.TO_TRANSCODE && video.waitTranscoding === true) {
176 return this.i18n('Waiting transcoding')
177 }
178
179 if (video.state.id === VideoState.TO_TRANSCODE) {
180 return this.i18n('To transcode')
181 }
182
183 if (video.state.id === VideoState.TO_IMPORT) {
184 return this.i18n('To import')
185 }
186
187 return ''
188 }
189
190 getAvatarUrl () {
191 if (this.ownerDisplayTypeChosen === 'account') {
192 return this.video.accountAvatarUrl
193 }
194
195 return this.video.videoChannelAvatarUrl
196 }
197
198 loadActions () {
199 if (this.displayVideoActions) this.showActions = true
200
201 this.loadWatchLater()
202 }
203
204 onVideoBlocked () {
205 this.videoBlocked.emit()
206 }
207
208 onVideoUnblocked () {
209 this.videoUnblocked.emit()
210 }
211
212 onVideoRemoved () {
213 this.videoRemoved.emit()
214 }
215
216 onVideoAccountMuted () {
217 this.videoAccountMuted.emit()
218 }
219
220 isUserLoggedIn () {
221 return this.authService.isLoggedIn()
222 }
223
224 onWatchLaterClick (currentState: boolean) {
225 if (currentState === true) this.removeFromWatchLater()
226 else this.addToWatchLater()
227
228 this.inWatchLaterPlaylist = !currentState
229 }
230
231 addToWatchLater () {
232 const body = { videoId: this.video.id }
233
234 this.videoPlaylistService.addVideoInPlaylist(this.watchLaterPlaylist.id, body).subscribe(
235 res => {
236 this.watchLaterPlaylist.playlistElementId = res.videoPlaylistElement.id
237 }
238 )
239 }
240
241 removeFromWatchLater () {
242 this.videoPlaylistService.removeVideoFromPlaylist(this.watchLaterPlaylist.id, this.watchLaterPlaylist.playlistElementId, this.video.id)
243 .subscribe(
244 _ => { /* empty */ }
245 )
246 }
247
248 isWatchLaterPlaylistDisplayed () {
249 return this.displayVideoActions && this.isUserLoggedIn() && this.inWatchLaterPlaylist !== undefined
250 }
251
252 private setUpBy () {
253 if (this.ownerDisplayType === 'account' || this.ownerDisplayType === 'videoChannel') {
254 this.ownerDisplayTypeChosen = this.ownerDisplayType
255 return
256 }
257
258 // If the video channel name an UUID (not really displayable, we changed this behaviour in v1.0.0-beta.12)
259 // -> Use the account name
260 if (
261 this.video.channel.name === `${this.video.account.name}_channel` ||
262 this.video.channel.name.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
263 ) {
264 this.ownerDisplayTypeChosen = 'account'
265 } else {
266 this.ownerDisplayTypeChosen = 'videoChannel'
267 }
268 }
269
270 private loadWatchLater () {
271 if (!this.isUserLoggedIn() || this.inWatchLaterPlaylist !== undefined) return
272
273 this.authService.userInformationLoaded
274 .pipe(switchMap(() => this.videoPlaylistService.listenToVideoPlaylistChange(this.video.id)))
275 .subscribe(existResult => {
276 const watchLaterPlaylist = this.authService.getUser().specialPlaylists.find(p => p.type === VideoPlaylistType.WATCH_LATER)
277 const existsInWatchLater = existResult.find(r => r.playlistId === watchLaterPlaylist.id)
278 this.inWatchLaterPlaylist = false
279
280 this.watchLaterPlaylist = {
281 id: watchLaterPlaylist.id
282 }
283
284 if (existsInWatchLater) {
285 this.inWatchLaterPlaylist = true
286 this.watchLaterPlaylist.playlistElementId = existsInWatchLater.playlistElementId
287 }
288
289 this.cd.markForCheck()
290 })
291
292 this.videoPlaylistService.runPlaylistCheck(this.video.id)
293 }
294 }