diff options
author | Rigel Kent <sendmemail@rigelk.eu> | 2020-04-03 00:22:04 +0200 |
---|---|---|
committer | Rigel Kent <sendmemail@rigelk.eu> | 2020-04-03 00:22:06 +0200 |
commit | c9ff8a08a06ef0f30ec4963aebfcc02293ca20c5 (patch) | |
tree | dc2899aff59d56b40dac81fabd90d863b1586331 | |
parent | b515c98c6b674ee5632f3f76ad4fe00e147d995e (diff) | |
download | PeerTube-c9ff8a08a06ef0f30ec4963aebfcc02293ca20c5.tar.gz PeerTube-c9ff8a08a06ef0f30ec4963aebfcc02293ca20c5.tar.zst PeerTube-c9ff8a08a06ef0f30ec4963aebfcc02293ca20c5.zip |
Support drag and drop for video upload and torrent file import
9 files changed, 64 insertions, 17 deletions
diff --git a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html b/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html index 4262ff0fc..ada32e3fd 100644 --- a/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html +++ b/client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html | |||
@@ -9,7 +9,7 @@ | |||
9 | <div class="modal-body"> | 9 | <div class="modal-body"> |
10 | <label i18n for="language">Language</label> | 10 | <label i18n for="language">Language</label> |
11 | <div class="peertube-select-container"> | 11 | <div class="peertube-select-container"> |
12 | <select id="language" formControlName="language"> | 12 | <select id="language" formControlName="language" class="form-control"> |
13 | <option></option> | 13 | <option></option> |
14 | <option *ngFor="let language of videoCaptionLanguages" [value]="language.id">{{ language.label }}</option> | 14 | <option *ngFor="let language of videoCaptionLanguages" [value]="language.id">{{ language.label }}</option> |
15 | </select> | 15 | </select> |
diff --git a/client/src/app/videos/+video-edit/video-add-components/drag-drop.directive.ts b/client/src/app/videos/+video-edit/video-add-components/drag-drop.directive.ts new file mode 100644 index 000000000..07c7d34ac --- /dev/null +++ b/client/src/app/videos/+video-edit/video-add-components/drag-drop.directive.ts | |||
@@ -0,0 +1,30 @@ | |||
1 | import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core' | ||
2 | |||
3 | @Directive({ | ||
4 | selector: '[dragDrop]' | ||
5 | }) | ||
6 | export class DragDropDirective { | ||
7 | @Output() onFileDropped = new EventEmitter<FileList>() | ||
8 | |||
9 | @HostBinding('class.dragover') dragover = false | ||
10 | |||
11 | @HostListener('dragover', ['$event']) onDragOver(e: Event) { | ||
12 | e.preventDefault() | ||
13 | e.stopPropagation() | ||
14 | this.dragover = true | ||
15 | } | ||
16 | |||
17 | @HostListener('dragleave', ['$event']) public onDragLeave(e: Event) { | ||
18 | e.preventDefault() | ||
19 | e.stopPropagation() | ||
20 | this.dragover = false | ||
21 | } | ||
22 | |||
23 | @HostListener('drop', ['$event']) public ondrop(e: DragEvent) { | ||
24 | e.preventDefault() | ||
25 | e.stopPropagation() | ||
26 | this.dragover = false | ||
27 | let files = e.dataTransfer.files | ||
28 | if (files.length > 0) this.onFileDropped.emit(files) | ||
29 | } | ||
30 | } | ||
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html index c290fd4b1..1d9384161 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html | |||
@@ -1,14 +1,13 @@ | |||
1 | <div *ngIf="!hasImportedVideo" class="upload-video-container"> | 1 | <div *ngIf="!hasImportedVideo" class="upload-video-container" dragDrop (onFileDropped)="setTorrentFile($event)"> |
2 | <div class="first-step-block"> | 2 | <div class="first-step-block"> |
3 | <my-global-icon class="upload-icon" iconName="upload"></my-global-icon> | 3 | <my-global-icon class="upload-icon" iconName="upload"></my-global-icon> |
4 | 4 | ||
5 | <div class="button-file"> | 5 | <div class="button-file form-control" [ngbTooltip]="'(extensions: .torrent)'"> |
6 | <span i18n>Select the torrent to import</span> | 6 | <span i18n>Select the torrent to import</span> |
7 | <input #torrentfileInput type="file" name="torrentfile" id="torrentfile" accept=".torrent" (change)="fileChange()" /> | 7 | <input #torrentfileInput type="file" name="torrentfile" id="torrentfile" accept=".torrent" (change)="fileChange()" /> |
8 | </div> | 8 | </div> |
9 | <span class="button-file-extension">(.torrent)</span> | ||
10 | 9 | ||
11 | <div class="torrent-or-magnet" i18n>Or</div> | 10 | <div class="torrent-or-magnet" i18n-data-content data-content="OR"></div> |
12 | 11 | ||
13 | <div class="form-group form-group-magnet-uri"> | 12 | <div class="form-group form-group-magnet-uri"> |
14 | <label i18n for="magnetUri">Paste magnet URI</label> | 13 | <label i18n for="magnetUri">Paste magnet URI</label> |
@@ -21,13 +20,13 @@ | |||
21 | </ng-template> | 20 | </ng-template> |
22 | </my-help> | 21 | </my-help> |
23 | 22 | ||
24 | <input type="text" id="magnetUri" [(ngModel)]="magnetUri" /> | 23 | <input type="text" id="magnetUri" [(ngModel)]="magnetUri" class="form-control" /> |
25 | </div> | 24 | </div> |
26 | 25 | ||
27 | <div class="form-group"> | 26 | <div class="form-group"> |
28 | <label i18n for="first-step-channel">Channel</label> | 27 | <label i18n for="first-step-channel">Channel</label> |
29 | <div class="peertube-select-container"> | 28 | <div class="peertube-select-container"> |
30 | <select id="first-step-channel" [(ngModel)]="firstStepChannelId"> | 29 | <select id="first-step-channel" [(ngModel)]="firstStepChannelId" class="form-control"> |
31 | <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option> | 30 | <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option> |
32 | </select> | 31 | </select> |
33 | </div> | 32 | </div> |
@@ -36,7 +35,7 @@ | |||
36 | <div class="form-group"> | 35 | <div class="form-group"> |
37 | <label i18n for="first-step-privacy">Privacy</label> | 36 | <label i18n for="first-step-privacy">Privacy</label> |
38 | <div class="peertube-select-container"> | 37 | <div class="peertube-select-container"> |
39 | <select id="first-step-privacy" [(ngModel)]="firstStepPrivacyId"> | 38 | <select id="first-step-privacy" [(ngModel)]="firstStepPrivacyId" class="form-control"> |
40 | <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option> | 39 | <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option> |
41 | </select> | 40 | </select> |
42 | </div> | 41 | </div> |
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts index e47624dd6..4d0b0b080 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts | |||
@@ -72,6 +72,11 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Ca | |||
72 | this.importVideo(torrentfile) | 72 | this.importVideo(torrentfile) |
73 | } | 73 | } |
74 | 74 | ||
75 | setTorrentFile (files: FileList) { | ||
76 | this.torrentfileInput.nativeElement.files = files | ||
77 | this.fileChange() | ||
78 | } | ||
79 | |||
75 | importVideo (torrentfile?: Blob) { | 80 | importVideo (torrentfile?: Blob) { |
76 | this.isImportingVideo = true | 81 | this.isImportingVideo = true |
77 | 82 | ||
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html index 09d0b8272..9a26fe308 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html +++ b/client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html | |||
@@ -15,13 +15,13 @@ | |||
15 | </ng-template> | 15 | </ng-template> |
16 | </my-help> | 16 | </my-help> |
17 | 17 | ||
18 | <input type="text" id="targetUrl" [(ngModel)]="targetUrl" /> | 18 | <input type="text" id="targetUrl" [(ngModel)]="targetUrl" class="form-control" /> |
19 | </div> | 19 | </div> |
20 | 20 | ||
21 | <div class="form-group"> | 21 | <div class="form-group"> |
22 | <label i18n for="first-step-channel">Channel</label> | 22 | <label i18n for="first-step-channel">Channel</label> |
23 | <div class="peertube-select-container"> | 23 | <div class="peertube-select-container"> |
24 | <select id="first-step-channel" [(ngModel)]="firstStepChannelId"> | 24 | <select id="first-step-channel" [(ngModel)]="firstStepChannelId" class="form-control"> |
25 | <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option> | 25 | <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option> |
26 | </select> | 26 | </select> |
27 | </div> | 27 | </div> |
@@ -30,7 +30,7 @@ | |||
30 | <div class="form-group"> | 30 | <div class="form-group"> |
31 | <label i18n for="first-step-privacy">Privacy</label> | 31 | <label i18n for="first-step-privacy">Privacy</label> |
32 | <div class="peertube-select-container"> | 32 | <div class="peertube-select-container"> |
33 | <select id="first-step-privacy" [(ngModel)]="firstStepPrivacyId"> | 33 | <select id="first-step-privacy" [(ngModel)]="firstStepPrivacyId" class="form-control"> |
34 | <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option> | 34 | <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option> |
35 | </select> | 35 | </select> |
36 | </div> | 36 | </div> |
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.html b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.html index b4e1ceeca..8db441a8c 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.html +++ b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.html | |||
@@ -1,8 +1,8 @@ | |||
1 | <div *ngIf="!isUploadingVideo" class="upload-video-container"> | 1 | <div *ngIf="!isUploadingVideo" class="upload-video-container" dragDrop (onFileDropped)="setVideoFile($event)"> |
2 | <div class="first-step-block"> | 2 | <div class="first-step-block"> |
3 | <my-global-icon class="upload-icon" iconName="upload"></my-global-icon> | 3 | <my-global-icon class="upload-icon" iconName="upload"></my-global-icon> |
4 | 4 | ||
5 | <div class="button-file form-control" [ngbTooltip]="'(extensions: ' + videoExtensions + ')'" container="body"> | 5 | <div class="button-file form-control" [ngbTooltip]="'(extensions: ' + videoExtensions + ')'"> |
6 | <span i18n>Select the file to upload</span> | 6 | <span i18n>Select the file to upload</span> |
7 | <input #videofileInput type="file" name="videofile" id="videofile" [accept]="videoExtensions" (change)="fileChange()" autofocus /> | 7 | <input #videofileInput type="file" name="videofile" id="videofile" [accept]="videoExtensions" (change)="fileChange()" autofocus /> |
8 | </div> | 8 | </div> |
diff --git a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts index ee4aa7b53..802345945 100644 --- a/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts +++ b/client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts | |||
@@ -108,6 +108,11 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy | |||
108 | return this.videofileInput.nativeElement.files[0] | 108 | return this.videofileInput.nativeElement.files[0] |
109 | } | 109 | } |
110 | 110 | ||
111 | setVideoFile (files: FileList) { | ||
112 | this.videofileInput.nativeElement.files = files | ||
113 | this.fileChange() | ||
114 | } | ||
115 | |||
111 | getAudioUploadLabel () { | 116 | getAudioUploadLabel () { |
112 | const videofile = this.getVideoFile() | 117 | const videofile = this.getVideoFile() |
113 | if (!videofile) return this.i18n('Upload') | 118 | if (!videofile) return this.i18n('Upload') |
diff --git a/client/src/app/videos/+video-edit/video-add.component.scss b/client/src/app/videos/+video-edit/video-add.component.scss index 9d068afde..c20467d9b 100644 --- a/client/src/app/videos/+video-edit/video-add.component.scss +++ b/client/src/app/videos/+video-edit/video-add.component.scss | |||
@@ -40,14 +40,19 @@ $border-color: #EAEAEA; | |||
40 | 40 | ||
41 | ::ng-deep .upload-video-container { | 41 | ::ng-deep .upload-video-container { |
42 | border: $border-width $border-type $border-color; | 42 | border: $border-width $border-type $border-color; |
43 | border-top: none; | 43 | border-top: transparent; |
44 | 44 | ||
45 | background-color: var(--submenuColor); | 45 | background-color: var(--submenuColor); |
46 | border-radius: 3px; | 46 | border-bottom-left-radius: 3px; |
47 | border-bottom-right-radius: 3px; | ||
47 | width: 100%; | 48 | width: 100%; |
48 | min-height: 440px; | 49 | min-height: 440px; |
49 | padding-bottom: 20px; | 50 | padding-bottom: 20px; |
50 | display: flex; | 51 | display: flex; |
51 | justify-content: center; | 52 | justify-content: center; |
52 | align-items: center; | 53 | align-items: center; |
54 | |||
55 | &.dragover { | ||
56 | border: 3px dashed var(--mainColor); | ||
57 | } | ||
53 | } | 58 | } |
diff --git a/client/src/app/videos/+video-edit/video-add.module.ts b/client/src/app/videos/+video-edit/video-add.module.ts index 911404bad..b8f5a9a47 100644 --- a/client/src/app/videos/+video-edit/video-add.module.ts +++ b/client/src/app/videos/+video-edit/video-add.module.ts | |||
@@ -3,6 +3,7 @@ import { SharedModule } from '../../shared' | |||
3 | import { VideoEditModule } from './shared/video-edit.module' | 3 | import { VideoEditModule } from './shared/video-edit.module' |
4 | import { VideoAddRoutingModule } from './video-add-routing.module' | 4 | import { VideoAddRoutingModule } from './video-add-routing.module' |
5 | import { VideoAddComponent } from './video-add.component' | 5 | import { VideoAddComponent } from './video-add.component' |
6 | import { DragDropDirective } from './video-add-components/drag-drop.directive' | ||
6 | import { CanDeactivateGuard } from '../../shared/guards/can-deactivate-guard.service' | 7 | import { CanDeactivateGuard } from '../../shared/guards/can-deactivate-guard.service' |
7 | import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component' | 8 | import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component' |
8 | import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-components/video-import-url.component' | 9 | import { VideoImportUrlComponent } from '@app/videos/+video-edit/video-add-components/video-import-url.component' |
@@ -18,10 +19,12 @@ import { VideoImportTorrentComponent } from '@app/videos/+video-edit/video-add-c | |||
18 | VideoAddComponent, | 19 | VideoAddComponent, |
19 | VideoUploadComponent, | 20 | VideoUploadComponent, |
20 | VideoImportUrlComponent, | 21 | VideoImportUrlComponent, |
21 | VideoImportTorrentComponent | 22 | VideoImportTorrentComponent, |
23 | DragDropDirective | ||
22 | ], | 24 | ], |
23 | exports: [ | 25 | exports: [ |
24 | VideoAddComponent | 26 | VideoAddComponent, |
27 | DragDropDirective | ||
25 | ], | 28 | ], |
26 | providers: [ | 29 | providers: [ |
27 | CanDeactivateGuard | 30 | CanDeactivateGuard |