]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - 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
CommitLineData
5fb2e288 1import { switchMap } from 'rxjs/operators'
b7819090
C
2import {
3 ChangeDetectionStrategy,
4 ChangeDetectorRef,
5 Component,
6 EventEmitter,
7 Inject,
8 Input,
9 LOCALE_ID,
10 OnInit,
11 Output
12} from '@angular/core'
67ed6552 13import { AuthService, ScreenService, ServerService, User } from '@app/core'
5fb2e288 14import { I18n } from '@ngx-translate/i18n-polyfill'
583eb04b 15import { ServerConfig, VideoPlaylistType, VideoPrivacy, VideoState } from '@shared/models'
67ed6552
C
16import { Video } from '../shared-main'
17import { VideoPlaylistService } from '../shared-video-playlist'
18import { VideoActionsDisplayType } from './video-actions-dropdown.component'
501bc6c2 19
22a16e36 20export type OwnerDisplayType = 'account' | 'videoChannel' | 'auto'
e2409062
C
21export type MiniatureDisplayOptions = {
22 date?: boolean
23 views?: boolean
24 by?: boolean
c2caa99b 25 avatar?: boolean
e2409062
C
26 privacyLabel?: boolean
27 privacyText?: boolean
28 state?: boolean
29 blacklistInfo?: boolean
30 nsfw?: boolean
31}
0bdad52f 32export type VideoLinkType = 'internal' | 'lazy-load' | 'external'
22a16e36 33
501bc6c2
C
34@Component({
35 selector: 'my-video-miniature',
ec8d8440 36 styleUrls: [ './video-miniature.component.scss' ],
89724816
C
37 templateUrl: './video-miniature.component.html',
38 changeDetection: ChangeDetectionStrategy.OnPush
501bc6c2 39})
22a16e36 40export class VideoMiniatureComponent implements OnInit {
df98563e
C
41 @Input() user: User
42 @Input() video: Video
e2409062 43
22a16e36 44 @Input() ownerDisplayType: OwnerDisplayType = 'account'
e2409062
C
45 @Input() displayOptions: MiniatureDisplayOptions = {
46 date: true,
47 views: true,
48 by: true,
c2caa99b 49 avatar: false,
e2409062
C
50 privacyLabel: false,
51 privacyText: false,
52 state: false,
53 blacklistInfo: false
54 }
55 @Input() displayAsRow = false
3a0fb65c 56 @Input() displayVideoActions = true
e66883b3 57 @Input() fitWidth = false
3a0fb65c 58
0bdad52f 59 @Input() videoLinkType: VideoLinkType = 'internal'
5fb2e288 60
5baee5fc
RK
61 @Output() videoBlocked = new EventEmitter()
62 @Output() videoUnblocked = new EventEmitter()
3a0fb65c 63 @Output() videoRemoved = new EventEmitter()
d473fd94 64 @Output() videoAccountMuted = new EventEmitter()
3a0fb65c
C
65
66 videoActionsDisplayOptions: VideoActionsDisplayType = {
67 playlist: true,
68 download: false,
69 update: true,
70 blacklist: true,
71 delete: true,
b764380a 72 report: true,
d473fd94
RK
73 duplicate: true,
74 mute: true
3a0fb65c
C
75 }
76 showActions = false
ba430d75 77 serverConfig: ServerConfig
22a16e36 78
b7819090
C
79 addToWatchLaterText: string
80 addedToWatchLaterText: string
81 inWatchLaterPlaylist: boolean
435258ea 82 channelLinkTitle = ''
b7819090
C
83
84 watchLaterPlaylist: {
85 id: number
86 playlistElementId?: number
87 }
88
0bdad52f
C
89 videoRouterLink: any[] = []
90 videoHref: string
91 videoTarget: string
5fb2e288 92
22a16e36 93 private ownerDisplayTypeChosen: 'account' | 'videoChannel'
501bc6c2 94
e2409062 95 constructor (
3a0fb65c 96 private screenService: ScreenService,
e2409062
C
97 private serverService: ServerService,
98 private i18n: I18n,
b7819090
C
99 private authService: AuthService,
100 private videoPlaylistService: VideoPlaylistService,
101 private cd: ChangeDetectorRef,
e2409062 102 @Inject(LOCALE_ID) private localeId: string
435258ea 103 ) {}
0883b324 104
d1a63fc7 105 get isVideoBlur () {
ba430d75 106 return this.video.isVideoNSFWForUser(this.user, this.serverConfig)
d1a63fc7
C
107 }
108
22a16e36 109 ngOnInit () {
ba430d75
C
110 this.serverConfig = this.serverService.getTmpConfig()
111 this.serverService.getConfig()
5fb2e288
C
112 .subscribe(config => {
113 this.serverConfig = config
114 this.buildVideoLink()
115 })
ba430d75 116
3a0fb65c 117 this.setUpBy()
22a16e36 118
435258ea 119 this.channelLinkTitle = this.i18n(
d6d951dd 120 '{{name}} (channel page)',
435258ea
RK
121 { name: this.video.channel.name, handle: this.video.byVideoChannel }
122 )
123
8dfceec4
C
124 // We rely on mouseenter to lazy load actions
125 if (this.screenService.isInTouchScreen()) {
743f023c 126 this.loadActions()
22a16e36 127 }
92fb909c 128 }
22a16e36 129
5fb2e288 130 buildVideoLink () {
0bdad52f
C
131 if (this.videoLinkType === 'internal' || !this.video.url) {
132 this.videoRouterLink = [ '/videos/watch', this.video.uuid ]
133 return
134 }
5fb2e288 135
0bdad52f
C
136 if (this.videoLinkType === 'external') {
137 this.videoRouterLink = null
138 this.videoHref = this.video.url
139 this.videoTarget = '_blank'
5fb2e288
C
140 return
141 }
142
0bdad52f
C
143 // Lazy load
144 this.videoRouterLink = [ '/search/lazy-load-video', { url: this.video.url } ]
5fb2e288
C
145 }
146
22a16e36
C
147 displayOwnerAccount () {
148 return this.ownerDisplayTypeChosen === 'account'
149 }
150
151 displayOwnerVideoChannel () {
152 return this.ownerDisplayTypeChosen === 'videoChannel'
153 }
017c3dca
C
154
155 isUnlistedVideo () {
156 return this.video.privacy.id === VideoPrivacy.UNLISTED
157 }
158
159 isPrivateVideo () {
160 return this.video.privacy.id === VideoPrivacy.PRIVATE
161 }
e2409062
C
162
163 getStateLabel (video: Video) {
dedc7abb
C
164 if (!video.state) return ''
165
e2409062
C
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 }
3a0fb65c 189
cf78883c
C
190 getAvatarUrl () {
191 if (this.ownerDisplayTypeChosen === 'account') {
192 return this.video.accountAvatarUrl
193 }
194
195 return this.video.videoChannelAvatarUrl
196 }
197
3a0fb65c
C
198 loadActions () {
199 if (this.displayVideoActions) this.showActions = true
b7819090
C
200
201 this.loadWatchLater()
3a0fb65c
C
202 }
203
5baee5fc
RK
204 onVideoBlocked () {
205 this.videoBlocked.emit()
3a0fb65c
C
206 }
207
5baee5fc
RK
208 onVideoUnblocked () {
209 this.videoUnblocked.emit()
3a0fb65c
C
210 }
211
212 onVideoRemoved () {
213 this.videoRemoved.emit()
214 }
215
d473fd94
RK
216 onVideoAccountMuted () {
217 this.videoAccountMuted.emit()
218 }
219
b7819090
C
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 () {
51b34a11 242 this.videoPlaylistService.removeVideoFromPlaylist(this.watchLaterPlaylist.id, this.watchLaterPlaylist.playlistElementId, this.video.id)
b7819090
C
243 .subscribe(
244 _ => { /* empty */ }
245 )
246 }
247
248 isWatchLaterPlaylistDisplayed () {
5fb2e288 249 return this.displayVideoActions && this.isUserLoggedIn() && this.inWatchLaterPlaylist !== undefined
b7819090
C
250 }
251
3a0fb65c
C
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 }
b7819090
C
269
270 private loadWatchLater () {
51b34a11
C
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)
b7819090 293 }
501bc6c2 294}