<div class="modal-content">
<div class="modal-header">
- <button type="button" class="close" aria-label="Close" (click)="cancel()">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="title-page title-page-single">{{ title }}</h4>
+ <span class="close" aria-hidden="true" (click)="cancel()"></span>
+ <h4 class="modal-title">{{ title }}</h4>
</div>
- <div class="modal-body" [innerHtml]="message"></div>
+ <div class="modal-body" >
+ <div [innerHtml]="message"></div>
- <div class="modal-footer">
- <button type="button" class="grey-button" data-dismiss="modal" (click)="cancel()">Cancel</button>
- <button type="button" class="orange-button" (click)="confirm()">Confirm</button>
+ <div class="form-group inputs">
+ <span class="action-button action-button-cancel" (click)="cancel()">
+ Cancel
+ </span>
+
+ <input
+ type="submit" value="Confirm" class="action-button-submit"
+ (click)="confirm()"
+ >
+ </div>
</div>
</div>
</div>
@import '_mixins';
textarea {
- @include peertube-input-text(100%);
+ @include peertube-textarea(100%, 150px);
- padding: 5px 15px;
- font-size: 15px;
- height: 150px;
margin-bottom: 15px;
}
<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
<div class="modal-dialog">
- <div class="modal-content modal-lg">
+ <div class="modal-content">
<div class="modal-header">
- <button type="button" class="close" aria-label="Close" (click)="hide()">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="title-page title-page-single">Download</h4>
+ <span class="close" aria-hidden="true" (click)="hide()"></span>
+ <h4 class="modal-title">Download video</h4>
</div>
<div class="modal-body">
- <div *ngFor="let file of video.files" class="resolution-block">
- <label>{{ file.resolutionLabel }}</label>
+ <div class="peertube-select-container">
+ <select [(ngModel)]="resolution">
+ <option *ngFor="let file of video.files" [value]="file.resolution">{{ file.resolutionLabel }}</option>
+ </select>
+ </div>
+
+ <div class="download-type">
+ <div class="peertube-radio-container">
+ <input type="radio" name="download" id="download-torrent" [(ngModel)]="downloadType" value="torrent">
+ <label for="download-torrent">Torrent</label>
+ </div>
+
+ <div class="peertube-radio-container">
+ <input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct">
+ <label for="download-direct">Direct download</label>
+ </div>
+ </div>
- <a class="orange-button-link " target="_blank" [href]="file.torrentUrl">
- <span class="icon icon-download"></span>
- Torrent file
- </a>
- <a class="orange-button-link" target="_blank" [href]="file.fileUrl">
- <span class="icon icon-download"></span>
- Download
- </a>
+ <div class="form-group inputs">
+ <span class="action-button action-button-cancel" (click)="hide()">
+ Cancel
+ </span>
- <!-- Don't display magnet URI for now, this is not compatible with most torrent clients -->
- <!--<input #magnetUriInput (click)="magnetUriInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="file.magnetUri" />-->
+ <input
+ type="submit" value="Download" class="action-button-submit"
+ (click)="download()"
+ >
</div>
</div>
</div>
@import '_variables';
@import '_mixins';
-.resolution-block:not(:first-child) {
- margin-top: 30px;
-}
-
-.orange-button-link {
- margin-right: 10px;
+.peertube-select-container {
+ @include peertube-select-container(130px);
}
-label {
- display: block;
-}
-
-.icon {
- @include icon(21px);
+.download-type {
+ margin-top: 30px;
- margin-right: 5px;
- position: relative;
- top: -1px;
+ .peertube-radio-container {
+ @include peertube-radio-container;
- &.icon-download {
- background-image: url('../../../assets/images/video/download-white.svg');
+ display: inline-block;
+ margin-right: 30px;
}
}
-import { Component, Input, ViewChild } from '@angular/core'
+import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { ModalDirective } from 'ngx-bootstrap/modal'
import { VideoDetails } from '../../shared/video/video-details.model'
templateUrl: './video-download.component.html',
styleUrls: [ './video-download.component.scss' ]
})
-export class VideoDownloadComponent {
+export class VideoDownloadComponent implements OnInit {
@Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective
+ downloadType: 'direct' | 'torrent' = 'torrent'
+ resolution = -1
+
constructor () {
// empty
}
+ ngOnInit () {
+ this.resolution = this.video.files[0].resolution
+ }
+
show () {
this.modal.show()
}
hide () {
this.modal.hide()
}
+
+ download () {
+ const file = this.video.files.find(f => f.resolution === this.resolution)
+ if (!file) {
+ console.error('Could not find file with resolution %d.', this.resolution)
+ return
+ }
+
+ const link = this.downloadType === 'direct' ? file.fileUrl : file.torrentUrl
+ window.open(link)
+ }
}
<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
<div class="modal-dialog">
- <div class="modal-content modal-lg">
+ <div class="modal-content">
<div class="modal-header">
- <button type="button" class="close" aria-label="Close" (click)="hide()">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="title-page title-page-single">Report video</h4>
+ <span class="close" aria-hidden="true" (click)="hide()"></span>
+ <h4 class="modal-title">Report video</h4>
</div>
<div class="modal-body">
<form novalidate [formGroup]="form" (ngSubmit)="report()">
<div class="form-group">
- <label for="reason">Reason</label>
- <textarea
- id="reason" class="form-control" placeholder="Reason..."
- formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }"
- >
+ <textarea placeholder="Reason..." formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }">
</textarea>
<div *ngIf="formErrors.reason" class="form-error">
{{ formErrors.reason }}
</div>
</div>
- <div class="form-group">
+ <div class="form-group inputs">
+ <span class="action-button action-button-cancel" (click)="hide()">
+ Cancel
+ </span>
+
<input
- type="submit" value="Report" class="orange-button"
+ type="submit" value="Submit" class="action-button-submit"
[disabled]="!form.valid"
>
</div>
--- /dev/null
+@import '_variables';
+@import '_mixins';
+
+textarea {
+ @include peertube-textarea(100%, 60px);
+}
@Component({
selector: 'my-video-report',
- templateUrl: './video-report.component.html'
+ templateUrl: './video-report.component.html',
+ styleUrls: [ './video-report.component.scss' ]
})
export class VideoReportComponent extends FormReactive implements OnInit {
@Input() video: VideoDetails = null
<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
- <div class="modal-dialog modal-lg">
+ <div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
- <button type="button" class="close" aria-label="Close" (click)="hide()">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="title-page title-page-single">Share</h4>
+ <span class="close" aria-hidden="true" (click)="hide()"></span>
+ <h4 class="modal-title">Share</h4>
</div>
<div class="modal-body">
<div *ngIf="notSecure()" class="alert alert-warning">
The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites).
</div>
+
+ <div class="form-group inputs">
+ <span class="action-button action-button-cancel" (click)="hide()">
+ Cancel
+ </span>
+ </div>
</div>
</div>
</div>
+.action-button-cancel {
+ margin-right: 0 !important;
+}
.action-more {
display: inline-block;
- .dropdown-menu .icon {
- display: inline-block;
- background-repeat: no-repeat;
- background-size: contain;
- width: 21px;
- height: 21px;
- vertical-align: middle;
- margin-right: 5px;
- position: relative;
- top: -1px;
+ .dropdown-menu .dropdown-item {
+ padding: 6px 24px;
- &.icon-download {
- background-image: url('../../../assets/images/video/download-grey.svg');
- }
+ .icon {
+ @include icon(24px);
- &.icon-alert {
- background-image: url('../../../assets/images/video/alert.svg');
- }
+ margin-right: 10px;
+ position: relative;
+ top: -1px;
+
+ &.icon-download {
+ background-image: url('../../../assets/images/video/download-black.svg');
+ }
+
+ &.icon-alert {
+ background-image: url('../../../assets/images/video/alert.svg');
+ }
- &.icon-blacklist {
- background-image: url('../../../assets/images/video/eye-closed.svg');
+ &.icon-blacklist {
+ background-image: url('../../../assets/images/video/blacklist.svg');
+ }
}
}
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
+ <g id="Artboard-4" transform="translate(-312.000000, -115.000000)" stroke="#585858" stroke-width="2">
+ <g id="7" transform="translate(312.000000, 115.000000)">
+ <path d="M19,5 L5,19" id="Path-14"></path>
+ <path d="M19,5 L5,19" id="Path-14" transform="translate(12.000000, 12.000000) scale(-1, 1) translate(-12.000000, -12.000000) "></path>
+ </g>
+ </g>
+ </g>
+</svg>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard-4" transform="translate(-48.000000, -467.000000)">
<g id="161" transform="translate(48.000000, 467.000000)">
- <path d="M12.8715755,3.50973876 L12,1.96027114 L11.1284245,3.50973876 L2.12842446,19.5097388 L1.29015252,21 L3,21 L21,21 L22.7098475,21 L21.8715755,19.5097388 L12.8715755,3.50973876 Z" id="Triangle-2" stroke="#585858" stroke-width="2" stroke-linejoin="round"></path>
- <path d="M12,17.75 C12.6903559,17.75 13.25,17.1903559 13.25,16.5 C13.25,15.8096441 12.6903559,15.25 12,15.25 C11.3096441,15.25 10.75,15.8096441 10.75,16.5 C10.75,17.1903559 11.3096441,17.75 12,17.75 Z" id="Oval-8" fill="#585858"></path>
- <rect id="Rectangle-3" fill="#585858" x="11" y="9" width="2" height="5" rx="1"></rect>
+ <path d="M12.8715755,3.50973876 L12,1.96027114 L11.1284245,3.50973876 L2.12842446,19.5097388 L1.29015252,21 L3,21 L21,21 L22.7098475,21 L21.8715755,19.5097388 L12.8715755,3.50973876 Z" id="Triangle-2" stroke="#000000" stroke-width="2" stroke-linejoin="round"></path>
+ <path d="M12,17.75 C12.6903559,17.75 13.25,17.1903559 13.25,16.5 C13.25,15.8096441 12.6903559,15.25 12,15.25 C11.3096441,15.25 10.75,15.8096441 10.75,16.5 C10.75,17.1903559 11.3096441,17.75 12,17.75 Z" id="Oval-8" fill="#000000"></path>
+ <rect id="Rectangle-3" fill="#000000" x="11" y="9" width="2" height="5" rx="1"></rect>
</g>
</g>
</g>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
+ <title>no</title>
+ <desc>Created with Sketch.</desc>
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Artboard-4" transform="translate(-312.000000, -863.000000)" stroke="#000000" stroke-width="2">
+ <g id="347" transform="translate(312.000000, 863.000000)">
+ <circle id="Oval-196" cx="12" cy="12" r="9"></circle>
+ <path d="M18,18 L6,6" id="Path-275"></path>
+ </g>
+ </g>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
+ <title>download</title>
+ <desc>Created with Sketch.</desc>
+ <defs></defs>
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
+ <g id="Artboard-4" transform="translate(-180.000000, -291.000000)" stroke="#000000" stroke-width="2">
+ <g id="84" transform="translate(180.000000, 291.000000)">
+ <path d="M12,3 L12,15" id="Path-58"></path>
+ <polyline id="Path-59" stroke-linejoin="round" transform="translate(12.000000, 14.000000) rotate(-270.000000) translate(-12.000000, -14.000000) " points="9 8 15 14 9 20"></polyline>
+ <path d="M3,18 L3,20.0590859 C3,20.6127331 3.44494889,21.0615528 3.99340349,21.0615528 L20.0067018,21.0615528 C20.5553434,21.0615528 21.0001052,20.6098102 21.0001051,20.0590859 L21.0001049,18" id="Path-12" stroke-linejoin="round"></path>
+ </g>
+ </g>
+ </g>
+</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <defs></defs>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
- <g id="Artboard-4" transform="translate(-796.000000, -1046.000000)" stroke="#585858" stroke-width="2">
- <g id="Extras" transform="translate(48.000000, 1046.000000)">
- <g id="eye-closed" transform="translate(760.000000, 12.000000) scale(1, -1) translate(-760.000000, -12.000000) translate(748.000000, 0.000000)">
- <path d="M2,14 C2,14 5,7 12,7 C19,7 22,14 22,14" id="Path-80" stroke-linejoin="round"></path>
- <path d="M12,7 L12,5" id="Path-81"></path>
- <path d="M18,8.5 L19,7" id="Path-81"></path>
- <path d="M21,12 L22.5,11" id="Path-81"></path>
- <path d="M1.5,12 L3,11" id="Path-81" transform="translate(2.250000, 11.500000) scale(1, -1) translate(-2.250000, -11.500000) "></path>
- <path d="M5,8.5 L6,7" id="Path-81" transform="translate(5.500000, 7.750000) scale(-1, 1) translate(-5.500000, -7.750000) "></path>
- </g>
- </g>
- </g>
- </g>
-</svg>
.modal {
.modal-header {
border-bottom: none;
+ margin-bottom: 5px;
- .title-page-single {
- margin: 0;
+ .modal-title {
+ font-size: 20px;
+ font-weight: $font-semibold;
+ }
+
+ .close {
+ @include icon(24px);
+
+ position: relative;
+ right: -1px;
+ float: right;
+ background-image: url('../assets/images/global/cross.svg');
+ }
+ }
+
+ .inputs {
+ margin-top: 40px;
+ margin-bottom: 0;
+ text-align: right;
+
+ .action-button-cancel {
+ @include peertube-button;
+ @include grey-button;
+
+ display: inline-block;
+ margin-right: 10px;
+ }
+
+ .action-button-submit {
+ @include peertube-button;
+ @include orange-button;
}
}
}
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/panels";
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed";
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/wells";
-@import "~bootstrap-sass/assets/stylesheets/bootstrap/close";
+//@import "~bootstrap-sass/assets/stylesheets/bootstrap/close";
// Components w/ JavaScript
@import "~bootstrap-sass/assets/stylesheets/bootstrap/modals";
}
}
+@mixin peertube-textarea ($width, $height) {
+ @include peertube-input-text($width);
+
+ height: $height;
+ padding: 5px 15px;
+ font-size: 15px;
+}
+
@mixin orange-button {
&, &:active, &:focus {
color: #fff;
overflow: hidden;
background: #fff;
position: relative;
+ font-size: 15px;
&:after {
top: 50%;
}
}
+// Thanks: https://codepen.io/triss90/pen/XNEdRe/
+@mixin peertube-radio-container {
+ input[type="radio"] {
+ display: none;
+
+ & + label {
+ font-weight: $font-regular;
+ cursor: pointer;
+
+ &:before {
+ position: relative;
+ top: -2px;
+ content: '';
+ background: #fff;
+ border-radius: 100%;
+ border: 1px solid #000;
+ display: inline-block;
+ width: 15px;
+ height: 15px;
+ vertical-align: middle;
+ cursor: pointer;
+ text-align: center;
+ margin-right: 10px;
+ }
+ }
+
+ &:checked + label:before {
+ background-color: #000;
+ box-shadow: inset 0 0 0 4px #fff;
+ }
+
+ &:focus + label:before {
+ outline: none;
+ border-color: #000;
+ }
+ }
+}
+
@mixin peertube-checkbox ($border-width) {
display: none;
}
private async loadPreviews (key: string) {
- const video = await VideoModel.loadByUUID(key)
+ const video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(key)
if (!video) return undefined
if (video.isOwned()) throw new Error('Cannot load preview of owned video.')