Support drag and drop for video upload and torrent file import
authorRigel Kent <sendmemail@rigelk.eu>
Thu, 2 Apr 2020 22:22:04 +0000 (00:22 +0200)
committerRigel Kent <sendmemail@rigelk.eu>
Thu, 2 Apr 2020 22:22:06 +0000 (00:22 +0200)
client/src/app/videos/+video-edit/shared/video-caption-add-modal.component.html
client/src/app/videos/+video-edit/video-add-components/drag-drop.directive.ts [new file with mode: 0644]
client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.html
client/src/app/videos/+video-edit/video-add-components/video-import-torrent.component.ts
client/src/app/videos/+video-edit/video-add-components/video-import-url.component.html
client/src/app/videos/+video-edit/video-add-components/video-upload.component.html
client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts
client/src/app/videos/+video-edit/video-add.component.scss
client/src/app/videos/+video-edit/video-add.module.ts

index 4262ff0fced1faa5aafc632fc3aab15029bfac6a..ada32e3fd1f4c0b4d34d16cba621814662f43fae 100644 (file)
@@ -9,7 +9,7 @@
     <div class="modal-body">
       <label i18n for="language">Language</label>
       <div class="peertube-select-container">
-        <select id="language" formControlName="language">
+        <select id="language" formControlName="language" class="form-control">
           <option></option>
           <option *ngFor="let language of videoCaptionLanguages" [value]="language.id">{{ language.label }}</option>
         </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 (file)
index 0000000..07c7d34
--- /dev/null
@@ -0,0 +1,30 @@
+import { Directive, Output, EventEmitter, HostBinding, HostListener } from '@angular/core'
+
+@Directive({
+  selector: '[dragDrop]'
+})
+export class DragDropDirective {
+  @Output() onFileDropped = new EventEmitter<FileList>()
+
+  @HostBinding('class.dragover') dragover = false
+
+  @HostListener('dragover', ['$event']) onDragOver(e: Event) {
+    e.preventDefault()
+    e.stopPropagation()
+    this.dragover = true
+  }
+
+  @HostListener('dragleave', ['$event']) public onDragLeave(e: Event) {
+    e.preventDefault()
+    e.stopPropagation()
+    this.dragover = false
+  }
+
+  @HostListener('drop', ['$event']) public ondrop(e: DragEvent) {
+    e.preventDefault()
+    e.stopPropagation()
+    this.dragover = false
+    let files = e.dataTransfer.files
+    if (files.length > 0) this.onFileDropped.emit(files)
+  }
+}
index c290fd4b1bb7142aa043da16960a8ce16fca9e95..1d938416124f6b204edd71ae13f381baa327faa6 100644 (file)
@@ -1,14 +1,13 @@
-<div *ngIf="!hasImportedVideo" class="upload-video-container">
+<div *ngIf="!hasImportedVideo" class="upload-video-container" dragDrop (onFileDropped)="setTorrentFile($event)">
   <div class="first-step-block">
     <my-global-icon class="upload-icon" iconName="upload"></my-global-icon>
 
-    <div class="button-file">
+    <div class="button-file form-control" [ngbTooltip]="'(extensions: .torrent)'">
       <span i18n>Select the torrent to import</span>
       <input #torrentfileInput type="file" name="torrentfile" id="torrentfile" accept=".torrent" (change)="fileChange()" />
     </div>
-    <span class="button-file-extension">(.torrent)</span>
 
-    <div class="torrent-or-magnet" i18n>Or</div>
+    <div class="torrent-or-magnet" i18n-data-content data-content="OR"></div>
 
     <div class="form-group form-group-magnet-uri">
       <label i18n for="magnetUri">Paste magnet URI</label>
         </ng-template>
       </my-help>
 
-      <input type="text" id="magnetUri" [(ngModel)]="magnetUri" />
+      <input type="text" id="magnetUri" [(ngModel)]="magnetUri" class="form-control" />
     </div>
 
     <div class="form-group">
       <label i18n for="first-step-channel">Channel</label>
       <div class="peertube-select-container">
-        <select id="first-step-channel" [(ngModel)]="firstStepChannelId">
+        <select id="first-step-channel" [(ngModel)]="firstStepChannelId" class="form-control">
           <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
         </select>
       </div>
@@ -36,7 +35,7 @@
     <div class="form-group">
       <label i18n for="first-step-privacy">Privacy</label>
       <div class="peertube-select-container">
-        <select id="first-step-privacy" [(ngModel)]="firstStepPrivacyId">
+        <select id="first-step-privacy" [(ngModel)]="firstStepPrivacyId" class="form-control">
           <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
         </select>
       </div>
