1
0
Fork 0

show less information by default in download modal (#3890)

* client(video/download): collapse advanced informaton by default
* fix(client/video-dl): update metadata upon resolution change

closes #3810

Co-authored-by: Rigel Kent <par@rigelk.eu>
This commit is contained in:
kontrollanten 2021-03-29 13:51:33 +02:00 committed by GitHub
parent f076d49f37
commit cf3c36247d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 143 additions and 76 deletions

View file

@ -17,22 +17,12 @@
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="alert alert-warning" *ngIf="isConfidentialVideo()" i18n>
<div class="alert alert-warning" *ngIf="isConfidentialVideo()" i18n> The following link contains a private token and should not be shared with anyone.
The following link contains a private token and should not be shared with anyone. </div>
</div>
<ng-container *ngIf="type === 'subtitles'">
<div class="input-group input-group-sm"> <div class="input-group input-group-sm">
<div class="input-group-prepend peertube-select-container">
<select *ngIf="type === 'video'" [(ngModel)]="resolutionId" (ngModelChange)="onResolutionIdChange()">
<option *ngFor="let file of getVideoFiles()" [value]="file.resolution.id">{{ file.resolution.label }}</option>
</select>
<select *ngIf="type === 'subtitles'" [(ngModel)]="subtitleLanguageId">
<option *ngFor="let caption of videoCaptions" [value]="caption.language.id">{{ caption.language.label }}</option>
</select>
</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" *ngIf="!isConfidentialVideo()"> <div class="input-group-append" *ngIf="!isConfidentialVideo()">
<button [cdkCopyToClipboard]="urlInput.value" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary"> <button [cdkCopyToClipboard]="urlInput.value" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
@ -40,62 +30,103 @@
</button> </button>
</div> </div>
</div> </div>
</div>
<ng-container *ngIf="type === 'video' && videoFile?.metadata">
<div ngbNav #nav="ngbNav" class="nav-tabs">
<ng-container ngbNavItem>
<a ngbNavLink i18n>Format</a>
<ng-template ngbNavContent>
<div class="file-metadata">
<div class="metadata-attribute metadata-attribute-tags" *ngFor="let item of videoFileMetadataFormat | keyvalue">
<span i18n class="metadata-attribute-label">{{ item.value.label }}</span>
<span class="metadata-attribute-value">{{ item.value.value }}</span>
</div>
</div>
</ng-template>
</ng-container>
<ng-container ngbNavItem [disabled]="videoFileMetadataVideoStream === undefined">
<a ngbNavLink i18n>Video stream</a>
<ng-template ngbNavContent>
<div class="file-metadata">
<div class="metadata-attribute metadata-attribute-tags" *ngFor="let item of videoFileMetadataVideoStream | keyvalue">
<span i18n class="metadata-attribute-label">{{ item.value.label }}</span>
<span class="metadata-attribute-value">{{ item.value.value }}</span>
</div>
</div>
</ng-template>
</ng-container>
<ng-container ngbNavItem [disabled]="videoFileMetadataAudioStream === undefined">
<a ngbNavLink i18n>Audio stream</a>
<ng-template ngbNavContent>
<div class="file-metadata">
<div class="metadata-attribute metadata-attribute-tags" *ngFor="let item of videoFileMetadataAudioStream | keyvalue">
<span i18n class="metadata-attribute-label">{{ item.value.label }}</span>
<span class="metadata-attribute-value">{{ item.value.value }}</span>
</div>
</div>
</ng-template>
</ng-container>
</div>
<div [ngbNavOutlet]="nav"></div>
</ng-container> </ng-container>
<div class="download-type" *ngIf="type === 'video'"> <ng-container *ngIf="type === 'video'">
<div class="peertube-radio-container"> <div ngbNav #resolutionNav="ngbNav" class="nav-tabs" [activeId]="resolutionId" (activeIdChange)="onResolutionIdChange($event)">
<input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct">
<label i18n for="download-direct">Direct download</label> <ng-container *ngFor="let file of getVideoFiles()" [ngbNavItem]="file.resolution.id">
<a ngbNavLink i18n>{{ file.resolution.label }}</a>
<ng-template ngbNavContent>
<div class="nav-content">
<div class="input-group input-group-sm">
<input #urlInput (click)="urlInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="getLink()" />
<div class="input-group-append" *ngIf="!isConfidentialVideo()">
<button [cdkCopyToClipboard]="urlInput.value" (click)="activateCopiedMessage()" type="button" class="btn btn-outline-secondary">
<span class="glyphicon glyphicon-duplicate"></span>
</button>
</div>
</div>
</div>
</ng-template>
</ng-container>
</div>
<div [ngbNavOutlet]="resolutionNav"></div>
<div class="advanced-filters collapse-transition" [ngbCollapse]="isAdvancedCustomizationCollapsed">
<ng-container *ngIf="videoFile?.metadata">
<div ngbNav #nav="ngbNav" class="nav-tabs nav-metadata">
<ng-container ngbNavItem>
<a ngbNavLink i18n>Format</a>
<ng-template ngbNavContent>
<div class="file-metadata">
<div class="metadata-attribute metadata-attribute-tags" *ngFor="let item of videoFileMetadataFormat | keyvalue">
<span i18n class="metadata-attribute-label">{{ item.value.label }}</span>
<span class="metadata-attribute-value">{{ item.value.value }}</span>
</div>
</div>
</ng-template>
<ng-container ngbNavItem [disabled]="videoFileMetadataVideoStream === undefined">
<a ngbNavLink i18n>Video stream</a>
<ng-template ngbNavContent>
<div class="file-metadata">
<div class="metadata-attribute metadata-attribute-tags" *ngFor="let item of videoFileMetadataVideoStream | keyvalue">
<span i18n class="metadata-attribute-label">{{ item.value.label }}</span>
<span class="metadata-attribute-value">{{ item.value.value }}</span>
</div>
</div>
</ng-template>
</ng-container>
<ng-container ngbNavItem [disabled]="videoFileMetadataAudioStream === undefined">
<a ngbNavLink i18n>Audio stream</a>
<ng-template ngbNavContent>
<div class="file-metadata">
<div class="metadata-attribute metadata-attribute-tags" *ngFor="let item of videoFileMetadataAudioStream | keyvalue">
<span i18n class="metadata-attribute-label">{{ item.value.label }}</span>
<span class="metadata-attribute-value">{{ item.value.value }}</span>
</div>
</div>
</ng-template>
</ng-container>
</ng-container>
</div>
<div [ngbNavOutlet]="nav"></div>
<div class="download-type">
<div class="peertube-radio-container">
<input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct">
<label i18n for="download-direct">Direct download</label>
</div>
<div class="peertube-radio-container">
<input type="radio" name="download" id="download-torrent" [(ngModel)]="downloadType" value="torrent">
<label i18n for="download-torrent">Torrent (.torrent file)</label>
</div>
</div>
</ng-container>
</div> </div>
<div class="peertube-radio-container"> <div (click)="isAdvancedCustomizationCollapsed = !isAdvancedCustomizationCollapsed" role="button" class="advanced-filters-button"
<input type="radio" name="download" id="download-torrent" [(ngModel)]="downloadType" value="torrent"> [attr.aria-expanded]="!isAdvancedCustomizationCollapsed" aria-controls="collapseBasic">
<label i18n for="download-torrent">Torrent (.torrent file)</label> <ng-container *ngIf="isAdvancedCustomizationCollapsed">
<span class="glyphicon glyphicon-menu-down"></span>
<ng-container i18n>
Advanced
</ng-container>
</ng-container>
<ng-container *ngIf="!isAdvancedCustomizationCollapsed">
<span class="glyphicon glyphicon-menu-up"></span>
<ng-container i18n>
Simple
</ng-container>
</ng-container>
</div> </div>
</div> </ng-container>
</div> </div>
<div class="modal-footer inputs"> <div class="modal-footer inputs">

View file

@ -1,6 +1,28 @@
@import 'variables'; @import 'variables';
@import 'mixins'; @import 'mixins';
.nav-content {
margin-top: 30px;
}
.advanced-filters-button {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
.nav-tabs {
margin-top: 10x;
}
.glyphicon {
margin-right: 5px;
}
}
.peertube-select-container { .peertube-select-container {
@include peertube-select-container(85px); @include peertube-select-container(85px);
@ -15,12 +37,21 @@
} }
} }
.action-button-cancel {
@include peertube-button-link;
}
.action-button-submit {
@include peertube-button-link;
@include orange-button;
}
#dropdownDownloadType { #dropdownDownloadType {
cursor: pointer; cursor: pointer;
} }
.download-type { .download-type {
margin-top: 30px; margin-top: 20px;
.peertube-radio-container { .peertube-radio-container {
@include peertube-radio-container; @include peertube-radio-container;
@ -30,6 +61,10 @@
} }
} }
.nav-metadata {
margin-top: 20px;
}
.file-metadata { .file-metadata {
padding: 1rem; padding: 1rem;
} }

