]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts
Reorganize client shared modules
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-video-miniature / video-actions-dropdown.component.ts
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'
10
11 export type VideoActionsDisplayType = {
12 playlist?: boolean
13 download?: boolean
14 update?: boolean
15 blacklist?: boolean
16 delete?: boolean
17 report?: boolean
18 duplicate?: boolean
19 }
20
21 @Component({
22 selector: 'my-video-actions-dropdown',
23 templateUrl: './video-actions-dropdown.component.html',
24 styleUrls: [ './video-actions-dropdown.component.scss' ]
25 })
26 export class VideoActionsDropdownComponent implements OnChanges {
27 @ViewChild('playlistDropdown') playlistDropdown: NgbDropdown
28 @ViewChild('playlistAdd') playlistAdd: VideoAddToPlaylistComponent
29
30 @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent
31 @ViewChild('videoReportModal') videoReportModal: VideoReportComponent
32 @ViewChild('videoBlockModal') videoBlockModal: VideoBlockComponent
33
34 @Input() video: Video | VideoDetails
35 @Input() videoCaptions: VideoCaption[] = []
36
37 @Input() displayOptions: VideoActionsDisplayType = {
38 playlist: false,
39 download: true,
40 update: true,
41 blacklist: true,
42 delete: true,
43 report: true,
44 duplicate: true
45 }
46 @Input() placement = 'left'
47
48 @Input() label: string
49
50 @Input() buttonStyled = false
51 @Input() buttonSize: DropdownButtonSize = 'normal'
52 @Input() buttonDirection: DropdownDirection = 'vertical'
53
54 @Output() videoRemoved = new EventEmitter()
55 @Output() videoUnblocked = new EventEmitter()
56 @Output() videoBlocked = new EventEmitter()
57 @Output() modalOpened = new EventEmitter()
58
59 videoActions: DropdownAction<{ video: Video }>[][] = []
60
61 private loaded = false
62
63 constructor (
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,
71 private i18n: I18n
72 ) { }
73
74 get user () {
75 return this.authService.getUser()
76 }
77
78 ngOnChanges () {
79 if (this.loaded) {
80 this.loaded = false
81 this.playlistAdd.reload()
82 }
83
84 this.buildActions()
85 }
86
87 isUserLoggedIn () {
88 return this.authService.isLoggedIn()
89 }
90
91 loadDropdownInformation () {
92 if (!this.isUserLoggedIn() || this.loaded === true) return
93
94 this.loaded = true
95
96 if (this.displayOptions.playlist) this.playlistAdd.load()
97 }
98
99 /* Show modals */
100
101 showDownloadModal () {
102 this.modalOpened.emit()
103
104 this.videoDownloadModal.show(this.video as VideoDetails, this.videoCaptions)
105 }
106
107 showReportModal () {
108 this.modalOpened.emit()
109
110 this.videoReportModal.show()
111 }
112
113 showBlockModal () {
114 this.modalOpened.emit()
115
116 this.videoBlockModal.show()
117 }
118
119 /* Actions checker */
120
121 isVideoUpdatable () {
122 return this.video.isUpdatableBy(this.user)
123 }
124
125 isVideoRemovable () {
126 return this.video.isRemovableBy(this.user)
127 }
128
129 isVideoBlockable () {
130 return this.video.isBlockableBy(this.user)
131 }
132
133 isVideoUnblockable () {
134 return this.video.isUnblockableBy(this.user)
135 }
136
137 isVideoDownloadable () {
138 return this.video && this.video instanceof VideoDetails && this.video.downloadEnabled
139 }
140
141 canVideoBeDuplicated () {
142 return this.video.canBeDuplicatedBy(this.user)
143 }
144
145 /* Action handlers */
146
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.'
150 )
151
152 const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblock'))
153 if (res === false) return
154
155 this.videoBlocklistService.unblockVideo(this.video.id).subscribe(
156 () => {
157 this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: this.video.name }))
158
159 this.video.blacklisted = false
160 this.video.blockedReason = null
161
162 this.videoUnblocked.emit()
163 },
164
165 err => this.notifier.error(err.message)
166 )
167 }
168
169 async removeVideo () {
170 this.modalOpened.emit()
171
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
174
175 this.videoService.removeVideo(this.video.id)
176 .subscribe(
177 () => {
178 this.notifier.success(this.i18n('Video {{videoName}} deleted.', { videoName: this.video.name }))
179
180 this.videoRemoved.emit()
181 },
182
183 error => this.notifier.error(error.message)
184 )
185 }
186
187 duplicateVideo () {
188 this.redundancyService.addVideoRedundancy(this.video)
189 .subscribe(
190 () => {
191 const message = this.i18n('This video will be duplicated by your instance.')
192 this.notifier.success(message)
193 },
194
195 err => this.notifier.error(err.message)
196 )
197 }
198
199 onVideoBlocked () {
200 this.videoBlocked.emit()
201 }
202
203 getPlaylistDropdownPlacement () {
204 if (this.screenService.isInSmallView()) {
205 return 'bottom-right'
206 }
207
208 return 'bottom-left bottom-right'
209 }
210
211 private buildActions () {
212 this.videoActions = [
213 [
214 {
215 label: this.i18n('Save to playlist'),
216 handler: () => this.playlistDropdown.toggle(),
217 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.playlist,
218 iconName: 'playlist-add'
219 }
220 ],
221 [
222 {
223 label: this.i18n('Download'),
224 handler: () => this.showDownloadModal(),
225 isDisplayed: () => this.displayOptions.download && this.isVideoDownloadable(),
226 iconName: 'download'
227 },
228 {
229 label: this.i18n('Update'),
230 linkBuilder: ({ video }) => [ '/videos/update', video.uuid ],
231 iconName: 'edit',
232 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable()
233 },
234 {
235 label: this.i18n('Block'),
236 handler: () => this.showBlockModal(),
237 iconName: 'no',
238 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoBlockable()
239 },
240 {
241 label: this.i18n('Unblock'),
242 handler: () => this.unblockVideo(),
243 iconName: 'undo',
244 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblockable()
245 },
246 {
247 label: this.i18n('Mirror'),
248 handler: () => this.duplicateVideo(),
249 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.duplicate && this.canVideoBeDuplicated(),
250 iconName: 'cloud-download'
251 },
252 {
253 label: this.i18n('Delete'),
254 handler: () => this.removeVideo(),
255 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.delete && this.isVideoRemovable(),
256 iconName: 'delete'
257 }
258 ],
259 [
260 {
261 label: this.i18n('Report'),
262 handler: () => this.showReportModal(),
263 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.report,
264 iconName: 'alert'
265 }
266 ]
267 ]
268 }
269 }