]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/app/videos/+video-edit/video-add-components/video-upload.component.ts
Refractor notification service
[github/Chocobozzz/PeerTube.git] / client / src / app / videos / +video-edit / video-add-components / video-upload.component.ts
index c9ab35b1d2668262c1624ef387a6743febb7dcdf..aa40f87819b0bc3d55f245d85a1c47ce7add3091 100644 (file)
@@ -1,12 +1,11 @@
 import { HttpEventType, HttpResponse } from '@angular/common/http'
-import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'
+import { Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'
 import { Router } from '@angular/router'
 import { LoadingBarService } from '@ngx-loading-bar/core'
-import { NotificationsService } from 'angular2-notifications'
 import { BytesPipe } from 'ngx-pipes'
 import { Subscription } from 'rxjs'
 import { VideoPrivacy } from '../../../../../../shared/models/videos'
-import { AuthService, ServerService } from '../../../core'
+import { AuthService, Notifier, ServerService } from '../../../core'
 import { VideoEdit } from '../../../shared/video/video-edit.model'
 import { VideoService } from '../../../shared/video/video.service'
 import { I18n } from '@ngx-translate/i18n-polyfill'
@@ -14,6 +13,7 @@ import { VideoSend } from '@app/videos/+video-edit/video-add-components/video-se
 import { CanComponentDeactivate } from '@app/shared/guards/can-deactivate-guard.service'
 import { FormValidatorService, UserService } from '@app/shared'
 import { VideoCaptionService } from '@app/shared/video-caption'
+import { scrollToTop } from '@app/shared/misc/utils'
 
 @Component({
   selector: 'my-video-upload',
@@ -25,7 +25,8 @@ import { VideoCaptionService } from '@app/shared/video-caption'
 })
 export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy, CanComponentDeactivate {
   @Output() firstStepDone = new EventEmitter<string>()
-  @ViewChild('videofileInput') videofileInput
+  @Output() firstStepError = new EventEmitter<void>()
+  @ViewChild('videofileInput') videofileInput: ElementRef<HTMLInputElement>
 
   // So that it can be accessed in the template
   readonly SPECIAL_SCHEDULED_PRIVACY = VideoEdit.SPECIAL_SCHEDULED_PRIVACY
@@ -42,13 +43,16 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
     id: 0,
     uuid: ''
   }
+  waitTranscodingEnabled = true
+
+  error: string
 
   protected readonly DEFAULT_VIDEO_PRIVACY = VideoPrivacy.PUBLIC
 
   constructor (
     protected formValidatorService: FormValidatorService,
     protected loadingBar: LoadingBarService,
-    protected notificationsService: NotificationsService,
+    protected notifier: Notifier,
     protected authService: AuthService,
     protected serverService: ServerService,
     protected videoService: VideoService,
@@ -68,10 +72,10 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
     super.ngOnInit()
 
     this.userService.getMyVideoQuotaUsed()
-      .subscribe(data => this.userVideoQuotaUsed = data.videoQuotaUsed)
-
-    this.userService.getMyVideoQuotaUsed()
-      .subscribe(data => this.userVideoQuotaUsedDaily = data.videoQuotaUsedDaily)
+        .subscribe(data => {
+          this.userVideoQuotaUsed = data.videoQuotaUsed
+          this.userVideoQuotaUsedDaily = data.videoQuotaUsedDaily
+        })
   }
 
   ngOnDestroy () {
@@ -83,7 +87,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
 
     if (this.videoUploaded === true) {
       // FIXME: cannot concatenate strings inside i18n service :/
-      text = this.i18n('Your video was uploaded to your account and is private.') +
+      text = this.i18n('Your video was uploaded to your account and is private.') + ' ' +
         this.i18n('But associated data (tags, description...) will be lost, are you sure you want to leave this page?')
     } else {
       text = this.i18n('Your video is not uploaded yet, are you sure you want to leave this page?')
@@ -105,50 +109,46 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
       this.isUploadingVideo = false
       this.videoUploadPercents = 0
       this.videoUploadObservable = null
-      this.notificationsService.info(this.i18n('Info'), this.i18n('Upload cancelled'))
+      this.notifier.info(this.i18n('Upload cancelled'))
     }
   }
 
   uploadFirstStep () {
-    const videofile = this.videofileInput.nativeElement.files[0] as File
+    const videofile = this.videofileInput.nativeElement.files[0]
     if (!videofile) return
 
-    // Cannot upload videos > 8GB for now
-    if (videofile.size > 8 * 1024 * 1024 * 1024) {
-      this.notificationsService.error(this.i18n('Error'), this.i18n('We are sorry but PeerTube cannot handle videos > 8GB'))
-      return
-    }
-
+    // Check global user quota
     const bytePipes = new BytesPipe()
     const videoQuota = this.authService.getUser().videoQuota
     if (videoQuota !== -1 && (this.userVideoQuotaUsed + videofile.size) > videoQuota) {
       const msg = this.i18n(
-        'Your video quota is exceeded with this video (video size: {{ videoSize }}, used: {{ videoQuotaUsed }}, quota: {{ videoQuota }})',
+        'Your video quota is exceeded with this video (video size: {{videoSize}}, used: {{videoQuotaUsed}}, quota: {{videoQuota}})',
         {
           videoSize: bytePipes.transform(videofile.size, 0),
           videoQuotaUsed: bytePipes.transform(this.userVideoQuotaUsed, 0),
           videoQuota: bytePipes.transform(videoQuota, 0)
         }
       )
-      this.notificationsService.error(this.i18n('Error'), msg)
+      this.notifier.error(msg)
       return
     }
 
+    // Check daily user quota
     const videoQuotaDaily = this.authService.getUser().videoQuotaDaily
     if (videoQuotaDaily !== -1 && (this.userVideoQuotaUsedDaily + videofile.size) > videoQuotaDaily) {
       const msg = this.i18n(
-        'Your daily video quota is exceeded with this video (video size: {{ videoSize }}, ' +
-            'used: {{ videoQuotaUsedDaily }}, quota: {{ videoQuotaDaily }})',
+        'Your daily video quota is exceeded with this video (video size: {{videoSize}}, used: {{quotaUsedDaily}}, quota: {{quotaDaily}})',
         {
           videoSize: bytePipes.transform(videofile.size, 0),
-          videoQuotaUsedDaily: bytePipes.transform(this.userVideoQuotaUsedDaily, 0),
-          videoQuotaDaily: bytePipes.transform(videoQuotaDaily, 0)
+          quotaUsedDaily: bytePipes.transform(this.userVideoQuotaUsedDaily, 0),
+          quotaDaily: bytePipes.transform(videoQuotaDaily, 0)
         }
       )
-      this.notificationsService.error(this.i18n('Error'), msg)
+      this.notifier.error(msg)
       return
     }
 
+    // Build name field
     const nameWithoutExtension = videofile.name.replace(/\.[^/.]+$/, '')
     let name: string
 
@@ -156,6 +156,11 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
     if (nameWithoutExtension.length < 3) name = videofile.name
     else name = nameWithoutExtension
 
+    // Force user to wait transcoding for unsupported video types in web browsers
+    if (!videofile.name.endsWith('.mp4') && !videofile.name.endsWith('.webm') && !videofile.name.endsWith('.ogv')) {
+      this.waitTranscodingEnabled = false
+    }
+
     const privacy = this.firstStepPrivacyId.toString()
     const nsfw = false
     const waitTranscoding = true
@@ -182,6 +187,8 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
       channelId
     })
 
