]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts
Lazy load all routes
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-video-miniature / video-actions-dropdown.component.ts
CommitLineData
54e78847 1import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core'
67ed6552
C
2import { AuthService, ConfirmService, Notifier, ScreenService } from '@app/core'
3import { VideoBlockComponent, VideoBlockService, VideoReportComponent } from '@app/shared/shared-moderation'
3a0fb65c 4import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
67ed6552 5import { I18n } from '@ngx-translate/i18n-polyfill'
8ba9c205 6import { VideoCaption } from '@shared/models'
67ed6552
C
7import { DropdownAction, DropdownButtonSize, DropdownDirection, RedundancyService, Video, VideoDetails, VideoService } from '../shared-main'
8import { VideoAddToPlaylistComponent } from '../shared-video-playlist'
9import { VideoDownloadComponent } from './video-download.component'
3a0fb65c
C
10
11export type VideoActionsDisplayType = {
12 playlist?: boolean
13 download?: boolean
14 update?: boolean
15 blacklist?: boolean
16 delete?: boolean
17 report?: boolean
b764380a 18 duplicate?: boolean
3a0fb65c
C
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})
4da22f64 26export class VideoActionsDropdownComponent implements OnChanges {
2f5d2ec5
C
27 @ViewChild('playlistDropdown') playlistDropdown: NgbDropdown
28 @ViewChild('playlistAdd') playlistAdd: VideoAddToPlaylistComponent
3a0fb65c 29
2f5d2ec5
C
30 @ViewChild('videoDownloadModal') videoDownloadModal: VideoDownloadComponent
31 @ViewChild('videoReportModal') videoReportModal: VideoReportComponent
5baee5fc 32 @ViewChild('videoBlockModal') videoBlockModal: VideoBlockComponent
3a0fb65c
C
33
34 @Input() video: Video | VideoDetails
8ba9c205 35 @Input() videoCaptions: VideoCaption[] = []
3a0fb65c
C
36
37 @Input() displayOptions: VideoActionsDisplayType = {
38 playlist: false,
39 download: true,
40 update: true,
41 blacklist: true,
42 delete: true,
b764380a
C
43 report: true,
44 duplicate: true
3a0fb65c 45 }
8dfceec4 46 @Input() placement = 'left'
3a0fb65c
C
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()
5baee5fc
RK
55 @Output() videoUnblocked = new EventEmitter()
56 @Output() videoBlocked = new EventEmitter()
689a4f69 57 @Output() modalOpened = new EventEmitter()
3a0fb65c
C
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,
5baee5fc 67 private videoBlocklistService: VideoBlockService,
3a0fb65c
C
68 private screenService: ScreenService,
69 private videoService: VideoService,
b764380a 70 private redundancyService: RedundancyService,
3a0fb65c
C
71 private i18n: I18n
72 ) { }
73
74 get user () {
75 return this.authService.getUser()
76 }
77
78 ngOnChanges () {
1c8ddbfa
C
79 if (this.loaded) {
80 this.loaded = false
78d60e63 81 this.playlistAdd.reload()
1c8ddbfa
C
82 }
83
3a0fb65c
C
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 () {
689a4f69
C
102 this.modalOpened.emit()
103
8ba9c205 104 this.videoDownloadModal.show(this.video as VideoDetails, this.videoCaptions)
3a0fb65c
C
105 }
106
107 showReportModal () {
689a4f69
C
108 this.modalOpened.emit()
109
3a0fb65c
C
110 this.videoReportModal.show()
111 }
112
5baee5fc 113 showBlockModal () {
689a4f69
C
114 this.modalOpened.emit()
115
5baee5fc 116 this.videoBlockModal.show()
3a0fb65c
C
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
5baee5fc
RK
129 isVideoBlockable () {
130 return this.video.isBlockableBy(this.user)
3a0fb65c
C
131 }
132
5baee5fc
RK
133 isVideoUnblockable () {
134 return this.video.isUnblockableBy(this.user)
3a0fb65c
C
135 }
136
72675ebe
C
137 isVideoDownloadable () {
138 return this.video && this.video instanceof VideoDetails && this.video.downloadEnabled
139 }
140
b764380a
C
141 canVideoBeDuplicated () {
142 return this.video.canBeDuplicatedBy(this.user)
143 }
144
3a0fb65c
C
145 /* Action handlers */
146
5baee5fc 147 async unblockVideo () {
3a0fb65c 148 const confirmMessage = this.i18n(
5baee5fc 149 'Do you really want to unblock this video? It will be available again in the videos list.'
3a0fb65c
C
150 )
151
5baee5fc 152 const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblock'))
3a0fb65c
C
153 if (res === false) return
154
5baee5fc 155 this.videoBlocklistService.unblockVideo(this.video.id).subscribe(
3a0fb65c 156 () => {
5baee5fc 157 this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: this.video.name }))
3a0fb65c
C
158
159 this.video.blacklisted = false
5baee5fc 160 this.video.blockedReason = null
3a0fb65c 161
5baee5fc 162 this.videoUnblocked.emit()
3a0fb65c
C
163 },
164
165 err => this.notifier.error(err.message)
166 )
167 }
168
169 async removeVideo () {
689a4f69
C
170 this.modalOpened.emit()
171
3a0fb65c
C
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
b764380a
C
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
5baee5fc
RK
199 onVideoBlocked () {
200 this.videoBlocked.emit()
3a0fb65c
C
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 () {
f238aec5
C
212 this.videoActions = [
213 [
3a0fb65c
C
214 {
215 label: this.i18n('Save to playlist'),
216 handler: () => this.playlistDropdown.toggle(),
f238aec5 217 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.playlist,
3a0fb65c
C
218 iconName: 'playlist-add'
219 }
f238aec5
C
220 ],
221 [
3a0fb65c
C
222 {
223 label: this.i18n('Download'),
224 handler: () => this.showDownloadModal(),
72675ebe 225 isDisplayed: () => this.displayOptions.download && this.isVideoDownloadable(),
3a0fb65c
C
226 iconName: 'download'
227 },
228 {
229 label: this.i18n('Update'),
230 linkBuilder: ({ video }) => [ '/videos/update', video.uuid ],
231 iconName: 'edit',
f238aec5 232 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.update && this.isVideoUpdatable()
3a0fb65c
C
233 },
234 {
5baee5fc
RK
235 label: this.i18n('Block'),
236 handler: () => this.showBlockModal(),
3a0fb65c 237 iconName: 'no',
5baee5fc 238 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoBlockable()
3a0fb65c
C
239 },
240 {
5baee5fc
RK
241 label: this.i18n('Unblock'),
242 handler: () => this.unblockVideo(),
3a0fb65c 243 iconName: 'undo',
5baee5fc 244 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.blacklist && this.isVideoUnblockable()
3a0fb65c 245 },
b764380a 246 {
988af781 247 label: this.i18n('Mirror'),
b764380a
C
248 handler: () => this.duplicateVideo(),
249 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.duplicate && this.canVideoBeDuplicated(),
250 iconName: 'cloud-download'
251 },
3a0fb65c
C
252 {
253 label: this.i18n('Delete'),
254 handler: () => this.removeVideo(),
f238aec5 255 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.delete && this.isVideoRemovable(),
3a0fb65c
C
256 iconName: 'delete'
257 }
f238aec5
C
258 ],
259 [
3a0fb65c
C
260 {
261 label: this.i18n('Report'),
262 handler: () => this.showReportModal(),
f238aec5 263 isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.report,
3a0fb65c
C
264 iconName: 'alert'
265 }
f238aec5
C
266 ]
267 ]
3a0fb65c
C
268 }
269}