index e47624dd655bd3915e35cc794c115dedebffc0ec..4d0b0b08087f7765b927f0a155b5dc31e2fd177e 100644 (file)
@@ -72,6 +72,11 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Ca
     this.importVideo(torrentfile)
   }
 
+  setTorrentFile (files: FileList) {
+    this.torrentfileInput.nativeElement.files = files
+    this.fileChange()
+  }
+
   importVideo (torrentfile?: Blob) {
     this.isImportingVideo = true
 
index 09d0b8272ae689314448f84179b0824754c5c1e0..9a26fe3082edfae92b364a404beec5506aa429e2 100644 (file)
         </ng-template>
       </my-help>
 
-      <input type="text" id="targetUrl" [(ngModel)]="targetUrl" />
+      <input type="text" id="targetUrl" [(ngModel)]="targetUrl" class="form-control" />
     </div>
 
     <div class="form-group">
       <label i18n for="first-step-channel">Channel</label>
       <div class="peertube-select-container">
-        <select id="first-step-channel" [(ngModel)]="firstStepChannelId">
+        <select id="first-step-channel" [(ngModel)]="firstStepChannelId" class="form-control">
           <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
         </select>
       </div>
@@ -30,7 +30,7 @@
     <div class="form-group">
       <label i18n for="first-step-privacy">Privacy</label>
       <div class="peertube-select-container">
-        <select id="first-step-privacy" [(ngModel)]="firstStepPrivacyId">
+        <select id="first-step-privacy" [(ngModel)]="firstStepPrivacyId" class="form-control">
           <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
         </select>
       </div>
index b4e1ceeca9c45089935d0c9e0bad0397949a3942..8db441a8cad81df09349c9c9353c1b889d41f918 100644 (file)
@@ -1,8 +1,8 @@
-<div *ngIf="!isUploadingVideo" class="upload-video-container">
+<div *ngIf="!isUploadingVideo" class="upload-video-container" dragDrop (onFileDropped)="setVideoFile($event)">
   <div class="first-step-block">
     <my-global-icon class="upload-icon" iconName="upload"></my-global-icon>
 
-    <div class="button-file form-control" [ngbTooltip]="'(extensions: ' + videoExtensions + ')'" container="body">
+    <div class="button-file form-control" [ngbTooltip]="'(extensions: ' + videoExtensions + ')'">
       <span i18n>Select the file to upload</span>
       <input #videofileInput type="file" name="videofile" id="videofile" [accept]="videoExtensions" (change)="fileChange()" autofocus />
     </div>
index ee4aa7b5337e6026c6c90ec680c0ef95bff62ebb..8023459453c17328d8bae12875dbca6479b18ef3 100644 (file)
@@ -108,6 +108,11 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
     return this.videofileInput.nativeElement.files[0]
   }
 
+  setVideoFile (files: FileList) {
+    this.videofileInput.nativeElement.files = files
+    this.fileChange()
+  }
+
   getAudioUploadLabel () {
     const videofile = this.getVideoFile()
     if (!videofile) return this.i18n('Upload')
index 9d068afde465f002d7db048f84e0f3368520d440..c20467d9b31fd302fe5c8570547a977d60e0b12f 100644 (file)
@@ -40,14 +40,19 @@ $border-color: #EAEAEA;
 
 ::ng-deep .upload-video-container {
   border: $border-width $border-type $border-color;
-  border-top: none;
+  border-top: transparent;
 
   background-color: var(--submenuColor);
-  border-radius: 3px;
+  border-bottom-left-radius: 3px;
+  border-bottom-right-radius: 3px;
   width: 100%;
   min-height: 440px;
   padding-bottom: 20px;
   display: flex;
   justify-content: center;
   align-items: center;
+
+  &.dragover {
+    border: 3px dashed var(--mainColor);
+  }
 }
index 911404badfb63191fd1a534e4a00938d8f3e20ca..b8f5a9a476cb78d36c92da9f1d39d50a03289ccb 100644 (file)
@@ -3,6 +3,7 @@ import { SharedModule } from '../../shared'
 import { VideoEditModule } from './shared/video-edit.module'
 import { VideoAddRoutingModule } from './video-add-routing.module'
 import { VideoAddComponent } from './video-add.component'
+import { DragDropDirective } from './video-add-components/drag-drop.directive'
 import { CanDeactivateGuard } from '../../shared/guards/can-deactivate-guard.service'
 import { VideoUploadComponent } from '@app/videos/+video-edit/video-add-components/video-upload.component'
 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
     VideoAddComponent,
     VideoUploadComponent,
     VideoImportUrlComponent,
-    VideoImportTorrentComponent
+    VideoImportTorrentComponent,
+    DragDropDirective
   ],
   exports: [
-    VideoAddComponent
+    VideoAddComponent,
+    DragDropDirective
   ],
   providers: [
     CanDeactivateGuard