+    this.videoPrivacies = this.videoService.explainedPrivacyLabels(this.videoPrivacies)
+
     this.videoUploadObservable = this.videoService.uploadVideo(formData).subscribe(
       event => {
         if (event.type === HttpEventType.UploadProgress) {
@@ -200,11 +207,18 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
         this.isUploadingVideo = false
         this.videoUploadPercents = 0
         this.videoUploadObservable = null
-        this.notificationsService.error(this.i18n('Error'), err.message)
+        this.firstStepError.emit()
+        this.notifier.error(err.message)
       }
     )
   }
 
+  isPublishingButtonDisabled () {
+    return !this.form.valid ||
+      this.isUpdatingVideo === true ||
+      this.videoUploaded !== true
+  }
+
   updateSecondStep () {
     if (this.checkForm() === false) {
       return
@@ -223,13 +237,13 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
             this.isUpdatingVideo = false
             this.isUploadingVideo = false
 
-            this.notificationsService.success(this.i18n('Success'), this.i18n('Video published.'))
+            this.notifier.success(this.i18n('Video published.'))
             this.router.navigate([ '/videos/watch', video.uuid ])
           },
 
           err => {
-            this.isUpdatingVideo = false
-            this.notificationsService.error(this.i18n('Error'), err.message)
+            this.error = err.message
+            scrollToTop()
             console.error(err)
           }
         )