View file

@ -30,6 +30,8 @@ export class VideoDownloadComponent {
videoCaptions: VideoCaption[] videoCaptions: VideoCaption[]
activeModal: NgbModalRef activeModal: NgbModalRef
isAdvancedCustomizationCollapsed = true
type: DownloadType = 'video' type: DownloadType = 'video'
private bytesPipe: BytesPipe private bytesPipe: BytesPipe
@ -65,8 +67,7 @@ export class VideoDownloadComponent {
this.activeModal = this.modalService.open(this.modal, { centered: true }) this.activeModal = this.modalService.open(this.modal, { centered: true })
this.resolutionId = this.getVideoFiles()[0].resolution.id this.onResolutionIdChange(this.getVideoFiles()[0].resolution.id)
this.onResolutionIdChange()
if (this.videoCaptions) this.subtitleLanguageId = this.videoCaptions[0].language.id if (this.videoCaptions) this.subtitleLanguageId = this.videoCaptions[0].language.id
@ -91,12 +92,15 @@ export class VideoDownloadComponent {
: this.getVideoFileLink() : this.getVideoFileLink()
} }
async onResolutionIdChange () { async onResolutionIdChange (resolutionId: number) {
this.resolutionId = resolutionId
this.videoFile = this.getVideoFile() this.videoFile = this.getVideoFile()
if (this.videoFile.metadata || !this.videoFile.metadataUrl) return
await this.hydrateMetadataFromMetadataUrl(this.videoFile) if (!this.videoFile.metadata) {
if (!this.videoFile.metadata) return if (!this.videoFile.metadataUrl) return
await this.hydrateMetadataFromMetadataUrl(this.videoFile)
}
this.videoFileMetadataFormat = this.videoFile this.videoFileMetadataFormat = this.videoFile
? this.getMetadataFormat(this.videoFile.metadata.format) ? this.getMetadataFormat(this.videoFile.metadata.format)
@ -110,9 +114,6 @@ export class VideoDownloadComponent {
} }
getVideoFile () { getVideoFile () {
// HTML select send us a string, so convert it to a number
this.resolutionId = parseInt(this.resolutionId.toString(), 10)
const file = this.getVideoFiles().find(f => f.resolution.id === this.resolutionId) const file = this.getVideoFiles().find(f => f.resolution.id === this.resolutionId)
if (!file) { if (!file) {
console.error('Could not find file with resolution %d.', this.resolutionId) console.error('Could not find file with resolution %d.', this.resolutionId)