diff options
Diffstat (limited to 'client/src/app')
5 files changed, 56 insertions, 7 deletions
diff --git a/client/src/app/shared/video/modals/video-download.component.html b/client/src/app/shared/video/modals/video-download.component.html index 3619f24e5..ed61198c4 100644 --- a/client/src/app/shared/video/modals/video-download.component.html +++ b/client/src/app/shared/video/modals/video-download.component.html | |||
@@ -1,6 +1,17 @@ | |||
1 | <ng-template #modal let-hide="close"> | 1 | <ng-template #modal let-hide="close"> |
2 | <div class="modal-header"> | 2 | <div class="modal-header"> |
3 | <h4 i18n class="modal-title">Download video</h4> | 3 | <h4 i18n class="modal-title">Download |
4 | <span *ngIf="!videoCaptions" i18n>video</span> | ||
5 | <div *ngIf="videoCaptions" ngbDropdown class="d-inline-block"> | ||
6 | <span id="dropdownDownloadType" ngbDropdownToggle i18n> | ||
7 | {{ type }} | ||
8 | </span> | ||
9 | <div ngbDropdownMenu aria-labelledby="dropdownDownloadType"> | ||
10 | <button *ngIf="type === 'video'" (click)="switchToType('subtitles')" ngbDropdownItem i18n>subtitles</button> | ||
11 | <button *ngIf="type === 'subtitles'" (click)="switchToType('video')" ngbDropdownItem i18n>video</button> | ||
12 | </div> | ||
13 | </div> | ||
14 | </h4> | ||
4 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> | 15 | <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> |
5 | </div> | 16 | </div> |
6 | 17 | ||
@@ -8,9 +19,12 @@ | |||
8 | <div class="form-group"> | 19 | <div class="form-group"> |
9 | <div class="input-group input-group-sm"> | 20 | <div class="input-group input-group-sm"> |
10 | <div class="input-group-prepend peertube-select-container"> | 21 | <div class="input-group-prepend peertube-select-container"> |
11 | <select [(ngModel)]="resolutionId"> | 22 | <select *ngIf="type === 'video'" [(ngModel)]="resolutionId"> |
12 | <option *ngFor="let file of getVideoFiles()" [value]="file.resolution.id">{{ file.resolution.label }}</option> | 23 | <option *ngFor="let file of getVideoFiles()" [value]="file.resolution.id">{{ file.resolution.label }}</option> |
13 | </select> | 24 | </select> |
25 | <select *ngIf="type === 'subtitles'" [(ngModel)]="subtitleLanguageId"> | ||
26 | <option *ngFor="let caption of videoCaptions" [value]="caption.language.id">{{ caption.language.label }}</option> | ||
27 | </select> | ||
14 | </div> | 28 | </div> |
15 | <input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getLink()" /> | 29 | <input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getLink()" /> |
16 | <div class="input-group-append"> | 30 | <div class="input-group-append"> |
@@ -21,7 +35,7 @@ | |||
21 | </div> | 35 | </div> |
22 | </div> | 36 | </div> |
23 | 37 | ||
24 | <div class="download-type"> | 38 | <div class="download-type" *ngIf="type === 'video'"> |
25 | <div class="peertube-radio-container"> | 39 | <div class="peertube-radio-container"> |
26 | <input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct"> | 40 | <input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct"> |
27 | <label i18n for="download-direct">Direct download</label> | 41 | <label i18n for="download-direct">Direct download</label> |
diff --git a/client/src/app/shared/video/modals/video-download.component.scss b/client/src/app/shared/video/modals/video-download.component.scss index 3e826c3b6..09dd91aa9 100644 --- a/client/src/app/shared/video/modals/video-download.component.scss +++ b/client/src/app/shared/video/modals/video-download.component.scss | |||
@@ -13,6 +13,10 @@ | |||
13 | } | 13 | } |
14 | } | 14 | } |
15 | 15 | ||
16 | #dropdownDownloadType { | ||
17 | cursor: pointer; | ||
18 | } | ||
19 | |||
16 | .download-type { | 20 | .download-type { |
17 | margin-top: 30px; | 21 | margin-top: 30px; |
18 | 22 | ||
diff --git a/client/src/app/shared/video/modals/video-download.component.ts b/client/src/app/shared/video/modals/video-download.component.ts index 712740086..c1ceca263 100644 --- a/client/src/app/shared/video/modals/video-download.component.ts +++ b/client/src/app/shared/video/modals/video-download.component.ts | |||
@@ -3,7 +3,9 @@ import { VideoDetails } from '../../../shared/video/video-details.model' | |||
3 | import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap' | 3 | import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap' |
4 | import { I18n } from '@ngx-translate/i18n-polyfill' | 4 | import { I18n } from '@ngx-translate/i18n-polyfill' |
5 | import { AuthService, Notifier } from '@app/core' | 5 | import { AuthService, Notifier } from '@app/core' |
6 | import { VideoPrivacy } from '@shared/models' | 6 | import { VideoPrivacy, VideoCaption } from '@shared/models' |
7 | |||
8 | type DownloadType = 'video' | 'subtitles' | ||
7 | 9 | ||
8 | @Component({ | 10 | @Component({ |
9 | selector: 'my-video-download', | 11 | selector: 'my-video-download', |
@@ -15,10 +17,14 @@ export class VideoDownloadComponent { | |||
15 | 17 | ||
16 | downloadType: 'direct' | 'torrent' = 'torrent' | 18 | downloadType: 'direct' | 'torrent' = 'torrent' |
17 | resolutionId: number | string = -1 | 19 | resolutionId: number | string = -1 |
20 | subtitleLanguageId: string | ||
18 | 21 | ||
19 | video: VideoDetails | 22 | video: VideoDetails |
23 | videoCaptions: VideoCaption[] | ||
20 | activeModal: NgbActiveModal | 24 | activeModal: NgbActiveModal |
21 | 25 | ||
26 | type: DownloadType = 'video' | ||
27 | |||
22 | constructor ( | 28 | constructor ( |
23 | private notifier: Notifier, | 29 | private notifier: Notifier, |
24 | private modalService: NgbModal, | 30 | private modalService: NgbModal, |
@@ -26,22 +32,31 @@ export class VideoDownloadComponent { | |||
26 | private i18n: I18n | 32 | private i18n: I18n |
27 | ) { } | 33 | ) { } |
28 | 34 | ||
35 | get typeText () { | ||
36 | return this.type === 'video' | ||
37 | ? this.i18n('video') | ||
38 | : this.i18n('subtitles') | ||
39 | } | ||
40 | |||
29 | getVideoFiles () { | 41 | getVideoFiles () { |
30 | if (!this.video) return [] | 42 | if (!this.video) return [] |
31 | 43 | ||
32 | return this.video.getFiles() | 44 | return this.video.getFiles() |
33 | } | 45 | } |
34 | 46 | ||
35 | show (video: VideoDetails) { | 47 | show (video: VideoDetails, videoCaptions?: VideoCaption[]) { |
36 | this.video = video | 48 | this.video = video |
49 | this.videoCaptions = videoCaptions && videoCaptions.length ? videoCaptions : undefined | ||
37 | 50 | ||
38 | this.activeModal = this.modalService.open(this.modal) | 51 | this.activeModal = this.modalService.open(this.modal) |
39 | 52 | ||
40 | this.resolutionId = this.getVideoFiles()[0].resolution.id | 53 | this.resolutionId = this.getVideoFiles()[0].resolution.id |
54 | if (this.videoCaptions) this.subtitleLanguageId = this.videoCaptions[0].language.id | ||
41 | } | 55 | } |
42 | 56 | ||
43 | onClose () { | 57 | onClose () { |
44 | this.video = undefined | 58 | this.video = undefined |
59 | this.videoCaptions = undefined | ||
45 | } | 60 | } |
46 | 61 | ||
47 | download () { | 62 | download () { |
@@ -50,6 +65,12 @@ export class VideoDownloadComponent { | |||
50 | } | 65 | } |
51 | 66 | ||
52 | getLink () { | 67 | getLink () { |
68 | return this.type === 'subtitles' && this.videoCaptions | ||
69 | ? this.getSubtitlesLink() | ||
70 | : this.getVideoLink() | ||
71 | } | ||
72 | |||
73 | getVideoLink () { | ||
53 | // HTML select send us a string, so convert it to a number | 74 | // HTML select send us a string, so convert it to a number |
54 | this.resolutionId = parseInt(this.resolutionId.toString(), 10) | 75 | this.resolutionId = parseInt(this.resolutionId.toString(), 10) |
55 | 76 | ||
@@ -72,7 +93,15 @@ export class VideoDownloadComponent { | |||
72 | } | 93 | } |
73 | } | 94 | } |
74 | 95 | ||
96 | getSubtitlesLink () { | ||
97 | return window.location.origin + this.videoCaptions.find(caption => caption.language.id === this.subtitleLanguageId).captionPath | ||
98 | } | ||
99 | |||
75 | activateCopiedMessage () { | 100 | activateCopiedMessage () { |
76 | this.notifier.success(this.i18n('Copied')) | 101 | this.notifier.success(this.i18n('Copied')) |
77 | } | 102 | } |
103 | |||
104 | switchToType (type: DownloadType) { | ||
105 | this.type = type | ||
106 | } | ||
78 | } | 107 | } |
diff --git a/client/src/app/shared/video/video-actions-dropdown.component.ts b/client/src/app/shared/video/video-actions-dropdown.component.ts index 80407098b..afdeab18d 100644 --- a/client/src/app/shared/video/video-actions-dropdown.component.ts +++ b/client/src/app/shared/video/video-actions-dropdown.component.ts | |||
@@ -13,6 +13,7 @@ import { VideoReportComponent } from '@app/shared/video/modals/video-report.comp | |||
13 | import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklist.component' | 13 | import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklist.component' |
14 | import { VideoBlacklistService } from '@app/shared/video-blacklist' | 14 | import { VideoBlacklistService } from '@app/shared/video-blacklist' |
15 | import { ScreenService } from '@app/shared/misc/screen.service' | 15 | import { ScreenService } from '@app/shared/misc/screen.service' |
16 | import { VideoCaption } from '@shared/models' | ||
16 | 17 | ||
17 | export type VideoActionsDisplayType = { | 18 | export type VideoActionsDisplayType = { |
18 | playlist?: boolean | 19 | playlist?: boolean |
@@ -37,6 +38,7 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
37 | @ViewChild('videoBlacklistModal', { static: false }) videoBlacklistModal: VideoBlacklistComponent | 38 | @ViewChild('videoBlacklistModal', { static: false }) videoBlacklistModal: VideoBlacklistComponent |
38 | 39 | ||
39 | @Input() video: Video | VideoDetails | 40 | @Input() video: Video | VideoDetails |
41 | @Input() videoCaptions: VideoCaption[] = [] | ||
40 | 42 | ||
41 | @Input() displayOptions: VideoActionsDisplayType = { | 43 | @Input() displayOptions: VideoActionsDisplayType = { |
42 | playlist: false, | 44 | playlist: false, |
@@ -105,7 +107,7 @@ export class VideoActionsDropdownComponent implements OnChanges { | |||
105 | showDownloadModal () { | 107 | showDownloadModal () { |
106 | this.modalOpened.emit() | 108 | this.modalOpened.emit() |
107 | 109 | ||
108 | this.videoDownloadModal.show(this.video as VideoDetails) | 110 | this.videoDownloadModal.show(this.video as VideoDetails, this.videoCaptions) |
109 | } | 111 | } |
110 | 112 | ||
111 | showReportModal () { | 113 | showReportModal () { |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html index 246eac2dd..908611ddf 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html | |||
@@ -109,7 +109,7 @@ | |||
109 | </div> | 109 | </div> |
110 | 110 | ||
111 | <my-video-actions-dropdown | 111 | <my-video-actions-dropdown |
112 | placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" | 112 | placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" [videoCaptions]="videoCaptions" |
113 | (videoRemoved)="onVideoRemoved()" (modalOpened)="onModalOpened()" | 113 | (videoRemoved)="onVideoRemoved()" (modalOpened)="onModalOpened()" |
114 | ></my-video-actions-dropdown> | 114 | ></my-video-actions-dropdown> |
115 | </div> | 115 | </div> |