Browse Source

Pause/resume all uploads at once #65

Artur Paikin 8 years ago
parent
commit
baf8e361f1

+ 17 - 8
src/core/Core.js

@@ -126,6 +126,7 @@ export default class Core {
       data: file.data,
       data: file.data,
       progress: {
       progress: {
         percentage: 0,
         percentage: 0,
+        uploadComplete: false,
         uploadStarted: false
         uploadStarted: false
       },
       },
       size: file.data.size,
       size: file.data.size,
@@ -180,15 +181,17 @@ export default class Core {
     // `remove-file` removes a file from `state.files`, for example when
     // `remove-file` removes a file from `state.files`, for example when
     // a user decides not to upload particular file and clicks a button to remove it
     // a user decides not to upload particular file and clicks a button to remove it
     this.emitter.on('file-remove', (fileID) => {
     this.emitter.on('file-remove', (fileID) => {
-      const updatedFiles = Object.assign({}, this.state.files)
+      const updatedFiles = Object.assign({}, this.getState().files)
       delete updatedFiles[fileID]
       delete updatedFiles[fileID]
       this.setState({files: updatedFiles})
       this.setState({files: updatedFiles})
     })
     })
 
 
-    this.emitter.on('core:file-upload-started', (fileID) => {
+    this.emitter.on('core:file-upload-started', (fileID, upload) => {
       const updatedFiles = Object.assign({}, this.getState().files)
       const updatedFiles = Object.assign({}, this.getState().files)
       const updatedFile = Object.assign({}, updatedFiles[fileID],
       const updatedFile = Object.assign({}, updatedFiles[fileID],
         Object.assign({}, {
         Object.assign({}, {
+          // can’t do that, because immutability. ??
+          // upload: upload,
           progress: Object.assign({}, updatedFiles[fileID].progress, {
           progress: Object.assign({}, updatedFiles[fileID].progress, {
             uploadStarted: Date.now()
             uploadStarted: Date.now()
           })
           })
@@ -196,14 +199,16 @@ export default class Core {
       ))
       ))
       updatedFiles[fileID] = updatedFile
       updatedFiles[fileID] = updatedFile
 
 
-      this.setState({
+      this.setState({files: updatedFiles})
-        files: updatedFiles
-      })
     })
     })
 
 
     this.emitter.on('upload-progress', (data) => {
     this.emitter.on('upload-progress', (data) => {
       const fileID = data.id
       const fileID = data.id
       const updatedFiles = Object.assign({}, this.getState().files)
       const updatedFiles = Object.assign({}, this.getState().files)
+      if (!updatedFiles[fileID]) {
+        console.error('Trying to set progress for a file that’s not with us anymore: ', fileID)
+        return
+      }
 
 
       const updatedFile = Object.assign({}, updatedFiles[fileID],
       const updatedFile = Object.assign({}, updatedFiles[fileID],
         Object.assign({}, {
         Object.assign({}, {
@@ -218,12 +223,13 @@ export default class Core {
 
 
       // calculate total progress, using the number of files currently uploading,
       // calculate total progress, using the number of files currently uploading,
       // multiplied by 100 and the summ of individual progress of each file
       // multiplied by 100 and the summ of individual progress of each file
-      const inProgress = Object.keys(updatedFiles).map((file) => {
+      const inProgress = Object.keys(updatedFiles).filter((file) => {
-        return file.progress !== 0
+        return !updatedFiles[file].progress.uploadComplete &&
+               updatedFiles[file].progress.uploadStarted
       })
       })
       const progressMax = Object.keys(inProgress).length * 100
       const progressMax = Object.keys(inProgress).length * 100
       let progressAll = 0
       let progressAll = 0
-      Object.keys(updatedFiles).forEach((file) => {
+      inProgress.forEach((file) => {
         progressAll = progressAll + updatedFiles[file].progress.percentage
         progressAll = progressAll + updatedFiles[file].progress.percentage
       })
       })
 
 
@@ -238,6 +244,9 @@ export default class Core {
     this.emitter.on('upload-success', (fileID, uploadURL) => {
     this.emitter.on('upload-success', (fileID, uploadURL) => {
       const updatedFiles = Object.assign({}, this.getState().files)
       const updatedFiles = Object.assign({}, this.getState().files)
       const updatedFile = Object.assign({}, updatedFiles[fileID], {
       const updatedFile = Object.assign({}, updatedFiles[fileID], {
+        progress: Object.assign({}, updatedFiles[fileID].progress, {
+          uploadComplete: true
+        }),
         uploadURL: uploadURL
         uploadURL: uploadURL
       })
       })
       updatedFiles[fileID] = updatedFile
       updatedFiles[fileID] = updatedFile

+ 55 - 19
src/plugins/Dashboard/Dashboard.js

@@ -2,7 +2,7 @@ import html from '../../core/html'
 import Utils from '../../core/Utils'
 import Utils from '../../core/Utils'
 import FileItem from './FileItem'
 import FileItem from './FileItem'
 import FileCard from './FileCard'
 import FileCard from './FileCard'
-import { closeIcon, localIcon, uploadIcon, dashboardBgIcon } from './icons'
+import { closeIcon, localIcon, uploadIcon, dashboardBgIcon, iconPause, iconResume } from './icons'
 
 
 export default function Dashboard (props, bus) {
 export default function Dashboard (props, bus) {
   // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
   // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
@@ -12,12 +12,12 @@ export default function Dashboard (props, bus) {
   const modal = state.modal
   const modal = state.modal
   const container = props.container
   const container = props.container
   const showFileCard = modal.showFileCard
   const showFileCard = modal.showFileCard
+  const showProgressDetails = props.showProgressDetails
 
 
   const hideModal = props.hideModal
   const hideModal = props.hideModal
   const hideAllPanels = props.hideAllPanels
   const hideAllPanels = props.hideAllPanels
   const showPanel = props.showPanel
   const showPanel = props.showPanel
   const log = props.log
   const log = props.log
-  // const handleInputChange = props.handleInputChange
 
 
   const acquirers = modal.targets.filter((target) => {
   const acquirers = modal.targets.filter((target) => {
     return target.type === 'acquirer'
     return target.type === 'acquirer'
@@ -55,13 +55,40 @@ export default function Dashboard (props, bus) {
     })
     })
   }
   }
 
 
-  const selectedFiles = Object.keys(files).filter((file) => {
+  const newFiles = Object.keys(files).filter((file) => {
-    return files[file].progress.percentage === 0
+    return !files[file].progress.uploadStarted
-    // return files[file].progress !== 100
   })
   })
+  const uploadStartedFiles = Object.keys(files).filter((file) => {
+    return files[file].progress.uploadStarted
+  })
+  const completeFiles = Object.keys(files).filter((file) => {
+    return files[file].progress.uploadComplete
+  })
+  const inProgressFiles = Object.keys(files).filter((file) => {
+    return !files[file].progress.uploadComplete &&
+           files[file].progress.uploadStarted &&
+           !files[file].isPaused
+  })
+
+  const uploadStartedFilesCount = Object.keys(uploadStartedFiles).length
+  const completeFilesCount = Object.keys(completeFiles).length
+  const inProgressFilesCount = Object.keys(inProgressFiles).length
   const totalFileCount = Object.keys(files).length
   const totalFileCount = Object.keys(files).length
-  const selectedFileCount = Object.keys(selectedFiles).length
+  const newFileCount = Object.keys(newFiles).length
-  const isSomethingSelected = selectedFileCount > 0
+
+  function renderPauseResume () {
+    if (uploadStartedFilesCount > 0) {
+      if (inProgressFilesCount > 0) {
+        return html`<button class="UppyDashboard-pauseResume UppyButton--circular UppyButton--yellow UppyButton--sizeS"
+                            onclick=${() => bus.emit('core:pause-all')}>${iconPause()}</button>`
+      }
+
+      if (uploadStartedFilesCount !== completeFilesCount) {
+        return html`<button class="UppyDashboard-pauseResume UppyButton--circular UppyButton--green UppyButton--sizeS"
+                            onclick=${() => bus.emit('core:resume-all')}>${iconResume()}</button>`
+      }
+    }
+  }
 
 
   return html`<div class="Uppy UppyTheme--default UppyDashboard ${isTouchDevice ? 'Uppy--isTouchDevice' : ''}"
   return html`<div class="Uppy UppyTheme--default UppyDashboard ${isTouchDevice ? 'Uppy--isTouchDevice' : ''}"
                  aria-hidden="${modal.isHidden}"
                  aria-hidden="${modal.isHidden}"
@@ -119,22 +146,31 @@ export default function Dashboard (props, bus) {
           <ul class="UppyDashboard-filesInner">
           <ul class="UppyDashboard-filesInner">
             ${totalFileCount === 0
             ${totalFileCount === 0
               ? html`<div class="UppyDashboard-bgIcon">${dashboardBgIcon()}</div>`
               ? html`<div class="UppyDashboard-bgIcon">${dashboardBgIcon()}</div>`
-              : ''
+              : null
             }
             }
             ${Object.keys(files).map((fileID) => {
             ${Object.keys(files).map((fileID) => {
-              return FileItem(files[fileID], bus)
+              return FileItem(
+                {file: files[fileID], showProgressDetails}, bus
+              )
             })}
             })}
           </ul>
           </ul>
-          ${!props.autoProceed && isSomethingSelected
+          <div class="UppyDashboard-actions">
-            ? html`<button class="UppyButton--circular UppyDashboard-upload"
+            ${renderPauseResume()}
-                           type="button"
+            ${!props.autoProceed && newFileCount > 0
-                           title="Upload"
+              ? html`<button class="UppyButton--circular UppyButton--blue UppyButton--sizeM UppyDashboard-upload"
-                           onclick=${next}>
+                             type="button"
-                      ${uploadIcon()}
+                             title="Upload all files"
-                      <sup class="UppyDashboard-uploadCount">${selectedFileCount}</sup>
+                             aria-label="Upload all files"
-                   </button>`
+                             onclick=${next}>
-            : null
+                        ${uploadIcon()}
-          }
+                        <sup class="UppyDashboard-uploadCount"
+                             title="Number of selected files"
+                             aria-label="Number of selected files">
+                              ${newFileCount}</sup>
+                     </button>`
+              : null
+            }
+          </div>
         </div>
         </div>
 
 
         ${acquirers.map((target) => {
         ${acquirers.map((target) => {

+ 34 - 14
src/plugins/Dashboard/FileItem.js

@@ -41,10 +41,13 @@ function getSpeed (fileProgress) {
   return uploadSpeed
   return uploadSpeed
 }
 }
 
 
-export default function fileItem (file, bus) {
+export default function fileItem (props, bus) {
-  const isUploaded = file.progress.percentage === 100
+  const file = props.file
-  const uploadInProgressOrComplete = file.progress.percentage > 0
+  const showProgressDetails = props.showProgressDetails
-  const uploadInProgress = file.progress.percentage > 0 && file.progress.percentage < 100
+
+  const isUploaded = file.progress.uploadComplete
+  const uploadInProgressOrComplete = file.progress.uploadStarted
+  const uploadInProgress = file.progress.uploadStarted && !file.progress.uploadComplete
   const isPaused = file.isPaused || false
   const isPaused = file.isPaused || false
 
 
   const fileName = Utils.getFileNameAndExtension(file.meta.name)[0]
   const fileName = Utils.getFileNameAndExtension(file.meta.name)[0]
@@ -72,19 +75,31 @@ export default function fileItem (file, bus) {
           : getIconByMime(file.type.general)
           : getIconByMime(file.type.general)
         }
         }
         <div class="UppyDashboardItem-progress">
         <div class="UppyDashboardItem-progress">
-          <button class="UppyDashboardItem-progressBtn" onclick=${(e) => {
+          <button class="UppyDashboardItem-progressBtn"
-            if (file.progress.percentage === 100) return
+                  title="${isUploaded
-            bus.emit('core:upload-pause', file.id)
+                          ? 'upload complete'
-          }}>
+                          : file.isPaused ? 'resume upload' : 'pause upload'}"
+                  onclick=${(e) => {
+                    if (isUploaded) return
+                    bus.emit('core:upload-pause', file.id)
+                  }}>
             ${FileItemProgress({progress: file.progress.percentage, fileID: file.id}, bus)}
             ${FileItemProgress({progress: file.progress.percentage, fileID: file.id}, bus)}
           </button>
           </button>
-          <div class="UppyDashboardItem-progressInfo">
+          ${showProgressDetails
-            ${getETA(file.progress)} ・ ↑ ${prettyBytes(getSpeed(file.progress))} / s
+            ? html`<div class="UppyDashboardItem-progressInfo"
-          </div>
+                   title="File progress: upload speed and ETA"
+                   aria-label="File progress: upload speed and ETA">
+                ${!file.isPaused && !isUploaded
+                  ? html`<span>${getETA(file.progress)} ・ ↑ ${prettyBytes(getSpeed(file.progress))}/s</span>`
+                  : null
+                }
+              </div>`
+            : null
+          }
         </div>
         </div>
       </div>
       </div>
     <div class="UppyDashboardItem-info">
     <div class="UppyDashboardItem-info">
-      <h4 class="UppyDashboardItem-name">
+      <h4 class="UppyDashboardItem-name" title="${fileName}">
         ${file.uploadURL
         ${file.uploadURL
           ? html`<a href="${file.uploadURL}" target="_blank">${file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName}</a>`
           ? html`<a href="${file.uploadURL}" target="_blank">${file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName}</a>`
           : file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName
           : file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName
@@ -95,14 +110,19 @@ export default function fileItem (file, bus) {
       </div>
       </div>
       ${!uploadInProgressOrComplete
       ${!uploadInProgressOrComplete
         ? html`<button class="UppyDashboardItem-edit"
         ? html`<button class="UppyDashboardItem-edit"
-              onclick=${(e) => bus.emit('dashboard:file-card', file.id)}>${iconEdit()}</button>`
+                       aria-label="Edit file"
+                       title="Edit file"
+                       onclick=${(e) => bus.emit('dashboard:file-card', file.id)}>
+                        ${iconEdit()}
+                      </button>`
         : null
         : null
       }
       }
     </div>
     </div>
     <div class="UppyDashboardItem-action">
     <div class="UppyDashboardItem-action">
       ${!isUploaded
       ${!isUploaded
         ? html`<button class="UppyDashboardItem-remove"
         ? html`<button class="UppyDashboardItem-remove"
-                       aria-label="Remove this file"
+                       aria-label="Remove file"
+                       title="Remove file"
                        onclick=${remove}>
                        onclick=${remove}>
                   ${removeIcon()}
                   ${removeIcon()}
                </button>`
                </button>`

+ 15 - 6
src/plugins/Dashboard/icons.js

@@ -9,6 +9,21 @@ export function defaultTabIcon () {
   </svg>`
   </svg>`
 }
 }
 
 
+export function iconResume () {
+  return html`<svg class="UppyIcon" width="25" height="25" viewBox="0 0 44 44">
+    <polygon class="play" transform="translate(6, 5.5)" points="13 21.6666667 13 11 21 16.3333333" />
+  </svg>`
+}
+
+export function iconPause () {
+  return html`<svg class="UppyIcon" width="25px" height="25px" viewBox="0 0 44 44">
+    <g transform="translate(18, 17)" class="pause">
+      <rect x="0" y="0" width="2" height="10" rx="0" />
+      <rect x="6" y="0" width="2" height="10" rx="0" />
+    </g>
+  </svg>`
+}
+
 export function iconEdit () {
 export function iconEdit () {
   return html`<svg class="UppyIcon UppyIcon-edit" width="28" height="28" viewBox="0 0 28 28">
   return html`<svg class="UppyIcon UppyIcon-edit" width="28" height="28" viewBox="0 0 28 28">
     <path d="M25.436 2.566a7.98 7.98 0 0 0-2.078-1.51C22.638.703 21.906.5 21.198.5a3 3 0 0 0-1.023.17 2.436 2.436 0 0 0-.893.562L2.292 18.217.5 27.5l9.28-1.796 16.99-16.99c.255-.254.444-.56.562-.888a3 3 0 0 0 .17-1.023c0-.708-.205-1.44-.555-2.16a8 8 0 0 0-1.51-2.077zM9.01 24.252l-4.313.834c0-.03.008-.06.012-.09.007-.944-.74-1.715-1.67-1.723-.04 0-.078.007-.118.01l.83-4.29L17.72 5.024l5.264 5.264L9.01 24.252zm16.84-16.96a.818.818 0 0 1-.194.31l-1.57 1.57-5.26-5.26 1.57-1.57a.82.82 0 0 1 .31-.194 1.45 1.45 0 0 1 .492-.074c.397 0 .917.126 1.468.397.55.27 1.13.678 1.656 1.21.53.53.94 1.11 1.208 1.655.272.55.397 1.07.393 1.468.004.193-.027.358-.074.488z" />
     <path d="M25.436 2.566a7.98 7.98 0 0 0-2.078-1.51C22.638.703 21.906.5 21.198.5a3 3 0 0 0-1.023.17 2.436 2.436 0 0 0-.893.562L2.292 18.217.5 27.5l9.28-1.796 16.99-16.99c.255-.254.444-.56.562-.888a3 3 0 0 0 .17-1.023c0-.708-.205-1.44-.555-2.16a8 8 0 0 0-1.51-2.077zM9.01 24.252l-4.313.834c0-.03.008-.06.012-.09.007-.944-.74-1.715-1.67-1.723-.04 0-.078.007-.118.01l.83-4.29L17.72 5.024l5.264 5.264L9.01 24.252zm16.84-16.96a.818.818 0 0 1-.194.31l-1.57 1.57-5.26-5.26 1.57-1.57a.82.82 0 0 1 .31-.194 1.45 1.45 0 0 1 .492-.074c.397 0 .917.126 1.468.397.55.27 1.13.678 1.656 1.21.53.53.94 1.11 1.208 1.655.272.55.397 1.07.393 1.468.004.193-.027.358-.074.488z" />
@@ -22,12 +37,6 @@ export function localIcon () {
   </svg>`
   </svg>`
 }
 }
 
 
-// export function backIcon () {
-//   return html`<svg class="UppyIcon" width="7px" height="10px" viewBox="0 0 23 45">
-//     <polygon points="21.2678133 0.318896058 1.26781326 21.8188961 0.634228199 22.5 1.26781326 23.1811039 21.2678133 44.6811039 22.7321867 43.3188961 2.73218674 21.8188961 2.73218674 23.1811039 22.7321867 1.68110394"></polygon>
-//   </svg>`
-// }
-
 export function closeIcon () {
 export function closeIcon () {
   return html`<svg class="UppyIcon" width="14px" height="14px" viewBox="0 0 19 19">
   return html`<svg class="UppyIcon" width="14px" height="14px" viewBox="0 0 19 19">
     <polygon points="17.3182539 17.2324466 9.93955339 9.85374611 9.586 9.50019272 9.23244661 9.85374611 1.85374611 17.2324466 2.56085289 17.2324466 1.93955339 16.6111471 1.93955865 17.3182486 9.31803946 9.93954813 9.67158232 9.58599474 9.31803419 9.23244661 1.93955339 1.85396581 1.93961588 2.56101008 2.56091538 1.93949089 1.85375137 1.93955865 9.23245187 9.31803946 9.586 9.67157706 9.93954813 9.31803946 17.3182486 1.93955865 16.6111471 1.93955339 17.2324466 2.56085289 17.2324466 1.85374611 9.85374611 9.23244661 9.50019272 9.586 9.85374611 9.93955339 17.2324466 17.3182539 17.9395534 16.6111471 10.5608529 9.23244661 10.5608529 9.93955339 17.9395534 2.56085289 18.2931068 2.2072995 17.9395534 1.85374611 17.3182539 1.23244661 16.9647058 0.878898482 16.6111524 1.23244135 9.23245187 8.61092215 9.93954813 8.61092215 2.56084763 1.23244135 2.20723173 0.87883598 1.85368362 1.23250911 1.23238412 1.85402831 0.878955712 2.20758169 1.23244661 2.56107259 8.61092741 9.93955339 8.61092215 9.23245187 1.23244135 16.6111524 0.878898482 16.9647058 1.23244661 17.3182539 1.85374611 17.9395534 2.2072995 18.2931068 2.56085289 17.9395534 9.93955339 10.5608529 9.23244661 10.5608529 16.6111471 17.9395534"></polygon>
     <polygon points="17.3182539 17.2324466 9.93955339 9.85374611 9.586 9.50019272 9.23244661 9.85374611 1.85374611 17.2324466 2.56085289 17.2324466 1.93955339 16.6111471 1.93955865 17.3182486 9.31803946 9.93954813 9.67158232 9.58599474 9.31803419 9.23244661 1.93955339 1.85396581 1.93961588 2.56101008 2.56091538 1.93949089 1.85375137 1.93955865 9.23245187 9.31803946 9.586 9.67157706 9.93954813 9.31803946 17.3182486 1.93955865 16.6111471 1.93955339 17.2324466 2.56085289 17.2324466 1.85374611 9.85374611 9.23244661 9.50019272 9.586 9.85374611 9.93955339 17.2324466 17.3182539 17.9395534 16.6111471 10.5608529 9.23244661 10.5608529 9.93955339 17.9395534 2.56085289 18.2931068 2.2072995 17.9395534 1.85374611 17.3182539 1.23244661 16.9647058 0.878898482 16.6111524 1.23244135 9.23245187 8.61092215 9.93954813 8.61092215 2.56084763 1.23244135 2.20723173 0.87883598 1.85368362 1.23250911 1.23238412 1.85402831 0.878955712 2.20758169 1.23244661 2.56107259 8.61092741 9.93955339 8.61092215 9.23245187 1.23244135 16.6111524 0.878898482 16.9647058 1.23244661 17.3182539 1.85374611 17.9395534 2.2072995 18.2931068 2.56085289 17.9395534 9.93955339 10.5608529 9.23244661 10.5608529 16.6111471 17.9395534"></polygon>

+ 81 - 19
src/plugins/Tus10.js

@@ -15,33 +15,69 @@ export default class Tus10 extends Plugin {
 
 
     // set default options
     // set default options
     const defaultOptions = {
     const defaultOptions = {
-      resume: true
+      resume: true,
+      allowPause: true
     }
     }
 
 
     // merge default options with the ones set by user
     // merge default options with the ones set by user
     this.opts = Object.assign({}, defaultOptions, opts)
     this.opts = Object.assign({}, defaultOptions, opts)
   }
   }
 
 
-  pauseUpload (fileID) {
+  pauseResume (action, fileID) {
     const updatedFiles = Object.assign({}, this.core.getState().files)
     const updatedFiles = Object.assign({}, this.core.getState().files)
-    const wasPaused = updatedFiles[fileID].isPaused || false
+    const inProgressUpdatedFiles = Object.keys(updatedFiles).filter((file) => {
-    const isPaused = !wasPaused
+      return !updatedFiles[file].progress.uploadComplete &&
-    let updatedFile
+             updatedFiles[file].progress.uploadStarted
-    if (wasPaused) {
+    })
-      updatedFile = Object.assign({}, updatedFiles[fileID], {
-        isPaused: false
-      })
-    } else {
-      updatedFile = Object.assign({}, updatedFiles[fileID], {
-        isPaused: true
-      })
-    }
-    updatedFiles[fileID] = updatedFile
-    this.core.setState({files: updatedFiles})
 
 
-    return isPaused
+    switch (action) {
+      case 'toggle':
+        const wasPaused = updatedFiles[fileID].isPaused || false
+        const isPaused = !wasPaused
+        let updatedFile
+        if (wasPaused) {
+          updatedFile = Object.assign({}, updatedFiles[fileID], {
+            isPaused: false
+          })
+        } else {
+          updatedFile = Object.assign({}, updatedFiles[fileID], {
+            isPaused: true
+          })
+        }
+        updatedFiles[fileID] = updatedFile
+        this.core.setState({files: updatedFiles})
+        return isPaused
+      case 'pauseAll':
+        inProgressUpdatedFiles.forEach((file) => {
+          const updatedFile = Object.assign({}, updatedFiles[file], {
+            isPaused: true
+          })
+          updatedFiles[file] = updatedFile
+        })
+        this.core.setState({files: updatedFiles})
+        return
+      case 'resumeAll':
+        inProgressUpdatedFiles.forEach((file) => {
+          const updatedFile = Object.assign({}, updatedFiles[file], {
+            isPaused: false
+          })
+          updatedFiles[file] = updatedFile
+        })
+        this.core.setState({files: updatedFiles})
+        return
+    }
   }
   }
 
 
+  // pauseResumeAll (action) {
+  //   let updatedFiles = Object.assign({}, this.core.getState().files)
+  //   updatedFiles = Object.keys(updatedFiles).map((file) => {
+  //     return Object.assign({}, updatedFiles[file], {
+  //       isPaused: action
+  //     })
+  //   })
+  //   this.core.setState({files: updatedFiles})
+  // }
+
 /**
 /**
  * Create a new Tus upload
  * Create a new Tus upload
  *
  *
@@ -85,19 +121,33 @@ export default class Tus10 extends Plugin {
 
 
       this.core.emitter.on('file-remove', (fileID) => {
       this.core.emitter.on('file-remove', (fileID) => {
         if (fileID === file.id) {
         if (fileID === file.id) {
+          console.log('removing file: ', fileID)
           upload.abort()
           upload.abort()
+          resolve(`upload ${fileID} was removed`)
         }
         }
       })
       })
 
 
       this.core.emitter.on('core:upload-pause', (fileID) => {
       this.core.emitter.on('core:upload-pause', (fileID) => {
         if (fileID === file.id) {
         if (fileID === file.id) {
-          const isPaused = this.pauseUpload(fileID)
+          const isPaused = this.pauseResume('toggle', fileID)
           isPaused ? upload.abort() : upload.start()
           isPaused ? upload.abort() : upload.start()
         }
         }
       })
       })
 
 
+      this.core.emitter.on('core:pause-all', () => {
+        const files = this.core.getState().files
+        if (!files[file.id]) return
+        upload.abort()
+      })
+
+      this.core.emitter.on('core:resume-all', () => {
+        const files = this.core.getState().files
+        if (!files[file.id]) return
+        upload.start()
+      })
+
       upload.start()
       upload.start()
-      this.core.emitter.emit('core:file-upload-started', file.id)
+      this.core.emitter.emit('core:file-upload-started', file.id, upload)
     })
     })
   }
   }
 
 
@@ -194,7 +244,19 @@ export default class Tus10 extends Plugin {
     this.uploadFiles(filesForUpload)
     this.uploadFiles(filesForUpload)
   }
   }
 
 
+  actions () {
+    this.core.emitter.on('core:pause-all', () => {
+      this.pauseResume('pauseAll')
+    })
+
+    this.core.emitter.on('core:resume-all', () => {
+      this.pauseResume('resumeAll')
+    })
+  }
+
   install () {
   install () {
+    this.actions()
+
     const bus = this.core.emitter
     const bus = this.core.emitter
     bus.on('core:upload', () => {
     bus.on('core:upload', () => {
       this.core.log('Tus is uploading...')
       this.core.log('Tus is uploading...')