Add option to download subtitles in download modal

pull/2393/head
Rigel Kent 2020-01-07 16:53:57 +01:00 committed by Chocobozzz
parent 9b7668f527
commit 8ba9c205ba
5 changed files with 56 additions and 7 deletions

View File

@ -1,6 +1,17 @@
<ng-template #modal let-hide="close"> <ng-template #modal let-hide="close">
<div class="modal-header"> <div class="modal-header">
<h4 i18n class="modal-title">Download video</h4> <h4 i18n class="modal-title">Download
<span *ngIf="!videoCaptions" i18n>video</span>
<div *ngIf="videoCaptions" ngbDropdown class="d-inline-block">
<span id="dropdownDownloadType" ngbDropdownToggle i18n>
{{ type }}
</span>
<div ngbDropdownMenu aria-labelledby="dropdownDownloadType">
<button *ngIf="type === 'video'" (click)="switchToType('subtitles')" ngbDropdownItem i18n>subtitles</button>
<button *ngIf="type === 'subtitles'" (click)="switchToType('video')" ngbDropdownItem i18n>video</button>
</div>
</div>
</h4>
<my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon> <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
</div> </div>
@ -8,9 +19,12 @@
<div class="form-group"> <div class="form-group">
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<div class="input-group-prepend peertube-select-container"> <div class="input-group-prepend peertube-select-container">
<select [(ngModel)]="resolutionId"> <select *ngIf="type === 'video'" [(ngModel)]="resolutionId">
<option *ngFor="let file of getVideoFiles()" [value]="file.resolution.id">{{ file.resolution.label }}</option> <option *ngFor="let file of getVideoFiles()" [value]="file.resolution.id">{{ file.resolution.label }}</option>
</select> </select>
<select *ngIf="type === 'subtitles'" [(ngModel)]="subtitleLanguageId">
<option *ngFor="let caption of videoCaptions" [value]="caption.language.id">{{ caption.language.label }}</option>
</select>
</div> </div>
<input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getLink()" /> <input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getLink()" />
<div class="input-group-append"> <div class="input-group-append">
@ -21,7 +35,7 @@
</div> </div>
</div> </div>
<div class="download-type"> <div class="download-type" *ngIf="type === 'video'">
<div class="peertube-radio-container"> <div class="peertube-radio-container">
<input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct"> <input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct">
<label i18n for="download-direct">Direct download</label> <label i18n for="download-direct">Direct download</label>

View File

@ -13,6 +13,10 @@
} }
} }
#dropdownDownloadType {
cursor: pointer;
}
.download-type { .download-type {
margin-top: 30px; margin-top: 30px;

View File

@ -3,7 +3,9 @@ import { VideoDetails } from '../../../shared/video/video-details.model'
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { AuthService, Notifier } from '@app/core' import { AuthService, Notifier } from '@app/core'
import { VideoPrivacy } from '@shared/models' import { VideoPrivacy, VideoCaption } from '@shared/models'
type DownloadType = 'video' | 'subtitles'
@Component({ @Component({
selector: 'my-video-download', selector: 'my-video-download',
@ -15,10 +17,14 @@ export class VideoDownloadComponent {
downloadType: 'direct' | 'torrent' = 'torrent' downloadType: 'direct' | 'torrent' = 'torrent'
resolutionId: number | string = -1 resolutionId: number | string = -1
subtitleLanguageId: string
video: VideoDetails video: VideoDetails
videoCaptions: VideoCaption[]
activeModal: NgbActiveModal activeModal: NgbActiveModal
type: DownloadType = 'video'
constructor ( constructor (
private notifier: Notifier, private notifier: Notifier,
private modalService: NgbModal, private modalService: NgbModal,
@ -26,22 +32,31 @@ export class VideoDownloadComponent {
private i18n: I18n private i18n: I18n
) { } ) { }
get typeText () {
return this.type === 'video'
? this.i18n('video')
: this.i18n('subtitles')
}
getVideoFiles () { getVideoFiles () {
if (!this.video) return [] if (!this.video) return []
return this.video.getFiles() return this.video.getFiles()
} }
show (video: VideoDetails) { show (video: VideoDetails, videoCaptions?: VideoCaption[]) {
this.video = video this.video = video
this.videoCaptions = videoCaptions && videoCaptions.length ? videoCaptions : undefined
this.activeModal = this.modalService.open(this.modal) this.activeModal = this.modalService.open(this.modal)
this.resolutionId = this.getVideoFiles()[0].resolution.id this.resolutionId = this.getVideoFiles()[0].resolution.id
if (this.videoCaptions) this.subtitleLanguageId = this.videoCaptions[0].language.id
} }
onClose () { onClose () {
this.video = undefined this.video = undefined
this.videoCaptions = undefined
} }
download () { download () {
@ -50,6 +65,12 @@ export class VideoDownloadComponent {
} }
getLink () { getLink () {
return this.type === 'subtitles' && this.videoCaptions
? this.getSubtitlesLink()
: this.getVideoLink()
}
getVideoLink () {
// HTML select send us a string, so convert it to a number // HTML select send us a string, so convert it to a number
this.resolutionId = parseInt(this.resolutionId.toString(), 10) this.resolutionId = parseInt(this.resolutionId.toString(), 10)
@ -72,7 +93,15 @@ export class VideoDownloadComponent {
} }
} }
getSubtitlesLink () {
return window.location.origin + this.videoCaptions.find(caption => caption.language.id === this.subtitleLanguageId).captionPath
}
activateCopiedMessage () { activateCopiedMessage () {
this.notifier.success(this.i18n('Copied')) this.notifier.success(this.i18n('Copied'))
} }
switchToType (type: DownloadType) {
this.type = type
}
} }

View File

@ -13,6 +13,7 @@ import { VideoReportComponent } from '@app/shared/video/modals/video-report.comp
import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklist.component' import { VideoBlacklistComponent } from '@app/shared/video/modals/video-blacklist.component'
import { VideoBlacklistService } from '@app/shared/video-blacklist' import { VideoBlacklistService } from '@app/shared/video-blacklist'
import { ScreenService } from '@app/shared/misc/screen.service' import { ScreenService } from '@app/shared/misc/screen.service'
import { VideoCaption } from '@shared/models'
export type VideoActionsDisplayType = { export type VideoActionsDisplayType = {
playlist?: boolean playlist?: boolean
@ -37,6 +38,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
@ViewChild('videoBlacklistModal', { static: false }) videoBlacklistModal: VideoBlacklistComponent @ViewChild('videoBlacklistModal', { static: false }) videoBlacklistModal: VideoBlacklistComponent
@Input() video: Video | VideoDetails @Input() video: Video | VideoDetails
@Input() videoCaptions: VideoCaption[] = []
@Input() displayOptions: VideoActionsDisplayType = { @Input() displayOptions: VideoActionsDisplayType = {
playlist: false, playlist: false,
@ -105,7 +107,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
showDownloadModal () { showDownloadModal () {
this.modalOpened.emit() this.modalOpened.emit()
this.videoDownloadModal.show(this.video as VideoDetails) this.videoDownloadModal.show(this.video as VideoDetails, this.videoCaptions)
} }
showReportModal () { showReportModal () {

View File

@ -109,7 +109,7 @@
</div> </div>
<my-video-actions-dropdown <my-video-actions-dropdown
placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" [videoCaptions]="videoCaptions"
(videoRemoved)="onVideoRemoved()" (modalOpened)="onModalOpened()" (videoRemoved)="onVideoRemoved()" (modalOpened)="onModalOpened()"
></my-video-actions-dropdown> ></my-video-actions-dropdown>
</div> </div>