1 import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core'
2 import { AuthService, ConfirmService, Notifier, ScreenService } from '@app/core'
3 import { VideoBlockComponent, VideoBlockService, VideoReportComponent } from '@app/shared/shared-moderation'
4 import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
5 import { I18n } from '@ngx-translate/i18n-polyfill'
6 import { VideoCaption } from '@shared/models'
7 import { DropdownAction, DropdownButtonSize, DropdownDirection, RedundancyService, Video, VideoDetails, VideoService } from '../shared-main'
8 import { VideoAddToPlaylistComponent } from '../shared-video-playlist'
9 import { VideoDownloadComponent } from './video-download.component'
11 export type VideoActionsDisplayType = {
22 selector: 'my-video-actions-dropdown',
23 templateUrl: './video-actions-dropdown.component.html',
24 styleUrls: [ './video-actions-dropdown.component.scss' ]
26 export class VideoActionsDropdownComponent implements OnChanges {
27 @ViewChild('playlistDropdown') playlistDropdown: NgbDropdown
28 @ViewChild('playlistAdd') playlistAdd: VideoAddToPlaylistComponent
30 @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent
31 @ViewChild('videoReportModal') videoReportModal: VideoReportComponent
32 @ViewChild('videoBlockModal') videoBlockModal: VideoBlockComponent
34 @Input() video: Video | VideoDetails
35 @Input() videoCaptions: VideoCaption[] = []
37 @Input() displayOptions: VideoActionsDisplayType = {
46 @Input() placement = 'left'
48 @Input() label: string
50 @Input() buttonStyled = false
51 @Input() buttonSize: DropdownButtonSize = 'normal'
52 @Input() buttonDirection: DropdownDirection = 'vertical'
54 @Output() videoRemoved = new EventEmitter()
55 @Output() videoUnblocked = new EventEmitter()
56 @Output() videoBlocked = new EventEmitter()
57 @Output() modalOpened = new EventEmitter()
59 videoActions: DropdownAction<{ video: Video }>[][] = []
61 private loaded = false
64 private authService: AuthService,
65 private notifier: Notifier,
66 private confirmService: ConfirmService,
67 private videoBlocklistService: VideoBlockService,
68 private screenService: ScreenService,
69 private videoService: VideoService,
70 private redundancyService: RedundancyService,
75 return this.authService.getUser()
81 this.playlistAdd.reload()
88 return this.authService.isLoggedIn()
91 loadDropdownInformation () {
92 if (!this.isUserLoggedIn() || this.loaded === true) return
96 if (this.displayOptions.playlist) this.playlistAdd.load()
101 showDownloadModal () {
102 this.modalOpened.emit()
104 this.videoDownloadModal.show(this.video as VideoDetails, this.videoCaptions)
108 this.modalOpened.emit()
110 this.videoReportModal.show()
114 this.modalOpened.emit()
116 this.videoBlockModal.show()
119 /* Actions checker */
121 isVideoUpdatable () {
122 return this.video.isUpdatableBy(this.user)
125 isVideoRemovable () {
126 return this.video.isRemovableBy(this.user)
129 isVideoBlockable () {
130 return this.video.isBlockableBy(this.user)
133 isVideoUnblockable () {
134 return this.video.isUnblockableBy(this.user)
137 isVideoDownloadable () {
138 return this.video && this.video instanceof VideoDetails && this.video.downloadEnabled
141 canVideoBeDuplicated () {
142 return this.video.canBeDuplicatedBy(this.user)
145 /* Action handlers */
147 async unblockVideo () {
148 const confirmMessage = this.i18n(
149 'Do you really want to unblock this video? It will be available again in the videos list.'
152 const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblock'))
153 if (res === false) return
155 this.videoBlocklistService.unblockVideo(this.video.id).subscribe(
157 this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: this.video.name }))
159 this.video.blacklisted = false
160 this.video.blockedReason = null
162 this.videoUnblocked.emit()
165 err => this.notifier.error(err.message)
169 async removeVideo () {
170 this.modalOpened.emit()
172 const res = await this.confirmService.confirm(this.i18n('Do you really want to delete this video?'), this.i18n('Delete'))
173 if (res === false) return
175 this.videoService.removeVideo(this.video.id)
178 this.notifier.success(this.i18n('Video {{videoName}} deleted.', { videoName: this.video.name }))
180 this.videoRemoved.emit()
183 error => this.notifier.error(error.message)
188 this.redundancyService.addVideoRedundancy(this.video)
191 const message = this.i18n('This video will be duplicated by your instance.')
192 this.notifier.success(message)
195 err => this.notifier.error(err.message)
200 this.videoBlocked.emit()
203 getPlaylistDropdownPlacement () {
204 if (this.screenService.isInSmallView()) {
205 return 'bottom-right'
208 return 'bottom-left bottom-right'
211 private buildActions () {
212 this.videoActions = [
215 label: this.i18n('Save to playlist'),
216 handler: () => this.playlistDropdown.toggle(),
217 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.playlist,
218 iconName: 'playlist-add'
223 label: this.i18n('Download'),
224 handler: () => this.showDownloadModal(),
225 isDisplayed: () => this.displayOptions.download && this.isVideoDownloadable(),
229 label: this.i18n('Update'),
230 linkBuilder: ({ video }) => [ '/videos/update', video.uuid ],
232 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable()
235 label: this.i18n('Block'),
236 handler: () => this.showBlockModal(),
238 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoBlockable()
241 label: this.i18n('Unblock'),
242 handler: () => this.unblockVideo(),
244 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblockable()
247 label: this.i18n('Mirror'),
248 handler: () => this.duplicateVideo(),
249 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.duplicate && this.canVideoBeDuplicated(),
250 iconName: 'cloud-download'
253 label: this.i18n('Delete'),
254 handler: () => this.removeVideo(),
255 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.delete && this.isVideoRemovable(),
261 label: this.i18n('Report'),
262 handler: () => this.showReportModal(),
263 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.report,