diff options
Diffstat (limited to 'client/src/app/shared')
3 files changed, 57 insertions, 2 deletions
diff --git a/client/src/app/shared/shared-main/video/video.model.ts b/client/src/app/shared/shared-main/video/video.model.ts index 472a8c810..4203ff1c0 100644 --- a/client/src/app/shared/shared-main/video/video.model.ts +++ b/client/src/app/shared/shared-main/video/video.model.ts | |||
@@ -14,7 +14,8 @@ import { | |||
14 | VideoPrivacy, | 14 | VideoPrivacy, |
15 | VideoScheduleUpdate, | 15 | VideoScheduleUpdate, |
16 | VideoState, | 16 | VideoState, |
17 | VideoStreamingPlaylist | 17 | VideoStreamingPlaylist, |
18 | VideoStreamingPlaylistType | ||
18 | } from '@shared/models' | 19 | } from '@shared/models' |
19 | 20 | ||
20 | export class Video implements VideoServerModel { | 21 | export class Video implements VideoServerModel { |
@@ -219,6 +220,14 @@ export class Video implements VideoServerModel { | |||
219 | return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO)) | 220 | return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.UPDATE_ANY_VIDEO)) |
220 | } | 221 | } |
221 | 222 | ||
223 | hasHLS () { | ||
224 | return this.streamingPlaylists?.some(p => p.type === VideoStreamingPlaylistType.HLS) | ||
225 | } | ||
226 | |||
227 | hasWebTorrent () { | ||
228 | return this.files && this.files.length !== 0 | ||
229 | } | ||
230 | |||
222 | isLiveInfoAvailableBy (user: AuthUser) { | 231 | isLiveInfoAvailableBy (user: AuthUser) { |
223 | return this.isLive && | 232 | return this.isLive && |
224 | user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.GET_ANY_LIVE)) | 233 | user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.GET_ANY_LIVE)) |
diff --git a/client/src/app/shared/shared-main/video/video.service.ts b/client/src/app/shared/shared-main/video/video.service.ts index 570e8e3be..d135a27dc 100644 --- a/client/src/app/shared/shared-main/video/video.service.ts +++ b/client/src/app/shared/shared-main/video/video.service.ts | |||
@@ -299,6 +299,15 @@ export class VideoService { | |||
299 | ) | 299 | ) |
300 | } | 300 | } |
301 | 301 | ||
302 | removeVideoFiles (videoIds: (number | string)[], type: 'hls' | 'webtorrent') { | ||
303 | return from(videoIds) | ||
304 | .pipe( | ||
305 | concatMap(id => this.authHttp.delete(VideoService.BASE_VIDEO_URL + '/' + id + '/' + type)), | ||
306 | toArray(), | ||
307 | catchError(err => this.restExtractor.handleError(err)) | ||
308 | ) | ||
309 | } | ||
310 | |||
302 | loadCompleteDescription (descriptionPath: string) { | 311 | loadCompleteDescription (descriptionPath: string) { |
303 | return this.authHttp | 312 | return this.authHttp |
304 | .get<{ description: string }>(environment.apiUrl + descriptionPath) | 313 | .get<{ description: string }>(environment.apiUrl + descriptionPath) |
diff --git a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts index eff56b40e..82c084791 100644 --- a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts +++ b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts | |||
@@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@a | |||
2 | import { AuthService, ConfirmService, Notifier, ScreenService } from '@app/core' | 2 | import { AuthService, ConfirmService, Notifier, ScreenService } from '@app/core' |
3 | import { BlocklistService, VideoBlockComponent, VideoBlockService, VideoReportComponent } from '@app/shared/shared-moderation' | 3 | import { BlocklistService, VideoBlockComponent, VideoBlockService, VideoReportComponent } from '@app/shared/shared-moderation' |
4 | import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' | 4 | import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' |
5 | import { VideoCaption } from '@shared/models' | 5 | import { UserRight, VideoCaption } from '@shared/models' |
6 | import { | 6 | import { |
7 | Actor, | 7 | Actor, |
8 | DropdownAction, | 8 | DropdownAction, |
@@ -27,6 +27,7 @@ export type VideoActionsDisplayType = { | |||
27 | duplicate?: boolean | 27 | duplicate?: boolean |
28 | mute?: boolean | 28 | mute?: boolean |
29 | liveInfo?: boolean | 29 | liveInfo?: boolean |
30 | removeFiles?: boolean | ||
30 | } | 31 | } |
31 | 32 | ||
32 | @Component({ | 33 | @Component({ |
@@ -65,6 +66,7 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
65 | @Input() buttonSize: DropdownButtonSize = 'normal' | 66 | @Input() buttonSize: DropdownButtonSize = 'normal' |
66 | @Input() buttonDirection: DropdownDirection = 'vertical' | 67 | @Input() buttonDirection: DropdownDirection = 'vertical' |
67 | 68 | ||
69 | @Output() videoFilesRemoved = new EventEmitter() | ||
68 | @Output() videoRemoved = new EventEmitter() | 70 | @Output() videoRemoved = new EventEmitter() |
69 | @Output() videoUnblocked = new EventEmitter() | 71 | @Output() videoUnblocked = new EventEmitter() |
70 | @Output() videoBlocked = new EventEmitter() | 72 | @Output() videoBlocked = new EventEmitter() |
@@ -174,6 +176,10 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
174 | return this.video.account.id !== this.user.account.id | 176 | return this.video.account.id !== this.user.account.id |
175 | } | 177 | } |
176 | 178 | ||
179 | canRemoveVideoFiles () { | ||
180 | return this.user.hasRight(UserRight.MANAGE_VIDEO_FILES) && this.video.hasHLS() && this.video.hasWebTorrent() | ||
181 | } | ||
182 | |||
177 | /* Action handlers */ | 183 | /* Action handlers */ |
178 | 184 | ||
179 | async unblockVideo () { | 185 | async unblockVideo () { |
@@ -245,6 +251,23 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
245 | }) | 251 | }) |
246 | } | 252 | } |
247 | 253 | ||
254 | async removeVideoFiles (video: Video, type: 'hls' | 'webtorrent') { | ||
255 | const confirmMessage = $localize`Do you really want to remove "${this.video.name}" files?` | ||
256 | |||
257 | const res = await this.confirmService.confirm(confirmMessage, $localize`Remove "${this.video.name}" files`) | ||
258 | if (res === false) return | ||
259 | |||
260 | this.videoService.removeVideoFiles([ video.id ], type) | ||
261 | .subscribe({ | ||
262 | next: () => { | ||
263 | this.notifier.success($localize`Removed files of ${video.name}.`) | ||
264 | this.videoFilesRemoved.emit() | ||
265 | }, | ||
266 | |||
267 | error: err => this.notifier.error(err.message) | ||
268 | }) | ||
269 | } | ||
270 | |||
248 | onVideoBlocked () { | 271 | onVideoBlocked () { |
249 | this.videoBlocked.emit() | 272 | this.videoBlocked.emit() |
250 | } | 273 | } |
@@ -317,6 +340,20 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
317 | iconName: 'flag' | 340 | iconName: 'flag' |
318 | } | 341 | } |
319 | ], | 342 | ], |
343 | [ | ||
344 | { | ||
345 | label: $localize`Delete HLS files`, | ||
346 | handler: ({ video }) => this.removeVideoFiles(video, 'hls'), | ||
347 | isDisplayed: () => this.displayOptions.removeFiles && this.canRemoveVideoFiles(), | ||
348 | iconName: 'delete' | ||
349 | }, | ||
350 | { | ||
351 | label: $localize`Delete WebTorrent files`, | ||
352 | handler: ({ video }) => this.removeVideoFiles(video, 'webtorrent'), | ||
353 | isDisplayed: () => this.displayOptions.removeFiles && this.canRemoveVideoFiles(), | ||
354 | iconName: 'delete' | ||
355 | } | ||
356 | ], | ||
320 | [ // actions regarding the account/its server | 357 | [ // actions regarding the account/its server |
321 | { | 358 | { |
322 | label: $localize`Mute account`, | 359 | label: $localize`Mute account`, |