Browse Source

Merge pull request #438 from transloadit/chore/refactors

Refactor Core and Plugins
Artur Paikin 7 years ago
parent
commit
92c3ff3298
70 changed files with 623 additions and 1709 deletions
  1. 1 1
      README.md
  2. 2 0
      examples/bundled-example/index.html
  3. 16 19
      examples/bundled-example/main.js
  4. 1 1
      examples/cdn-example/index.html
  5. 121 160
      src/core/Core.js
  6. 48 72
      src/core/Core.test.js
  7. 11 11
      src/core/Plugin.js
  8. 3 3
      src/core/Utils.js
  9. 8 40
      src/index.js
  10. 16 16
      src/plugins/AwsS3/index.js
  11. 7 2
      src/plugins/Dashboard/FileCard.js
  12. 47 52
      src/plugins/Dashboard/index.js
  13. 8 8
      src/plugins/DragDrop/index.js
  14. 6 8
      src/plugins/Dropbox/index.js
  15. 5 5
      src/plugins/Dummy.js
  16. 5 5
      src/plugins/FileInput.js
  17. 41 41
      src/plugins/GoldenRetriever/index.js
  18. 6 8
      src/plugins/GoogleDrive/index.js
  19. 3 3
      src/plugins/Informer.js
  20. 7 9
      src/plugins/Instagram/index.js
  21. 5 6
      src/plugins/MagicLog.js
  22. 0 51
      src/plugins/MetaData.js
  23. 0 372
      src/plugins/Plugin.test.js
  24. 3 3
      src/plugins/ProgressBar.js
  25. 5 5
      src/plugins/Provider/index.js
  26. 0 0
      src/plugins/Provider/view/AuthView.js
  27. 0 0
      src/plugins/Provider/view/Breadcrumb.js
  28. 0 0
      src/plugins/Provider/view/Breadcrumbs.js
  29. 0 0
      src/plugins/Provider/view/Browser.js
  30. 0 0
      src/plugins/Provider/view/Loader.js
  31. 0 0
      src/plugins/Provider/view/Table.js
  32. 0 0
      src/plugins/Provider/view/TableRow.js
  33. 18 21
      src/plugins/Provider/view/index.js
  34. 6 6
      src/plugins/Redux.js
  35. 10 16
      src/plugins/Redux.test.js
  36. 10 10
      src/plugins/ReduxDevTools.js
  37. 0 5
      src/plugins/RestoreFiles/index.js
  38. 9 9
      src/plugins/StatusBar/index.js
  39. 41 41
      src/plugins/Transloadit/index.js
  40. 43 44
      src/plugins/Tus.js
  41. 0 5
      src/plugins/Tus10.js
  42. 10 10
      src/plugins/Webcam/index.js
  43. 29 29
      src/plugins/XHRUpload.js
  44. 4 3
      src/scss/_dashboard.scss
  45. 1 2
      src/scss/_statusbar.scss
  46. 0 70
      test/acceptance/dragdrop.spec.js
  47. 0 21
      test/acceptance/dummy.spec.js
  48. 0 49
      test/acceptance/fallback.spec.js
  49. 0 40
      test/acceptance/i18n.spec.js
  50. BIN
      test/acceptance/image.jpg
  51. BIN
      test/acceptance/image2.jpg
  52. 0 135
      test/acceptance/index.js
  53. 0 65
      test/acceptance/multipart.spec.js
  54. 0 49
      test/acceptance/saucelabs-dummy.spec.js
  55. 0 118
      test/acceptance/tools.js
  56. BIN
      test/acceptance/xpi/JSErrorCollector.xpi
  57. BIN
      test/acceptance/xpi/firebug-2.0.16.xpi
  58. 4 4
      test/mocks/acquirerPlugin1.js
  59. 4 4
      test/mocks/acquirerPlugin2.js
  60. 4 4
      test/mocks/invalidPluginWithoutId.js
  61. 4 4
      test/mocks/invalidPluginWithoutType.js
  62. 1 1
      website/src/api-usage-example.ejs
  63. 1 1
      website/src/docs/index.md
  64. 1 1
      website/src/docs/react.md
  65. 33 20
      website/src/docs/uppy.md
  66. 2 2
      website/src/docs/xhrupload.md
  67. 6 9
      website/src/examples/dashboard/app.es6
  68. 6 9
      website/src/examples/dashboard/index.ejs
  69. 1 1
      website/themes/uppy/layout/index.ejs
  70. 0 0
      website/themes/uppy/layout/partials/frontpage-code-sample.html

+ 1 - 1
README.md

@@ -33,7 +33,7 @@ const uppy = Uppy({ autoProceed: false })
   .use(GoogleDrive, { target: Dashboard, host: 'https://server.uppy.io' })
   .use(Tus, { endpoint: '://master.tus.io/files/' })
   .run()
-  .on('core:success', files => console.log(`Successfully uploaded these files: ${files}`))
+  .on('success', files => console.log(`Successfully uploaded these files: ${files}`))
 ```
 
 **[Try it online](http://uppy.io/examples/dashboard/)** or **[read the docs](http://uppy.io/docs)**  for details on how to use Uppy and its plugins.

+ 2 - 0
examples/bundled-example/index.html

@@ -21,10 +21,12 @@
     <main>
       <h1>Uppy is here</h1>
       <button id="uppyModalOpener">Choose Files</button>
+      <button id="uppyModalOpener2">Choose Files</button>
 
       <div class="Uppy">
         <form class="MyForm" action="/">
           <input type="file" />
+          <input type="checkbox" name="check_test" value="1" checked>
           <input type="hidden" name="bla" value="12333">
           <input type="text" name="yo" value="1">
           <button type="submit">Upload</button>

+ 16 - 19
examples/bundled-example/main.js

@@ -1,13 +1,13 @@
 const Uppy = require('../../src/core')
 const Dashboard = require('../../src/plugins/Dashboard')
-// const GoogleDrive = require('../../src/plugins/GoogleDrive')
+const GoogleDrive = require('../../src/plugins/GoogleDrive')
 const Dropbox = require('../../src/plugins/Dropbox')
 const Instagram = require('../../src/plugins/Instagram')
 const Webcam = require('../../src/plugins/Webcam')
 const Tus = require('../../src/plugins/Tus')
 // const XHRUpload = require('../../src/plugins/XHRUpload')
 // const FileInput = require('../../src/plugins/FileInput')
-const MetaData = require('../../src/plugins/MetaData')
+// const MetaData = require('../../src/plugins/MetaData')
 // const Informer = require('../../src/plugins/Informer')
 // const StatusBar = require('../../src/plugins/StatusBar')
 // const DragDrop = require('../../src/plugins/DragDrop')
@@ -20,7 +20,8 @@ const uppy = Uppy({
   debug: true,
   autoProceed: false,
   meta: {
-    username: 'John'
+    username: 'John',
+    license: 'Creative Commons'
   }
   // restrictions: {
   //   maxFileSize: 300000,
@@ -43,36 +44,34 @@ const uppy = Uppy({
 })
   .use(Dashboard, {
     trigger: '#uppyModalOpener',
+    target: '.MyForm',
     // maxWidth: 350,
     // maxHeight: 400,
     inline: false,
-    // disableStatusBar: true,
-    // disableInformer: true,
+    disableStatusBar: false,
+    disableInformer: false,
     getMetaFromForm: true,
-    // replaceTargetContent: true,
-    // target: '.MyForm',
+    replaceTargetContent: false,
     hideUploadButton: false,
     closeModalOnClickOutside: false,
     locale: {
-      strings: {browse: 'browse'}
-    }
+      strings: { browse: 'browse' }
+    },
+    metaFields: [
+      { id: 'license', name: 'License', placeholder: 'specify license' },
+      { id: 'caption', name: 'Caption', placeholder: 'describe what the image is about' }
+    ]
     // note: 'Images and video only, 300kb or less'
   })
-  // .use(GoogleDrive, {target: Dashboard, host: 'http://localhost:3020'})
+  .use(GoogleDrive, {target: Dashboard, host: 'http://localhost:3020'})
   .use(Dropbox, {target: Dashboard, host: 'http://localhost:3020'})
   .use(Instagram, {target: Dashboard, host: 'http://localhost:3020'})
   .use(Webcam, {target: Dashboard})
   .use(Tus, {endpoint: TUS_ENDPOINT, resume: true})
-  .use(MetaData, {
-    fields: [
-      { id: 'license', name: 'License', value: 'Creative Commons', placeholder: 'specify license' },
-      { id: 'caption', name: 'Caption', value: 'none', placeholder: 'describe what the image is about' }
-    ]
-  })
   // .use(GoldenRetriever, {serviceWorker: true})
   .run()
 
-uppy.on('core:complete', ({ successful, failed }) => {
+uppy.on('complete', ({ successful, failed }) => {
   if (failed.length === 0) {
     console.log('UPLOAD SUCCESSFUL!!!')
   } else {
@@ -93,7 +92,5 @@ if ('serviceWorker' in navigator) {
     })
 }
 
-// uppy.emit('informer', 'Smile!', 'info', 2000)
-
 var modalTrigger = document.querySelector('#uppyModalOpener')
 if (modalTrigger) modalTrigger.click()

+ 1 - 1
examples/cdn-example/index.html

@@ -26,7 +26,7 @@
 
       uppy.run()
 
-      uppy.on('core:success', (fileCount) => {
+      uppy.on('success', (fileCount) => {
         console.log(`${fileCount} files uploaded`)
       })
 

+ 121 - 160
src/core/Core.js

@@ -1,6 +1,5 @@
 const Utils = require('../core/Utils')
 const Translator = require('../core/Translator')
-const UppySocket = require('./UppySocket')
 const ee = require('namespace-emitter')
 const cuid = require('cuid')
 const throttle = require('lodash.throttle')
@@ -68,15 +67,16 @@ class Uppy {
     this.i18n = this.translator.translate.bind(this.translator)
     this.getState = this.getState.bind(this)
     this.getPlugin = this.getPlugin.bind(this)
-    this.updateMeta = this.updateMeta.bind(this)
-    this.initSocket = this.initSocket.bind(this)
+    this.setFileMeta = this.setFileMeta.bind(this)
+    this.setFileState = this.setFileState.bind(this)
+    // this._initSocket = this._initSocket.bind(this)
     this.log = this.log.bind(this)
     this.info = this.info.bind(this)
     this.hideInfo = this.hideInfo.bind(this)
     this.addFile = this.addFile.bind(this)
     this.removeFile = this.removeFile.bind(this)
     this.pauseResume = this.pauseResume.bind(this)
-    this.calculateProgress = this.calculateProgress.bind(this)
+    this._calculateProgress = this._calculateProgress.bind(this)
     this.resetProgress = this.resetProgress.bind(this)
 
     this.pauseAll = this.pauseAll.bind(this)
@@ -114,7 +114,7 @@ class Uppy {
     })
 
     this._storeUnsubscribe = this.store.subscribe((prevState, nextState, patch) => {
-      this.emit('core:state-update', prevState, nextState, patch)
+      this.emit('state-update', prevState, nextState, patch)
       this.updateAll(nextState)
     })
 
@@ -157,6 +157,17 @@ class Uppy {
     return this.getState()
   }
 
+  /**
+  * Shorthand to set state for a specific file
+  */
+  setFileState (fileID, state) {
+    this.setState({
+      files: Object.assign({}, this.getState().files, {
+        [fileID]: Object.assign({}, this.getState().files[fileID], state)
+      })
+    })
+  }
+
   resetProgress () {
     const defaultProgress = {
       percentage: 0,
@@ -178,7 +189,7 @@ class Uppy {
     })
 
     // TODO Document on the website
-    this.emit('core:reset-progress')
+    this.emit('reset-progress')
   }
 
   addPreProcessor (fn) {
@@ -221,7 +232,7 @@ class Uppy {
     this.setState({meta: newMeta})
   }
 
-  updateMeta (data, fileID) {
+  setFileMeta (fileID, data) {
     const updatedFiles = Object.assign({}, this.getState().files)
     if (!updatedFiles[fileID]) {
       this.log('Was trying to set metadata for a file that’s not with us anymore: ', fileID)
@@ -234,13 +245,22 @@ class Uppy {
     this.setState({files: updatedFiles})
   }
 
+  /**
+   * Get a file object.
+   *
+   * @param {string} fileID The ID of the file object to return.
+   */
+  getFile (fileID) {
+    return this.getState().files[fileID]
+  }
+
   /**
   * Check if minNumberOfFiles restriction is reached before uploading
   *
   * @return {boolean}
   * @private
   */
-  checkMinNumberOfFiles () {
+  _checkMinNumberOfFiles () {
     const {minNumberOfFiles} = this.opts.restrictions
     if (Object.keys(this.getState().files).length < minNumberOfFiles) {
       this.info(`${this.i18n('youHaveToAtLeastSelectX', {smart_count: minNumberOfFiles})}`, 'error', 5000)
@@ -257,7 +277,7 @@ class Uppy {
   * @return {boolean}
   * @private
   */
-  checkRestrictions (file) {
+  _checkRestrictions (file) {
     const {maxFileSize, maxNumberOfFiles, allowedFileTypes} = this.opts.restrictions
 
     if (maxNumberOfFiles) {
@@ -343,13 +363,13 @@ class Uppy {
           preview: file.preview
         }
 
-        const isFileAllowed = this.checkRestrictions(newFile)
+        const isFileAllowed = this._checkRestrictions(newFile)
         if (!isFileAllowed) return Promise.reject(new Error('File not allowed'))
 
         updatedFiles[fileID] = newFile
         this.setState({files: updatedFiles})
 
-        this.emit('core:file-added', newFile)
+        this.emit('file-added', newFile)
         this.log(`Added file: ${fileName}, ${fileID}, mime type: ${fileType}`)
 
         if (this.opts.autoProceed && !this.scheduledAutoProceed) {
@@ -370,8 +390,8 @@ class Uppy {
     delete updatedFiles[fileID]
 
     this.setState({files: updatedFiles})
-    this.calculateTotalProgress()
-    this.emit('core:file-removed', fileID)
+    this._calculateTotalProgress()
+    this.emit('file-removed', fileID)
 
     // Clean up object URLs.
     if (removedFile.preview && Utils.isObjectURL(removedFile.preview)) {
@@ -381,15 +401,6 @@ class Uppy {
     this.log(`Removed file: ${fileID}`)
   }
 
-  /**
-   * Get a file object.
-   *
-   * @param {string} fileID The ID of the file object to return.
-   */
-  getFile (fileID) {
-    return this.getState().files[fileID]
-  }
-
   /**
    * Generate a preview image for the given file, if possible.
    */
@@ -413,14 +424,7 @@ class Uppy {
    * Set the preview URL for a file.
    */
   setPreviewURL (fileID, preview) {
-    const { files } = this.getState()
-    this.setState({
-      files: Object.assign({}, files, {
-        [fileID]: Object.assign({}, files[fileID], {
-          preview: preview
-        })
-      })
-    })
+    this.setFileState(fileID, { preview: preview })
   }
 
   pauseResume (fileID) {
@@ -438,7 +442,7 @@ class Uppy {
     updatedFiles[fileID] = updatedFile
     this.setState({files: updatedFiles})
 
-    this.emit('core:upload-pause', fileID, isPaused)
+    this.emit('upload-pause', fileID, isPaused)
 
     return isPaused
   }
@@ -458,7 +462,7 @@ class Uppy {
     })
     this.setState({files: updatedFiles})
 
-    this.emit('core:pause-all')
+    this.emit('pause-all')
   }
 
   resumeAll () {
@@ -477,7 +481,7 @@ class Uppy {
     })
     this.setState({files: updatedFiles})
 
-    this.emit('core:resume-all')
+    this.emit('resume-all')
   }
 
   retryAll () {
@@ -498,10 +502,15 @@ class Uppy {
       error: null
     })
 
-    this.emit('core:retry-all', filesToRetry)
+    this.emit('retry-all', filesToRetry)
+
+    const uploadID = this._createUpload(filesToRetry)
+    return this._runUpload(uploadID)
+  }
 
-    const uploadID = this.createUpload(filesToRetry)
-    return this.runUpload(uploadID)
+  cancelAll () {
+    this.emit('cancel-all')
+    this.setState({ files: {}, totalProgress: 0 })
   }
 
   retryUpload (fileID) {
@@ -514,50 +523,37 @@ class Uppy {
       files: updatedFiles
     })
 
-    this.emit('core:upload-retry', fileID)
+    this.emit('upload-retry', fileID)
 
-    const uploadID = this.createUpload([ fileID ])
-    return this.runUpload(uploadID)
+    const uploadID = this._createUpload([ fileID ])
+    return this._runUpload(uploadID)
   }
 
   reset () {
     this.cancelAll()
   }
 
-  cancelAll () {
-    this.emit('core:cancel-all')
-    this.setState({ files: {}, totalProgress: 0 })
-  }
-
-  calculateProgress (data) {
+  _calculateProgress (data) {
     const fileID = data.id
-    const updatedFiles = Object.assign({}, this.getState().files)
 
     // skip progress event for a file that’s been removed
-    if (!updatedFiles[fileID]) {
-      this.log('Trying to set progress for a file that’s not with us anymore: ', fileID)
+    if (!this.getState().files[fileID]) {
+      this.log('Trying to set progress for a file that’s been removed: ', fileID)
       return
     }
 
-    const updatedFile = Object.assign({}, updatedFiles[fileID],
-      Object.assign({}, {
-        progress: Object.assign({}, updatedFiles[fileID].progress, {
-          bytesUploaded: data.bytesUploaded,
-          bytesTotal: data.bytesTotal,
-          percentage: Math.floor((data.bytesUploaded / data.bytesTotal * 100).toFixed(2))
-        })
-      }
-    ))
-    updatedFiles[data.id] = updatedFile
-
-    this.setState({
-      files: updatedFiles
+    this.setFileState(fileID, {
+      progress: Object.assign({}, this.getState().files[fileID].progress, {
+        bytesUploaded: data.bytesUploaded,
+        bytesTotal: data.bytesTotal,
+        percentage: Math.floor((data.bytesUploaded / data.bytesTotal * 100).toFixed(2))
+      })
     })
 
-    this.calculateTotalProgress()
+    this._calculateTotalProgress()
   }
 
-  calculateTotalProgress () {
+  _calculateTotalProgress () {
     // calculate total progress, using the number of files currently uploading,
     // multiplied by 100 and the summ of individual progress of each file
     const files = Object.assign({}, this.getState().files)
@@ -594,23 +590,13 @@ class Uppy {
     //   this.setState({bla: 'bla'})
     // }, 20)
 
-    // this.on('core:state-update', (prevState, nextState, patch) => {
-    //   if (this.withDevTools) {
-    //     this.devTools.send('UPPY_STATE_UPDATE', nextState)
-    //   }
-    // })
-
-    this.on('core:error', (error) => {
+    this.on('error', (error) => {
       this.setState({ error: error.message })
     })
 
-    this.on('core:upload-error', (fileID, error) => {
-      const updatedFiles = Object.assign({}, this.getState().files)
-      const updatedFile = Object.assign({}, updatedFiles[fileID],
-        { error: error.message }
-      )
-      updatedFiles[fileID] = updatedFile
-      this.setState({ files: updatedFiles, error: error.message })
+    this.on('upload-error', (fileID, error) => {
+      this.setFileState(fileID, { error: error.message })
+      this.setState({ error: error.message })
 
       const fileName = this.getState().files[fileID].name
       let message = `Failed to upload ${fileName}`
@@ -620,83 +606,63 @@ class Uppy {
       this.info(message, 'error', 5000)
     })
 
-    this.on('core:upload', () => {
+    this.on('upload', () => {
       this.setState({ error: null })
     })
 
-    this.on('core:file-add', (data) => {
-      this.addFile(data)
-    })
+    // this.on('file-add', (data) => {
+    //   this.addFile(data)
+    // })
 
-    this.on('core:file-added', (file) => {
+    this.on('file-added', (file) => {
       this.generatePreview(file)
     })
 
-    this.on('core:file-remove', (fileID) => {
+    this.on('file-remove', (fileID) => {
       this.removeFile(fileID)
     })
 
-    this.on('core:upload-started', (fileID, upload) => {
-      const updatedFiles = Object.assign({}, this.getState().files)
-      const updatedFile = Object.assign({}, updatedFiles[fileID],
-        Object.assign({}, {
-          progress: Object.assign({}, updatedFiles[fileID].progress, {
-            uploadStarted: Date.now(),
-            uploadComplete: false,
-            percentage: 0,
-            bytesUploaded: 0
-          })
-        }
-      ))
-      updatedFiles[fileID] = updatedFile
-
-      this.setState({files: updatedFiles})
+    this.on('upload-started', (fileID, upload) => {
+      this.setFileState(fileID, {
+        progress: Object.assign({}, this.getState().files[fileID].progress, {
+          uploadStarted: Date.now(),
+          uploadComplete: false,
+          percentage: 0,
+          bytesUploaded: 0
+        })
+      })
     })
 
     // upload progress events can occur frequently, especially when you have a good
     // connection to the remote server. Therefore, we are throtteling them to
     // prevent accessive function calls.
     // see also: https://github.com/tus/tus-js-client/commit/9940f27b2361fd7e10ba58b09b60d82422183bbb
-    const throttledCalculateProgress = throttle(this.calculateProgress, 100, {leading: true, trailing: false})
+    const _throttledCalculateProgress = throttle(this._calculateProgress, 100, { leading: true, trailing: false })
 
-    this.on('core:upload-progress', (data) => {
-      throttledCalculateProgress(data)
-    })
+    this.on('upload-progress', _throttledCalculateProgress)
 
-    this.on('core:upload-success', (fileID, uploadResp, uploadURL) => {
-      const updatedFiles = Object.assign({}, this.getState().files)
-      const updatedFile = Object.assign({}, updatedFiles[fileID], {
-        progress: Object.assign({}, updatedFiles[fileID].progress, {
+    this.on('upload-success', (fileID, uploadResp, uploadURL) => {
+      this.setFileState(fileID, {
+        progress: Object.assign({}, this.getState().files[fileID].progress, {
           uploadComplete: true,
           percentage: 100
         }),
         uploadURL: uploadURL,
         isPaused: false
       })
-      updatedFiles[fileID] = updatedFile
 
-      this.setState({
-        files: updatedFiles
-      })
-
-      this.calculateTotalProgress()
+      this._calculateTotalProgress()
     })
 
-    this.on('core:update-meta', (data, fileID) => {
-      this.updateMeta(data, fileID)
-    })
-
-    this.on('core:preprocess-progress', (fileID, progress) => {
-      const files = Object.assign({}, this.getState().files)
-      files[fileID] = Object.assign({}, files[fileID], {
-        progress: Object.assign({}, files[fileID].progress, {
+    this.on('preprocess-progress', (fileID, progress) => {
+      this.setFileState(fileID, {
+        progress: Object.assign({}, this.getState().files[fileID].progress, {
           preprocess: progress
         })
       })
-
-      this.setState({ files: files })
     })
-    this.on('core:preprocess-complete', (fileID) => {
+
+    this.on('preprocess-complete', (fileID) => {
       const files = Object.assign({}, this.getState().files)
       files[fileID] = Object.assign({}, files[fileID], {
         progress: Object.assign({}, files[fileID].progress)
@@ -705,17 +671,16 @@ class Uppy {
 
       this.setState({ files: files })
     })
-    this.on('core:postprocess-progress', (fileID, progress) => {
-      const files = Object.assign({}, this.getState().files)
-      files[fileID] = Object.assign({}, files[fileID], {
-        progress: Object.assign({}, files[fileID].progress, {
+
+    this.on('postprocess-progress', (fileID, progress) => {
+      this.setFileState(fileID, {
+        progress: Object.assign({}, this.getState().files[fileID].progress, {
           postprocess: progress
         })
       })
-
-      this.setState({ files: files })
     })
-    this.on('core:postprocess-complete', (fileID) => {
+
+    this.on('postprocess-complete', (fileID) => {
       const files = Object.assign({}, this.getState().files)
       files[fileID] = Object.assign({}, files[fileID], {
         progress: Object.assign({}, files[fileID].progress)
@@ -826,7 +791,7 @@ class Uppy {
    * @param function method description
    */
   iteratePlugins (method) {
-    Object.keys(this.plugins).forEach((pluginType) => {
+    Object.keys(this.plugins).forEach(pluginType => {
       this.plugins[pluginType].forEach(method)
     })
   }
@@ -855,19 +820,15 @@ class Uppy {
   close () {
     this.reset()
 
-    if (this.withDevTools) {
-      this.devToolsUnsubscribe()
-    }
-
     this._storeUnsubscribe()
 
     this.iteratePlugins((plugin) => {
       plugin.uninstall()
     })
 
-    if (this.socket) {
-      this.socket.close()
-    }
+    // if (this.socket) {
+    //   this.socket.close()
+    // }
   }
 
   /**
@@ -889,7 +850,7 @@ class Uppy {
       }
     })
 
-    this.emit('core:info-visible')
+    this.emit('info-visible')
 
     window.clearTimeout(this.infoTimeoutID)
     if (duration === 0) {
@@ -908,7 +869,7 @@ class Uppy {
     this.setState({
       info: newInfo
     })
-    this.emit('core:info-hidden')
+    this.emit('info-hidden')
   }
 
   /**
@@ -945,13 +906,13 @@ class Uppy {
     }
   }
 
-  initSocket (opts) {
-    if (!this.socket) {
-      this.socket = new UppySocket(opts)
-    }
+  // _initSocket (opts) {
+  //   if (!this.socket) {
+  //     this.socket = new UppySocket(opts)
+  //   }
 
-    return this.socket
-  }
+  //   return this.socket
+  // }
 
   /**
    * Initializes actions, installs all plugins (by iterating on them and calling `install`), sets options
@@ -971,11 +932,11 @@ class Uppy {
     this.log(`Core: attempting to restore upload "${uploadID}"`)
 
     if (!this.getState().currentUploads[uploadID]) {
-      this.removeUpload(uploadID)
+      this._removeUpload(uploadID)
       return Promise.reject(new Error('Nonexistent upload'))
     }
 
-    return this.runUpload(uploadID)
+    return this._runUpload(uploadID)
   }
 
   /**
@@ -984,10 +945,10 @@ class Uppy {
    * @param {Array<string>} fileIDs File IDs to include in this upload.
    * @return {string} ID of this upload.
    */
-  createUpload (fileIDs) {
+  _createUpload (fileIDs) {
     const uploadID = cuid()
 
-    this.emit('core:upload', {
+    this.emit('upload', {
       id: uploadID,
       fileIDs: fileIDs
     })
@@ -1009,7 +970,7 @@ class Uppy {
    *
    * @param {string} uploadID The ID of the upload.
    */
-  removeUpload (uploadID) {
+  _removeUpload (uploadID) {
     const currentUploads = Object.assign({}, this.getState().currentUploads)
     delete currentUploads[uploadID]
 
@@ -1023,7 +984,7 @@ class Uppy {
    *
    * @private
    */
-  runUpload (uploadID) {
+  _runUpload (uploadID) {
     const uploadData = this.getState().currentUploads[uploadID]
     const fileIDs = uploadData.fileIDs
     const restoreStep = uploadData.step
@@ -1059,21 +1020,21 @@ class Uppy {
     // Not returning the `catch`ed promise, because we still want to return a rejected
     // promise from this method if the upload failed.
     lastStep.catch((err) => {
-      this.emit('core:error', err)
+      this.emit('error', err)
 
-      this.removeUpload(uploadID)
+      this._removeUpload(uploadID)
     })
 
     return lastStep.then(() => {
       const files = fileIDs.map((fileID) => this.getFile(fileID))
       const successful = files.filter((file) => !file.error)
       const failed = files.filter((file) => file.error)
-      this.emit('core:complete', { successful, failed })
+      this.emit('complete', { successful, failed })
 
       // Compatibility with pre-0.21
-      this.emit('core:success', fileIDs)
+      this.emit('success', fileIDs)
 
-      this.removeUpload(uploadID)
+      this._removeUpload(uploadID)
 
       return { successful, failed }
     })
@@ -1089,7 +1050,7 @@ class Uppy {
       this.log('No uploader type plugins are used', 'warning')
     }
 
-    const isMinNumberOfFilesReached = this.checkMinNumberOfFiles()
+    const isMinNumberOfFilesReached = this._checkMinNumberOfFiles()
     if (!isMinNumberOfFilesReached) {
       return Promise.reject(new Error('Minimum number of files has not been reached'))
     }
@@ -1111,8 +1072,8 @@ class Uppy {
         }
       })
 
-      const uploadID = this.createUpload(waitingFileIDs)
-      return this.runUpload(uploadID)
+      const uploadID = this._createUpload(waitingFileIDs)
+      return this._runUpload(uploadID)
     })
   }
 }

+ 48 - 72
src/core/Core.test.js

@@ -1,6 +1,6 @@
 import Core from './Core'
 import utils from './Utils'
-import Plugin from '../../src/plugins/Plugin'
+import Plugin from './Plugin'
 import AcquirerPlugin1 from '../../test/mocks/acquirerPlugin1'
 import AcquirerPlugin2 from '../../test/mocks/acquirerPlugin2'
 import InvalidPlugin from '../../test/mocks/invalidPlugin'
@@ -141,7 +141,7 @@ describe('src/Core', () => {
     it('should update the state', () => {
       const core = new Core()
       const stateUpdateEventMock = jest.fn()
-      core.on('core:state-update', stateUpdateEventMock)
+      core.on('state-update', stateUpdateEventMock)
       core.use(AcquirerPlugin1)
       core.use(AcquirerPlugin2)
 
@@ -215,8 +215,8 @@ describe('src/Core', () => {
     // const corePauseEventMock = jest.fn()
     const coreCancelEventMock = jest.fn()
     const coreStateUpdateEventMock = jest.fn()
-    core.on('core:cancel-all', coreCancelEventMock)
-    core.on('core:state-update', coreStateUpdateEventMock)
+    core.on('cancel-all', coreCancelEventMock)
+    core.on('state-update', coreStateUpdateEventMock)
     core.setState({ foo: 'bar', totalProgress: 30 })
 
     core.reset()
@@ -242,9 +242,9 @@ describe('src/Core', () => {
     // const corePauseEventMock = jest.fn()
     const coreCancelEventMock = jest.fn()
     const coreStateUpdateEventMock = jest.fn()
-    // core.on('core:pause-all', corePauseEventMock)
-    core.on('core:cancel-all', coreCancelEventMock)
-    core.on('core:state-update', coreStateUpdateEventMock)
+    // core.on('pause-all', corePauseEventMock)
+    core.on('cancel-all', coreCancelEventMock)
+    core.on('state-update', coreStateUpdateEventMock)
 
     core.close()
 
@@ -312,7 +312,7 @@ describe('src/Core', () => {
         })
     })
 
-    it('should update the file progress state when core:preprocess-progress event is fired', () => {
+    it('should update the file progress state when preprocess-progress event is fired', () => {
       const core = new Core()
       core.run()
       return core
@@ -324,7 +324,7 @@ describe('src/Core', () => {
         })
         .then(() => {
           const fileId = Object.keys(core.state.files)[0]
-          core.emit('core:preprocess-progress', fileId, {
+          core.emit('preprocess-progress', fileId, {
             mode: 'determinate',
             message: 'something',
             value: 0
@@ -340,7 +340,7 @@ describe('src/Core', () => {
         })
     })
 
-    it('should update the file progress state when core:preprocess-complete event is fired', () => {
+    it('should update the file progress state when preprocess-complete event is fired', () => {
       const core = new Core()
       core.run()
       return core
@@ -352,7 +352,7 @@ describe('src/Core', () => {
         })
         .then(() => {
           const fileId = Object.keys(core.state.files)[0]
-          core.emit('core:preprocess-complete', fileId, {
+          core.emit('preprocess-complete', fileId, {
             mode: 'determinate',
             message: 'something',
             value: 0
@@ -422,7 +422,7 @@ describe('src/Core', () => {
         })
     })
 
-    it('should update the file progress state when core:postprocess-progress event is fired', () => {
+    it('should update the file progress state when postprocess-progress event is fired', () => {
       const core = new Core()
       core.run()
       return core
@@ -434,7 +434,7 @@ describe('src/Core', () => {
         })
         .then(() => {
           const fileId = Object.keys(core.state.files)[0]
-          core.emit('core:postprocess-progress', fileId, {
+          core.emit('postprocess-progress', fileId, {
             mode: 'determinate',
             message: 'something',
             value: 0
@@ -450,7 +450,7 @@ describe('src/Core', () => {
         })
     })
 
-    it('should update the file progress state when core:postprocess-complete event is fired', () => {
+    it('should update the file progress state when postprocess-complete event is fired', () => {
       const core = new Core()
       core.run()
       return core
@@ -462,7 +462,7 @@ describe('src/Core', () => {
         })
         .then(() => {
           const fileId = Object.keys(core.state.files)[0]
-          core.emit('core:postprocess-complete', fileId, {
+          core.emit('postprocess-complete', fileId, {
             mode: 'determinate',
             message: 'something',
             value: 0
@@ -527,7 +527,7 @@ describe('src/Core', () => {
       const fileAddedEventMock = jest.fn()
       const core = new Core()
       core.run()
-      core.on('core:file-added', fileAddedEventMock)
+      core.on('file-added', fileAddedEventMock)
       return core
         .addFile({
           source: 'jest',
@@ -598,19 +598,19 @@ describe('src/Core', () => {
       })).rejects.toMatchObject({ message: 'onBeforeFileAdded: a plain string' })
     })
 
-    it('should call utils.generatePreview when core:file-added is triggered and thumbnail generation is allowed', () => {
+    it('should call utils.generatePreview when file-added is triggered and thumbnail generation is allowed', () => {
       const core = new Core({
       }).run()
       const file = {
         type: 'image/jpeg',
         isRemote: false
       }
-      core.emit('core:file-added', file)
+      core.emit('file-added', file)
       expect(utils.createThumbnail).toHaveBeenCalledTimes(1)
       expect(utils.createThumbnail.mock.calls[0][1]).toEqual(200)
     })
 
-    it('should return an object url of the image when core:file-added is triggered and thumbnail generation is disabled', () => {
+    it('should return an object url of the image when file-added is triggered and thumbnail generation is disabled', () => {
       const core = new Core({
         thumbnailGeneration: false
       }).run()
@@ -619,7 +619,7 @@ describe('src/Core', () => {
         isRemote: false,
         data: 'foo'
       }
-      core.emit('core:file-added', file)
+      core.emit('file-added', file)
       expect(URL.createObjectURL).toHaveBeenCalledTimes(1)
       expect(URL.createObjectURL).toHaveBeenCalledWith('foo')
     })
@@ -648,7 +648,7 @@ describe('src/Core', () => {
       core.addUploader((fileIDs) => {
         fileIDs.forEach((fileID) => {
           if (/bar/.test(core.getFile(fileID).name)) {
-            core.emit('core:upload-error', fileID, new Error('This is bar and I do not like bar'))
+            core.emit('upload-error', fileID, new Error('This is bar and I do not like bar'))
           }
         })
         return Promise.resolve()
@@ -675,7 +675,7 @@ describe('src/Core', () => {
       const fileRemovedEventMock = jest.fn()
 
       const core = new Core()
-      core.on('core:file-removed', fileRemovedEventMock)
+      core.on('file-removed', fileRemovedEventMock)
       core.run()
       return core
         .addFile({
@@ -751,32 +751,8 @@ describe('src/Core', () => {
         })
         .then(() => {
           const fileId = Object.keys(core.state.files)[0]
-          core.updateMeta({ foo: 'bar', bur: 'mur' }, fileId)
-          core.updateMeta({ boo: 'moo', bur: 'fur' }, fileId)
-          expect(core.state.files[fileId].meta).toEqual({
-            name: 'foo.jpg',
-            type: 'image/jpeg',
-            foo: 'bar',
-            bur: 'fur',
-            boo: 'moo'
-          })
-        })
-    })
-
-    it('should update meta data for a file by calling core:update-meta', () => {
-      const core = new Core()
-      core.run()
-      return core
-        .addFile({
-          source: 'jest',
-          name: 'foo.jpg',
-          type: 'image/jpeg',
-          data: utils.dataURItoFile(sampleImageDataURI, {})
-        })
-        .then(() => {
-          const fileId = Object.keys(core.state.files)[0]
-          core.emit('core:update-meta', { foo: 'bar', bur: 'mur' }, fileId)
-          core.emit('core:update-meta', { boo: 'moo', bur: 'fur' }, fileId)
+          core.setFileMeta(fileId, { foo: 'bar', bur: 'mur' })
+          core.setFileMeta(fileId, { boo: 'moo', bur: 'fur' })
           expect(core.state.files[fileId].meta).toEqual({
             name: 'foo.jpg',
             type: 'image/jpeg',
@@ -800,7 +776,7 @@ describe('src/Core', () => {
         })
         .then(() => {
           const fileId = Object.keys(core.state.files)[0]
-          core.calculateProgress({
+          core._calculateProgress({
             id: fileId,
             bytesUploaded: 12345,
             bytesTotal: 17175
@@ -813,7 +789,7 @@ describe('src/Core', () => {
             uploadStarted: false
           })
 
-          core.calculateProgress({
+          core._calculateProgress({
             id: fileId,
             bytesUploaded: 17175,
             bytesTotal: 17175
@@ -851,19 +827,19 @@ describe('src/Core', () => {
           core.state.files[fileId1].progress.uploadStarted = new Date()
           core.state.files[fileId2].progress.uploadStarted = new Date()
 
-          core.calculateProgress({
+          core._calculateProgress({
             id: fileId1,
             bytesUploaded: 12345,
             bytesTotal: 17175
           })
 
-          core.calculateProgress({
+          core._calculateProgress({
             id: fileId2,
             bytesUploaded: 10201,
             bytesTotal: 17175
           })
 
-          core.calculateTotalProgress()
+          core._calculateTotalProgress()
           expect(core.state.totalProgress).toEqual(65)
         })
     })
@@ -872,7 +848,7 @@ describe('src/Core', () => {
       const resetProgressEvent = jest.fn()
       const core = new Core()
       core.run()
-      core.on('core:reset-progress', resetProgressEvent)
+      core.on('reset-progress', resetProgressEvent)
       return core
         .addFile({
           source: 'jest',
@@ -894,19 +870,19 @@ describe('src/Core', () => {
           core.state.files[fileId1].progress.uploadStarted = new Date()
           core.state.files[fileId2].progress.uploadStarted = new Date()
 
-          core.calculateProgress({
+          core._calculateProgress({
             id: fileId1,
             bytesUploaded: 12345,
             bytesTotal: 17175
           })
 
-          core.calculateProgress({
+          core._calculateProgress({
             id: fileId2,
             bytesUploaded: 10201,
             bytesTotal: 17175
           })
 
-          core.calculateTotalProgress()
+          core._calculateTotalProgress()
 
           expect(core.state.totalProgress).toEqual(65)
 
@@ -998,28 +974,28 @@ describe('src/Core', () => {
   })
 
   describe('actions', () => {
-    it('should update the state when receiving the core:error event', () => {
+    it('should update the state when receiving the error event', () => {
       const core = new Core()
       core.run()
-      core.emit('core:error', new Error('foooooo'))
+      core.emit('error', new Error('foooooo'))
       expect(core.state.error).toEqual('foooooo')
     })
 
-    it('should update the state when receiving the core:upload-error event', () => {
+    it('should update the state when receiving the upload-error event', () => {
       const core = new Core()
       core.run()
       core.state.files['fileId'] = {
         name: 'filename'
       }
-      core.emit('core:upload-error', 'fileId', { message: 'this is the error' })
+      core.emit('upload-error', 'fileId', { message: 'this is the error' })
       expect(core.state.info).toEqual({'message': 'Failed to upload filename', 'details': 'this is the error', 'isHidden': false, 'type': 'error'})
     })
 
-    it('should reset the error state when receiving the core:upload event', () => {
+    it('should reset the error state when receiving the upload event', () => {
       const core = new Core()
       core.run()
-      core.emit('core:error', { foo: 'bar' })
-      core.emit('core:upload')
+      core.emit('error', { foo: 'bar' })
+      core.emit('upload')
       expect(core.state.error).toEqual(null)
     })
   })
@@ -1076,7 +1052,7 @@ describe('src/Core', () => {
       const infoVisibleEvent = jest.fn()
       const core = new Core()
       core.run()
-      core.on('core:info-visible', infoVisibleEvent)
+      core.on('info-visible', infoVisibleEvent)
 
       core.info('This is the message', 'info', 0)
       expect(core.state.info).toEqual({
@@ -1093,7 +1069,7 @@ describe('src/Core', () => {
       const infoVisibleEvent = jest.fn()
       const core = new Core()
       core.run()
-      core.on('core:info-visible', infoVisibleEvent)
+      core.on('info-visible', infoVisibleEvent)
 
       core.info({
         message: 'This is the message',
@@ -1118,8 +1094,8 @@ describe('src/Core', () => {
       const infoHiddenEvent = jest.fn()
       const core = new Core()
       core.run()
-      core.on('core:info-visible', infoVisibleEvent)
-      core.on('core:info-hidden', infoHiddenEvent)
+      core.on('info-visible', infoVisibleEvent)
+      core.on('info-hidden', infoHiddenEvent)
 
       core.info('This is the message', 'info', 100)
       expect(typeof core.infoTimeoutID).toEqual('number')
@@ -1141,8 +1117,8 @@ describe('src/Core', () => {
       const infoHiddenEvent = jest.fn()
       const core = new Core()
       core.run()
-      core.on('core:info-visible', infoVisibleEvent)
-      core.on('core:info-hidden', infoHiddenEvent)
+      core.on('info-visible', infoVisibleEvent)
+      core.on('info-hidden', infoHiddenEvent)
 
       core.info('This is the message', 'info', 0)
       expect(typeof core.infoTimeoutID).toEqual('undefined')
@@ -1168,7 +1144,7 @@ describe('src/Core', () => {
         type: 'image/jpeg',
         data: utils.dataURItoFile(sampleImageDataURI, {})
       }).then(() => {
-        core.createUpload(Object.keys(core.state.files))
+        core._createUpload(Object.keys(core.state.files))
         const uploadId = Object.keys(core.state.currentUploads)[0]
         const currentUploadsState = {}
         currentUploadsState[uploadId] = {
@@ -1188,7 +1164,7 @@ describe('src/Core', () => {
           const uploadId = Object.keys(core.state.currentUploads)[0]
           expect(typeof core.state.currentUploads[uploadId]).toEqual('object')
           expect(core.state.currentUploads[uploadId].fileIDs.length).toEqual(1)
-          core.removeUpload(uploadId)
+          core._removeUpload(uploadId)
           expect(typeof core.state.currentUploads[uploadId]).toEqual('undefined')
         })
       }

+ 11 - 11
src/plugins/Plugin.js → src/core/Plugin.js

@@ -13,8 +13,8 @@ const getFormData = require('get-form-data')
  * @return {array | string} files or success/fail message
  */
 module.exports = class Plugin {
-  constructor (core, opts) {
-    this.core = core
+  constructor (uppy, opts) {
+    this.uppy = uppy
     this.opts = opts || {}
 
     // clear everything inside the target selector
@@ -27,14 +27,14 @@ module.exports = class Plugin {
   }
 
   getPluginState () {
-    return this.core.state.plugins[this.id]
+    return this.uppy.state.plugins[this.id]
   }
 
   setPluginState (update) {
-    const plugins = Object.assign({}, this.core.state.plugins)
+    const plugins = Object.assign({}, this.uppy.state.plugins)
     plugins[this.id] = Object.assign({}, plugins[this.id], update)
 
-    this.core.setState({
+    this.uppy.setState({
       plugins: plugins
     })
   }
@@ -68,12 +68,12 @@ module.exports = class Plugin {
         this.el = yo.update(this.el, this.render(state))
       })
 
-      this.core.log(`Installing ${callerPluginName} to a DOM element`)
+      this.uppy.log(`Installing ${callerPluginName} to a DOM element`)
 
       // attempt to extract meta from form element
       if (this.opts.getMetaFromForm && targetElement.nodeName === 'FORM') {
         const formMeta = getFormData(targetElement)
-        this.core.setMeta(formMeta)
+        this.uppy.setMeta(formMeta)
       }
 
       // clear everything inside the target container
@@ -81,7 +81,7 @@ module.exports = class Plugin {
         targetElement.innerHTML = ''
       }
 
-      this.el = plugin.render(this.core.state)
+      this.el = plugin.render(this.uppy.state)
       targetElement.appendChild(this.el)
 
       return this.el
@@ -95,7 +95,7 @@ module.exports = class Plugin {
       // Targeting a plugin type
       const Target = target
       // Find the target plugin instance.
-      this.core.iteratePlugins((plugin) => {
+      this.uppy.iteratePlugins((plugin) => {
         if (plugin instanceof Target) {
           targetPlugin = plugin
           return false
@@ -105,12 +105,12 @@ module.exports = class Plugin {
 
     if (targetPlugin) {
       const targetPluginName = targetPlugin.id
-      this.core.log(`Installing ${callerPluginName} to ${targetPluginName}`)
+      this.uppy.log(`Installing ${callerPluginName} to ${targetPluginName}`)
       this.el = targetPlugin.addTarget(plugin)
       return this.el
     }
 
-    this.core.log(`Not installing ${callerPluginName}`)
+    this.uppy.log(`Not installing ${callerPluginName}`)
     throw new Error(`Invalid target option given to ${callerPluginName}`)
   }
 

+ 3 - 3
src/core/Utils.js

@@ -489,10 +489,10 @@ function getSocketHost (url) {
 }
 
 function _emitSocketProgress (uploader, progressData, file) {
-  const {progress, bytesUploaded, bytesTotal} = progressData
+  const { progress, bytesUploaded, bytesTotal } = progressData
   if (progress) {
-    uploader.core.log(`Upload progress: ${progress}`)
-    uploader.core.emitter.emit('core:upload-progress', {
+    uploader.uppy.log(`Upload progress: ${progress}`)
+    uploader.uppy.emit('upload-progress', {
       uploader,
       id: file.id,
       bytesUploaded: bytesUploaded,

+ 8 - 40
src/index.js

@@ -1,19 +1,19 @@
-const Core = require('./core/index.js')
+const Core = require('./core')
 
 // Parent
-const Plugin = require('./plugins/Plugin')
+const Plugin = require('./core/Plugin')
 
 // Orchestrators
-const Dashboard = require('./plugins/Dashboard/index.js')
+const Dashboard = require('./plugins/Dashboard')
 
 // Acquirers
 const Dummy = require('./plugins/Dummy')
-const DragDrop = require('./plugins/DragDrop/index.js')
+const DragDrop = require('./plugins/DragDrop')
 const FileInput = require('./plugins/FileInput.js')
-const GoogleDrive = require('./plugins/GoogleDrive/index.js')
-const Dropbox = require('./plugins/Dropbox/index.js')
-const Instagram = require('./plugins/Instagram/index.js')
-const Webcam = require('./plugins/Webcam/index.js')
+const GoogleDrive = require('./plugins/GoogleDrive')
+const Dropbox = require('./plugins/Dropbox')
+const Instagram = require('./plugins/Instagram')
+const Webcam = require('./plugins/Webcam')
 
 // Progressindicators
 const StatusBar = require('./plugins/StatusBar')
@@ -21,7 +21,6 @@ const ProgressBar = require('./plugins/ProgressBar.js')
 const Informer = require('./plugins/Informer.js')
 
 // Modifiers
-const MetaData = require('./plugins/MetaData.js')
 
 // Uploaders
 const Tus = require('./plugins/Tus')
@@ -51,39 +50,8 @@ module.exports = {
   Transloadit,
   AwsS3,
   Dashboard,
-  MetaData,
   Webcam,
   GoldenRetriever,
   ReduxDevTools,
   ReduxStore
 }
-
-Object.defineProperty(module.exports, 'RestoreFiles', {
-  enumerable: true,
-  configurable: true,
-  get: () => {
-    console.warn('Uppy.RestoreFiles is deprecated and will be removed in v0.22. Use Uppy.GoldenRetriever instead.')
-    Object.defineProperty(module.exports, 'RestoreFiles', {
-      enumerable: true,
-      configurable: true,
-      writable: true,
-      value: GoldenRetriever
-    })
-    return GoldenRetriever
-  }
-})
-
-Object.defineProperty(module.exports, 'Tus10', {
-  enumerable: true,
-  configurable: true,
-  get: () => {
-    console.warn('Uppy.Tus10 is deprecated and will be removed in v0.22. Use Uppy.Tus instead.')
-    Object.defineProperty(module.exports, 'Tus10', {
-      enumerable: true,
-      configurable: true,
-      writable: true,
-      value: Tus
-    })
-    return Tus
-  }
-})

+ 16 - 16
src/plugins/AwsS3/index.js

@@ -1,10 +1,10 @@
-const Plugin = require('../Plugin')
+const Plugin = require('../../core/Plugin')
 const Translator = require('../../core/Translator')
 const XHRUpload = require('../XHRUpload')
 
 module.exports = class AwsS3 extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'uploader'
     this.id = 'AwsS3'
     this.title = 'AWS S3'
@@ -45,7 +45,7 @@ module.exports = class AwsS3 extends Plugin {
 
   prepareUpload (fileIDs) {
     fileIDs.forEach((id) => {
-      this.core.emit('core:preprocess-progress', id, {
+      this.uppy.emit('preprocess-progress', id, {
         mode: 'determinate',
         message: this.i18n('preparingUpload'),
         value: 0
@@ -54,24 +54,24 @@ module.exports = class AwsS3 extends Plugin {
 
     return Promise.all(
       fileIDs.map((id) => {
-        const file = this.core.getFile(id)
+        const file = this.uppy.getFile(id)
         const paramsPromise = Promise.resolve()
           .then(() => this.opts.getUploadParameters(file))
         return paramsPromise.then((params) => {
-          this.core.emit('core:preprocess-progress', file.id, {
+          this.uppy.emit('preprocess-progress', file.id, {
             mode: 'determinate',
             message: this.i18n('preparingUpload'),
             value: 1
           })
           return params
         }).catch((error) => {
-          this.core.emit('core:upload-error', file.id, error)
+          this.uppy.emit('upload-error', file.id, error)
         })
       })
     ).then((responses) => {
       const updatedFiles = {}
       fileIDs.forEach((id, index) => {
-        const file = this.core.getFile(id)
+        const file = this.uppy.getFile(id)
         if (file.error) {
           return
         }
@@ -101,20 +101,20 @@ module.exports = class AwsS3 extends Plugin {
         updatedFiles[id] = updatedFile
       })
 
-      this.core.setState({
-        files: Object.assign({}, this.core.getState().files, updatedFiles)
+      this.uppy.setState({
+        files: Object.assign({}, this.uppy.getState().files, updatedFiles)
       })
 
       fileIDs.forEach((id) => {
-        this.core.emit('core:preprocess-complete', id)
+        this.uppy.emit('preprocess-complete', id)
       })
     })
   }
 
   install () {
-    this.core.addPreProcessor(this.prepareUpload)
+    this.uppy.addPreProcessor(this.prepareUpload)
 
-    this.core.use(XHRUpload, {
+    this.uppy.use(XHRUpload, {
       fieldName: 'file',
       responseUrlFieldName: 'location',
       getResponseData (xhr) {
@@ -146,9 +146,9 @@ module.exports = class AwsS3 extends Plugin {
   }
 
   uninstall () {
-    const uploader = this.core.getPlugin('XHRUpload')
-    this.core.removePlugin(uploader)
+    const uploader = this.uppy.getPlugin('XHRUpload')
+    this.uppy.removePlugin(uploader)
 
-    this.core.removePreProcessor(this.prepareUpload)
+    this.uppy.removePreProcessor(this.prepareUpload)
   }
 }

+ 7 - 2
src/plugins/Dashboard/FileCard.js

@@ -8,7 +8,10 @@ module.exports = function fileCard (props) {
 
   const tempStoreMetaOrSubmit = (ev) => {
     if (ev.keyCode === 13) {
+      ev.stopPropagation()
+      ev.preventDefault()
       props.done(meta, file.id)
+      return
     }
 
     const value = ev.target.value
@@ -24,9 +27,11 @@ module.exports = function fileCard (props) {
         <input class="UppyDashboardFileCard-input"
                type="text"
                data-name="${field.id}"
-               value="${file.meta[field.id]}"
+               value="${file.meta[field.id] || ''}"
                placeholder="${field.placeholder || ''}"
-               onkeyup=${tempStoreMetaOrSubmit} /></fieldset>`
+               onkeyup=${tempStoreMetaOrSubmit}
+               onkeydown=${tempStoreMetaOrSubmit}
+               onkeypress=${tempStoreMetaOrSubmit} /></fieldset>`
     })
   }
 

+ 47 - 52
src/plugins/Dashboard/index.js

@@ -1,4 +1,4 @@
-const Plugin = require('../Plugin')
+const Plugin = require('../../core/Plugin')
 const Translator = require('../../core/Translator')
 const dragDrop = require('drag-drop')
 const Dashboard = require('./Dashboard')
@@ -26,8 +26,8 @@ const FOCUSABLE_ELEMENTS = [
  * Dashboard UI with previews, metadata editing, tabs for various services and more
  */
 module.exports = class DashboardUI extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.id = this.opts.id || 'Dashboard'
     this.title = 'Dashboard'
     this.type = 'orchestrator'
@@ -64,6 +64,7 @@ module.exports = class DashboardUI extends Plugin {
     const defaultOptions = {
       target: 'body',
       getMetaFromForm: true,
+      metaFields: [],
       trigger: '#uppy-select-files',
       inline: false,
       width: 750,
@@ -93,7 +94,6 @@ module.exports = class DashboardUI extends Plugin {
     this.isModalOpen = this.isModalOpen.bind(this)
 
     this.addTarget = this.addTarget.bind(this)
-    this.actions = this.actions.bind(this)
     this.hideAllPanels = this.hideAllPanels.bind(this)
     this.showPanel = this.showPanel.bind(this)
     this.getFocusableNodes = this.getFocusableNodes.bind(this)
@@ -122,7 +122,7 @@ module.exports = class DashboardUI extends Plugin {
         callerPluginType !== 'progressindicator' &&
         callerPluginType !== 'presenter') {
       let msg = 'Dashboard: Modal can only be used by plugins of types: acquirer, progressindicator, presenter'
-      this.core.log(msg)
+      this.uppy.log(msg)
       return
     }
 
@@ -248,7 +248,7 @@ module.exports = class DashboardUI extends Plugin {
     }
 
     if (!this.opts.inline && !showModalTrigger) {
-      this.core.log('Dashboard modal trigger not found, you won’t be able to select files. Make sure `trigger` is set correctly in Dashboard options', 'error')
+      this.uppy.log('Dashboard modal trigger not found, you won’t be able to select files. Make sure `trigger` is set correctly in Dashboard options', 'error')
     }
 
     if (!this.opts.inline) {
@@ -259,6 +259,10 @@ module.exports = class DashboardUI extends Plugin {
     this.removeDragDropListener = dragDrop(this.el, (files) => {
       this.handleDrop(files)
     })
+
+    this.uppy.on('dashboard:file-card', this.handleFileCard)
+
+    window.addEventListener('resize', this.updateDashboardElWidth)
   }
 
   removeEvents () {
@@ -267,28 +271,20 @@ module.exports = class DashboardUI extends Plugin {
       showModalTrigger.forEach(trigger => trigger.removeEventListener('click', this.openModal))
     }
 
-    this.removeDragDropListener()
-
     if (!this.opts.inline) {
       document.removeEventListener('keydown', this.onKeydown)
     }
-  }
-
-  actions () {
-    this.core.on('dashboard:file-card', this.handleFileCard)
 
-    window.addEventListener('resize', this.updateDashboardElWidth)
-  }
+    this.removeDragDropListener()
 
-  removeActions () {
-    this.core.off('dashboard:file-card', this.handleFileCard)
+    this.uppy.off('dashboard:file-card', this.handleFileCard)
 
     window.removeEventListener('resize', this.updateDashboardElWidth)
   }
 
   updateDashboardElWidth () {
     const dashboardEl = this.el.querySelector('.UppyDashboard-inner')
-    this.core.log(`Dashboard width: ${dashboardEl.offsetWidth}`)
+    this.uppy.log(`Dashboard width: ${dashboardEl.offsetWidth}`)
 
     this.setPluginState({
       containerWidth: dashboardEl.offsetWidth
@@ -302,10 +298,10 @@ module.exports = class DashboardUI extends Plugin {
   }
 
   handleDrop (files) {
-    this.core.log('[Dashboard] Files were dropped')
+    this.uppy.log('[Dashboard] Files were dropped')
 
     files.forEach((file) => {
-      this.core.addFile({
+      this.uppy.addFile({
         source: this.id,
         name: file.name,
         type: file.type,
@@ -315,15 +311,15 @@ module.exports = class DashboardUI extends Plugin {
   }
 
   cancelAll () {
-    this.core.emit('core:cancel-all')
+    this.uppy.emit('cancel-all')
   }
 
   pauseAll () {
-    this.core.emit('core:pause-all')
+    this.uppy.emit('pause-all')
   }
 
   resumeAll () {
-    this.core.emit('core:resume-all')
+    this.uppy.emit('resume-all')
   }
 
   render (state) {
@@ -354,7 +350,7 @@ module.exports = class DashboardUI extends Plugin {
     totalUploadedSize = prettyBytes(totalUploadedSize)
 
     const attachRenderFunctionToTarget = (target) => {
-      const plugin = this.core.getPlugin(target.id)
+      const plugin = this.uppy.getPlugin(target.id)
       return Object.assign({}, target, {
         icon: plugin.icon || this.opts.defaultTabIcon,
         render: plugin.render
@@ -362,7 +358,7 @@ module.exports = class DashboardUI extends Plugin {
     }
 
     const isSupported = (target) => {
-      const plugin = this.core.getPlugin(target.id)
+      const plugin = this.uppy.getPlugin(target.id)
       // If the plugin does not provide a `supported` check, assume the plugin works everywhere.
       if (typeof plugin.isSupported !== 'function') {
         return true
@@ -379,24 +375,24 @@ module.exports = class DashboardUI extends Plugin {
       .map(attachRenderFunctionToTarget)
 
     const startUpload = (ev) => {
-      this.core.upload().catch((err) => {
+      this.uppy.upload().catch((err) => {
         // Log error.
-        this.core.log(err.stack || err.message || err)
+        this.uppy.log(err.stack || err.message || err)
       })
     }
 
     const cancelUpload = (fileID) => {
-      this.core.emit('core:upload-cancel', fileID)
-      this.core.emit('core:file-remove', fileID)
+      this.uppy.emit('upload-cancel', fileID)
+      this.uppy.removeFile(fileID)
     }
 
     const showFileCard = (fileID) => {
-      this.core.emit('dashboard:file-card', fileID)
+      this.uppy.emit('dashboard:file-card', fileID)
     }
 
     const fileCardDone = (meta, fileID) => {
-      this.core.emit('core:update-meta', meta, fileID)
-      this.core.emit('dashboard:file-card')
+      this.uppy.setFileMeta(fileID, meta)
+      this.uppy.emit('dashboard:file-card')
     }
 
     return Dashboard({
@@ -408,9 +404,9 @@ module.exports = class DashboardUI extends Plugin {
       totalProgress: state.totalProgress,
       acquirers: acquirers,
       activePanel: pluginState.activePanel,
-      getPlugin: this.core.getPlugin,
+      getPlugin: this.uppy.getPlugin,
       progressindicators: progressindicators,
-      autoProceed: this.core.opts.autoProceed,
+      autoProceed: this.uppy.opts.autoProceed,
       hideUploadButton: this.opts.hideUploadButton,
       id: this.id,
       closeModal: this.requestCloseModal,
@@ -420,19 +416,19 @@ module.exports = class DashboardUI extends Plugin {
       semiTransparent: this.opts.semiTransparent,
       showPanel: this.showPanel,
       hideAllPanels: this.hideAllPanels,
-      log: this.core.log,
+      log: this.uppy.log,
       i18n: this.i18n,
       pauseAll: this.pauseAll,
       resumeAll: this.resumeAll,
-      addFile: this.core.addFile,
-      removeFile: this.core.removeFile,
-      info: this.core.info,
+      addFile: this.uppy.addFile,
+      removeFile: this.uppy.removeFile,
+      info: this.uppy.info,
       note: this.opts.note,
-      metaFields: state.metaFields,
-      resumableUploads: this.core.state.capabilities.resumableUploads || false,
+      metaFields: this.getPluginState().metaFields,
+      resumableUploads: this.uppy.state.capabilities.resumableUploads || false,
       startUpload: startUpload,
-      pauseUpload: this.core.pauseResume,
-      retryUpload: this.core.retryUpload,
+      pauseUpload: this.uppy.pauseResume,
+      retryUpload: this.uppy.retryUpload,
       cancelUpload: cancelUpload,
       fileCardFor: pluginState.fileCardFor,
       showFileCard: showFileCard,
@@ -446,7 +442,7 @@ module.exports = class DashboardUI extends Plugin {
   }
 
   discoverProviderPlugins () {
-    this.core.iteratePlugins((plugin) => {
+    this.uppy.iteratePlugins((plugin) => {
       if (plugin && !plugin.target && plugin.opts && plugin.opts.target === this.constructor) {
         this.addTarget(plugin)
       }
@@ -459,6 +455,7 @@ module.exports = class DashboardUI extends Plugin {
       isHidden: true,
       showFileCard: false,
       activePanel: false,
+      metaFields: this.opts.metaFields,
       targets: []
     })
 
@@ -469,19 +466,19 @@ module.exports = class DashboardUI extends Plugin {
 
     const plugins = this.opts.plugins || []
     plugins.forEach((pluginID) => {
-      const plugin = this.core.getPlugin(pluginID)
+      const plugin = this.uppy.getPlugin(pluginID)
       if (plugin) plugin.mount(this, plugin)
     })
 
     if (!this.opts.disableStatusBar) {
-      this.core.use(StatusBar, {
+      this.uppy.use(StatusBar, {
         target: this,
         hideUploadButton: this.opts.hideUploadButton
       })
     }
 
     if (!this.opts.disableInformer) {
-      this.core.use(Informer, {
+      this.uppy.use(Informer, {
         target: this
       })
     }
@@ -489,30 +486,28 @@ module.exports = class DashboardUI extends Plugin {
     this.discoverProviderPlugins()
 
     this.initEvents()
-    this.actions()
   }
 
   uninstall () {
     if (!this.opts.disableInformer) {
-      const informer = this.core.getPlugin('Informer')
-      if (informer) this.core.removePlugin(informer)
+      const informer = this.uppy.getPlugin('Informer')
+      if (informer) this.uppy.removePlugin(informer)
     }
 
     if (!this.opts.disableStatusBar) {
-      const statusBar = this.core.getPlugin('StatusBar')
+      const statusBar = this.uppy.getPlugin('StatusBar')
       // Checking if this plugin exists, in case it was removed by uppy-core
       // before the Dashboard was.
-      if (statusBar) this.core.removePlugin(statusBar)
+      if (statusBar) this.uppy.removePlugin(statusBar)
     }
 
     const plugins = this.opts.plugins || []
     plugins.forEach((pluginID) => {
-      const plugin = this.core.getPlugin(pluginID)
+      const plugin = this.uppy.getPlugin(pluginID)
       if (plugin) plugin.unmount()
     })
 
     this.unmount()
-    this.removeActions()
     this.removeEvents()
   }
 }

+ 8 - 8
src/plugins/DragDrop/index.js

@@ -1,4 +1,4 @@
-const Plugin = require('./../Plugin')
+const Plugin = require('../../core/Plugin')
 const Translator = require('../../core/Translator')
 const { toArray } = require('../../core/Utils')
 const dragDrop = require('drag-drop')
@@ -9,8 +9,8 @@ const html = require('yo-yo')
  *
  */
 module.exports = class DragDrop extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'acquirer'
     this.id = this.opts.id || 'DragDrop'
     this.title = 'Drag & Drop'
@@ -83,10 +83,10 @@ module.exports = class DragDrop extends Plugin {
   }
 
   handleDrop (files) {
-    this.core.log('[DragDrop] Files dropped')
+    this.uppy.log('[DragDrop] Files dropped')
 
     files.forEach((file) => {
-      this.core.addFile({
+      this.uppy.addFile({
         source: this.id,
         name: file.name,
         type: file.type,
@@ -96,12 +96,12 @@ module.exports = class DragDrop extends Plugin {
   }
 
   onInputChange (ev) {
-    this.core.log('[DragDrop] Files selected through input')
+    this.uppy.log('[DragDrop] Files selected through input')
 
     const files = toArray(ev.target.files)
 
     files.forEach((file) => {
-      this.core.addFile({
+      this.uppy.addFile({
         source: this.id,
         name: file.name,
         type: file.type,
@@ -146,7 +146,7 @@ module.exports = class DragDrop extends Plugin {
     }
     this.removeDragDropListener = dragDrop(this.el, (files) => {
       this.handleDrop(files)
-      this.core.log(files)
+      this.uppy.log(files)
     })
   }
 }

+ 6 - 8
src/plugins/Dropbox/index.js

@@ -1,14 +1,12 @@
 const html = require('yo-yo')
-const Plugin = require('../Plugin')
-
-const Provider = require('../../Provider')
-
-const View = require('../../generic-provider-views')
+const Plugin = require('../../core/Plugin')
+const Provider = require('../Provider')
+const View = require('../Provider/view')
 const icons = require('./icons')
 
 module.exports = class Dropbox extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'acquirer'
     this.id = this.opts.id || 'Dropbox'
     this.title = 'Dropbox'
@@ -22,7 +20,7 @@ module.exports = class Dropbox extends Plugin {
 
     // writing out the key explicitly for readability the key used to store
     // the provider instance must be equal to this.id.
-    this[this.id] = new Provider(core, {
+    this[this.id] = new Provider(uppy, {
       host: this.opts.host,
       provider: 'dropbox'
     })

+ 5 - 5
src/plugins/Dummy.js

@@ -1,4 +1,4 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 const html = require('yo-yo')
 // const yo = require('yo-yo')
 
@@ -7,8 +7,8 @@ const html = require('yo-yo')
  * A test plugin, does nothing useful
  */
 module.exports = class Dummy extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'acquirer'
     this.id = this.opts.id || 'Dummy'
     this.title = 'Mr. Plugin'
@@ -54,7 +54,7 @@ module.exports = class Dummy extends Plugin {
   }
 
   install () {
-    this.core.setState({dummy: {text: '123'}})
+    this.uppy.setState({dummy: {text: '123'}})
 
     const target = this.opts.target
     if (target) {
@@ -62,7 +62,7 @@ module.exports = class Dummy extends Plugin {
     }
 
     setTimeout(() => {
-      this.core.setState({dummy: {text: '!!!'}})
+      this.uppy.setState({dummy: {text: '!!!'}})
     }, 2000)
   }
 }

+ 5 - 5
src/plugins/FileInput.js

@@ -1,11 +1,11 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 const { toArray } = require('../core/Utils')
 const Translator = require('../core/Translator')
 const html = require('yo-yo')
 
 module.exports = class FileInput extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.id = this.opts.id || 'FileInput'
     this.title = 'File Input'
     this.type = 'acquirer'
@@ -41,12 +41,12 @@ module.exports = class FileInput extends Plugin {
   }
 
   handleInputChange (ev) {
-    this.core.log('All right, something selected through input...')
+    this.uppy.log('All right, something selected through input...')
 
     const files = toArray(ev.target.files)
 
     files.forEach((file) => {
-      this.core.addFile({
+      this.uppy.addFile({
         source: this.id,
         name: file.name,
         type: file.type,

+ 41 - 41
src/plugins/GoldenRetriever/index.js

@@ -1,4 +1,4 @@
-const Plugin = require('../Plugin')
+const Plugin = require('../../core/Plugin')
 const ServiceWorkerStore = require('./ServiceWorkerStore')
 const IndexedDBStore = require('./IndexedDBStore')
 const MetaDataStore = require('./MetaDataStore')
@@ -11,8 +11,8 @@ const MetaDataStore = require('./MetaDataStore')
 * https://uppy.io/blog/2017/07/golden-retriever/
 */
 module.exports = class GoldenRetriever extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'debugger'
     this.id = 'GoldenRetriever'
     this.title = 'Golden Retriever'
@@ -26,16 +26,16 @@ module.exports = class GoldenRetriever extends Plugin {
 
     this.MetaDataStore = new MetaDataStore({
       expires: this.opts.expires,
-      storeName: core.getID()
+      storeName: uppy.getID()
     })
     this.ServiceWorkerStore = null
     if (this.opts.serviceWorker) {
-      this.ServiceWorkerStore = new ServiceWorkerStore({ storeName: core.getID() })
+      this.ServiceWorkerStore = new ServiceWorkerStore({ storeName: uppy.getID() })
     }
     this.IndexedDBStore = new IndexedDBStore(Object.assign(
       { expires: this.opts.expires },
       opts.indexedDB || {},
-      { storeName: core.getID() }))
+      { storeName: uppy.getID() }))
 
     this.saveFilesStateToLocalStorage = this.saveFilesStateToLocalStorage.bind(this)
     this.loadFilesStateFromLocalStorage = this.loadFilesStateFromLocalStorage.bind(this)
@@ -48,8 +48,8 @@ module.exports = class GoldenRetriever extends Plugin {
     const savedState = this.MetaDataStore.load()
 
     if (savedState) {
-      this.core.log('Recovered some state from Local Storage')
-      this.core.setState(savedState)
+      this.uppy.log('Recovered some state from Local Storage')
+      this.uppy.setState(savedState)
     }
   }
 
@@ -60,9 +60,9 @@ module.exports = class GoldenRetriever extends Plugin {
   getWaitingFiles () {
     const waitingFiles = {}
 
-    const allFiles = this.core.state.files
+    const allFiles = this.uppy.state.files
     Object.keys(allFiles).forEach((fileID) => {
-      const file = this.core.getFile(fileID)
+      const file = this.uppy.getFile(fileID)
       if (!file.progress || !file.progress.uploadStarted) {
         waitingFiles[fileID] = file
       }
@@ -79,13 +79,13 @@ module.exports = class GoldenRetriever extends Plugin {
   getUploadingFiles () {
     const uploadingFiles = {}
 
-    const { currentUploads } = this.core.state
+    const { currentUploads } = this.uppy.state
     if (currentUploads) {
       const uploadIDs = Object.keys(currentUploads)
       uploadIDs.forEach((uploadID) => {
         const filesInUpload = currentUploads[uploadID].fileIDs
         filesInUpload.forEach((fileID) => {
-          uploadingFiles[fileID] = this.core.getFile(fileID)
+          uploadingFiles[fileID] = this.uppy.getFile(fileID)
         })
       })
     }
@@ -100,7 +100,7 @@ module.exports = class GoldenRetriever extends Plugin {
     )
 
     this.MetaDataStore.save({
-      currentUploads: this.core.state.currentUploads,
+      currentUploads: this.uppy.state.currentUploads,
       files: filesToSave
     })
   }
@@ -108,13 +108,13 @@ module.exports = class GoldenRetriever extends Plugin {
   loadFileBlobsFromServiceWorker () {
     this.ServiceWorkerStore.list().then((blobs) => {
       const numberOfFilesRecovered = Object.keys(blobs).length
-      const numberOfFilesTryingToRecover = Object.keys(this.core.state.files).length
+      const numberOfFilesTryingToRecover = Object.keys(this.uppy.state.files).length
       if (numberOfFilesRecovered === numberOfFilesTryingToRecover) {
-        this.core.log(`Successfully recovered ${numberOfFilesRecovered} blobs from Service Worker!`)
-        this.core.info(`Successfully recovered ${numberOfFilesRecovered} files`, 'success', 3000)
+        this.uppy.log(`Successfully recovered ${numberOfFilesRecovered} blobs from Service Worker!`)
+        this.uppy.info(`Successfully recovered ${numberOfFilesRecovered} files`, 'success', 3000)
         this.onBlobsLoaded(blobs)
       } else {
-        this.core.log('Failed to recover blobs from Service Worker, trying IndexedDB now...')
+        this.uppy.log('Failed to recover blobs from Service Worker, trying IndexedDB now...')
         this.loadFileBlobsFromIndexedDB()
       }
     })
@@ -125,19 +125,19 @@ module.exports = class GoldenRetriever extends Plugin {
       const numberOfFilesRecovered = Object.keys(blobs).length
 
       if (numberOfFilesRecovered > 0) {
-        this.core.log(`Successfully recovered ${numberOfFilesRecovered} blobs from Indexed DB!`)
-        this.core.info(`Successfully recovered ${numberOfFilesRecovered} files`, 'success', 3000)
+        this.uppy.log(`Successfully recovered ${numberOfFilesRecovered} blobs from Indexed DB!`)
+        this.uppy.info(`Successfully recovered ${numberOfFilesRecovered} files`, 'success', 3000)
         return this.onBlobsLoaded(blobs)
       }
-      this.core.log('Couldn’t recover anything from IndexedDB :(')
+      this.uppy.log('Couldn’t recover anything from IndexedDB :(')
     })
   }
 
   onBlobsLoaded (blobs) {
     const obsoleteBlobs = []
-    const updatedFiles = Object.assign({}, this.core.state.files)
+    const updatedFiles = Object.assign({}, this.uppy.state.files)
     Object.keys(blobs).forEach((fileID) => {
-      const originalFile = this.core.getFile(fileID)
+      const originalFile = this.uppy.getFile(fileID)
       if (!originalFile) {
         obsoleteBlobs.push(fileID)
         return
@@ -152,16 +152,16 @@ module.exports = class GoldenRetriever extends Plugin {
       const updatedFile = Object.assign({}, originalFile, updatedFileData)
       updatedFiles[fileID] = updatedFile
 
-      this.core.generatePreview(updatedFile)
+      this.uppy.generatePreview(updatedFile)
     })
-    this.core.setState({
+    this.uppy.setState({
       files: updatedFiles
     })
-    this.core.emit('core:restored')
+    this.uppy.emit('restored')
 
     if (obsoleteBlobs.length) {
       this.deleteBlobs(obsoleteBlobs).then(() => {
-        this.core.log(`[GoldenRetriever] cleaned up ${obsoleteBlobs.length} old files`)
+        this.uppy.log(`[GoldenRetriever] cleaned up ${obsoleteBlobs.length} old files`)
       })
     }
   }
@@ -182,52 +182,52 @@ module.exports = class GoldenRetriever extends Plugin {
   install () {
     this.loadFilesStateFromLocalStorage()
 
-    if (Object.keys(this.core.state.files).length > 0) {
+    if (Object.keys(this.uppy.state.files).length > 0) {
       if (this.ServiceWorkerStore) {
-        this.core.log('Attempting to load files from Service Worker...')
+        this.uppy.log('Attempting to load files from Service Worker...')
         this.loadFileBlobsFromServiceWorker()
       } else {
-        this.core.log('Attempting to load files from Indexed DB...')
+        this.uppy.log('Attempting to load files from Indexed DB...')
         this.loadFileBlobsFromIndexedDB()
       }
     }
 
-    this.core.on('core:file-added', (file) => {
+    this.uppy.on('file-added', (file) => {
       if (file.isRemote) return
 
       if (this.ServiceWorkerStore) {
         this.ServiceWorkerStore.put(file).catch((err) => {
-          this.core.log('Could not store file', 'error')
-          this.core.log(err)
+          this.uppy.log('Could not store file', 'error')
+          this.uppy.log(err)
         })
       }
 
       this.IndexedDBStore.put(file).catch((err) => {
-        this.core.log('Could not store file', 'error')
-        this.core.log(err)
+        this.uppy.log('Could not store file', 'error')
+        this.uppy.log(err)
       })
     })
 
-    this.core.on('core:file-removed', (fileID) => {
+    this.uppy.on('file-removed', (fileID) => {
       if (this.ServiceWorkerStore) this.ServiceWorkerStore.delete(fileID)
       this.IndexedDBStore.delete(fileID)
     })
 
-    this.core.on('core:complete', ({ successful }) => {
+    this.uppy.on('complete', ({ successful }) => {
       const fileIDs = successful.map((file) => file.id)
       this.deleteBlobs(fileIDs).then(() => {
-        this.core.log(`[GoldenRetriever] removed ${successful.length} files that finished uploading`)
+        this.uppy.log(`[GoldenRetriever] removed ${successful.length} files that finished uploading`)
       })
     })
 
-    this.core.on('core:state-update', this.saveFilesStateToLocalStorage)
+    this.uppy.on('state-update', this.saveFilesStateToLocalStorage)
 
-    this.core.on('core:restored', () => {
+    this.uppy.on('restored', () => {
       // start all uploads again when file blobs are restored
-      const { currentUploads } = this.core.getState()
+      const { currentUploads } = this.uppy.getState()
       if (currentUploads) {
         Object.keys(currentUploads).forEach((uploadId) => {
-          this.core.restore(uploadId, currentUploads[uploadId])
+          this.uppy.restore(uploadId, currentUploads[uploadId])
         })
       }
     })

+ 6 - 8
src/plugins/GoogleDrive/index.js

@@ -1,13 +1,11 @@
 const html = require('yo-yo')
-const Plugin = require('../Plugin')
-
-const Provider = require('../../Provider')
-
-const View = require('../../generic-provider-views')
+const Plugin = require('../../core/Plugin')
+const Provider = require('../Provider')
+const View = require('../Provider/view')
 
 module.exports = class GoogleDrive extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'acquirer'
     this.id = this.opts.id || 'GoogleDrive'
     this.title = 'Google Drive'
@@ -19,7 +17,7 @@ module.exports = class GoogleDrive extends Plugin {
 
     // writing out the key explicitly for readability the key used to store
     // the provider instance must be equal to this.id.
-    this[this.id] = new Provider(core, {
+    this[this.id] = new Provider(uppy, {
       host: this.opts.host,
       provider: 'drive',
       authProvider: 'google'

+ 3 - 3
src/plugins/Informer.js

@@ -1,4 +1,4 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 const html = require('yo-yo')
 
 /**
@@ -9,8 +9,8 @@ const html = require('yo-yo')
  *
  */
 module.exports = class Informer extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'progressindicator'
     this.id = this.opts.id || 'Informer'
     this.title = 'Informer'

+ 7 - 9
src/plugins/Instagram/index.js

@@ -1,13 +1,11 @@
 const html = require('yo-yo')
-const Plugin = require('../Plugin')
-
-const Provider = require('../../Provider')
-
-const View = require('../../generic-provider-views')
+const Plugin = require('../../core/Plugin')
+const Provider = require('../Provider')
+const View = require('../Provider/view')
 
 module.exports = class Instagram extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'acquirer'
     this.id = this.opts.id || 'Instagram'
     this.title = 'Instagram'
@@ -21,7 +19,7 @@ module.exports = class Instagram extends Plugin {
 
     // writing out the key explicitly for readability the key used to store
     // the provider instance must be equal to this.id.
-    this[this.id] = new Provider(core, {
+    this[this.id] = new Provider(uppy, {
       host: this.opts.host,
       provider: 'instagram',
       authProvider: 'instagram'
@@ -128,7 +126,7 @@ module.exports = class Instagram extends Plugin {
   }
 
   getNextPagePath () {
-    const { files } = this.core.getState()[this.stateId]
+    const { files } = this.uppy.getState()[this.stateId]
     return `recent?max_id=${this.getItemId(files[files.length - 1])}`
   }
 

+ 5 - 6
src/plugins/MagicLog.js

@@ -1,4 +1,4 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 // import deepDiff from 'deep-diff'
 
 /**
@@ -8,8 +8,8 @@ const Plugin = require('./Plugin')
  *
  */
 module.exports = class MagicLog extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'debugger'
     this.id = 'MagicLog'
     this.title = 'Magic Log'
@@ -32,11 +32,10 @@ module.exports = class MagicLog extends Plugin {
   }
 
   install () {
-    const uppy = this.core.emitter
-    uppy.on('state-update', this.handleStateUpdate)
+    this.uppy.on('state-update', this.handleStateUpdate)
   }
 
   uninstall () {
-    this.core.emitter.off('state-update', this.handleStateUpdate)
+    this.uppy.off('state-update', this.handleStateUpdate)
   }
 }

+ 0 - 51
src/plugins/MetaData.js

@@ -1,51 +0,0 @@
-const Plugin = require('./Plugin')
-
-/**
- * Meta Data
- * Adds metadata fields to Uppy
- *
- */
-module.exports = class MetaData extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
-    this.type = 'modifier'
-    this.id = 'MetaData'
-    this.title = 'Meta Data'
-
-    // set default options
-    const defaultOptions = {}
-
-    // merge default options with the ones set by user
-    this.opts = Object.assign({}, defaultOptions, opts)
-
-    this.handleFileAdded = this.handleFileAdded.bind(this)
-  }
-
-  handleFileAdded (file) {
-    const metaFields = this.opts.fields
-
-    metaFields.forEach((item) => {
-      const obj = {}
-      obj[item.id] = item.value
-      this.core.updateMeta(obj, file.id)
-    })
-  }
-
-  addInitialMeta () {
-    const metaFields = this.opts.fields
-
-    this.core.setState({
-      metaFields: metaFields
-    })
-
-    this.core.on('core:file-added', this.handleFileAdded)
-  }
-
-  install () {
-    this.addInitialMeta()
-  }
-
-  uninstall () {
-    this.core.off('core:file-added', this.handleFileAdded)
-  }
-}

+ 0 - 372
src/plugins/Plugin.test.js

@@ -1,372 +0,0 @@
-const getFormData = require('get-form-data')
-const nanoraf = require('nanoraf')
-const yo = require('yo-yo')
-
-const { findDOMElement } = require('../core/Utils')
-const Plugin = require('./Plugin')
-
-jest.mock('get-form-data')
-jest.mock('nanoraf')
-jest.mock('../core/Utils', () => ({
-  findDOMElement: jest.fn()
-}))
-
-getFormData.mockImplementation(() => ({ foo: 'bar' }))
-nanoraf.mockImplementation(cb => {
-  cb({ some: 'state' }) // eslint-disable-line standard/no-callback-literal
-  return () => {}
-})
-
-describe('Plugin', () => {
-  let plugin
-
-  afterEach(() => {
-    getFormData.mockClear()
-  })
-
-  it('is a class', () => {
-    expect(typeof Plugin).toBe('function')
-  })
-
-  it('accepts two parameters', () => {
-    expect(Plugin.length).toBe(2)
-  })
-
-  it('defaults options when not passed as an argument', () => {
-    plugin = new Plugin()
-    expect(typeof plugin.opts).toBe('object')
-  })
-
-  describe('plugin state', () => {
-    class MockPlugin extends Plugin {
-      constructor (core, opts) {
-        super(core, opts)
-        this.id = 'MockPlugin'
-      }
-    }
-    it('returns plugin state from `getPluginState()`', () => {
-      const mockState = {}
-      plugin = new MockPlugin({
-        state: {
-          plugins: {
-            MockPlugin: mockState
-          }
-        }
-      })
-
-      expect(plugin.getPluginState()).toBe(mockState)
-    })
-
-    it('merges plugin state using `setPluginState()`', () => {
-      const initialState = {
-        plugins: {
-          MockPlugin: {
-            hello: 'world',
-            asdf: 'quux'
-          }
-        }
-      }
-
-      plugin = new MockPlugin({
-        setState (patch) {
-          this.state = Object.assign({}, this.state, patch)
-        },
-        state: initialState
-      })
-
-      plugin.setPluginState({ hello: 'friends' })
-
-      expect(plugin.core.state).not.toBe(initialState)
-      expect(plugin.getPluginState()).toEqual({
-        hello: 'friends',
-        asdf: 'quux'
-      })
-    })
-  })
-
-  // it('sets `replaceTargetContent` based on options argument', () => {
-  //   plugin = new Plugin(null, { replaceTargetContent: false })
-  //   expect(plugin.opts.replaceTargetContent).toBe(false)
-  // })
-
-  // it('defaults `replaceTargetContent` to true when not passed as an option', () => {
-  //   plugin = new Plugin()
-  //   expect(plugin.opts.replaceTargetContent).toBe(true)
-  // })
-
-  describe('.update', () => {
-    beforeEach(() => {
-      plugin = new Plugin()
-      plugin.render = jest.fn(() => ({ ren: 'der' }))
-    })
-
-    it('is a function', () => {
-      expect(typeof Plugin.prototype.update).toBe('function')
-    })
-
-    it('accepts one parameter', () => {
-      expect(Plugin.prototype.update.length).toBe(1)
-    })
-
-    it('does nothing when plugin has no UI element (`el`)', () => {
-      plugin.updateUI = jest.fn()
-      expect(plugin.update()).toBe(undefined)
-      expect(plugin.updateUI.mock.calls.length).toBe(0)
-    })
-
-    it('calls updateUI method with state when UI element (`el`) exists', () => {
-      plugin.el = {}
-      plugin.updateUI = jest.fn()
-      plugin.update({ foo: 'bar' })
-      expect(plugin.updateUI.mock.calls.length).toBe(1)
-      expect(plugin.updateUI.mock.calls[0][0]).toEqual({ foo: 'bar' })
-    })
-
-    it('does nothing when a UI element exists but and no updateUI method', () => {
-      plugin.el = {}
-      expect(() => plugin.update()).not.toThrow()
-    })
-  })
-
-  describe('.mount', () => {
-    const addTarget = jest.fn(() => 'body')
-    const mockCore = {
-      iteratePlugins: (cb) => {
-        cb(new mockTarget()) // eslint-disable-line new-cap
-      },
-      log: jest.fn(),
-      setMeta: jest.fn(),
-      state: 'default'
-    }
-    const mockPlugin = {
-      id: 'pID'
-    }
-    const mockTarget = function () {
-      this.id = 'tID'
-      this.addTarget = addTarget
-    }
-
-    let yoUpdateSpy
-
-    beforeEach(() => {
-      yoUpdateSpy = jest.spyOn(yo, 'update').mockImplementation(() => ({ yo: 'el' }))
-      plugin = new Plugin(mockCore, { getMetaFromForm: true })
-      plugin.render = jest.fn(() => ({ ren: 'der' }))
-    })
-
-    afterEach(() => {
-      findDOMElement.mockReset()
-      findDOMElement.mockRestore()
-      mockCore.log.mockReset()
-      mockCore.setMeta.mockReset()
-      yoUpdateSpy.mockReset()
-      yoUpdateSpy.mockRestore()
-    })
-
-    it('is a function', () => {
-      expect(typeof Plugin.prototype.mount).toBe('function')
-    })
-
-    it('accepts two parameters', () => {
-      expect(Plugin.prototype.mount.length).toBe(2)
-    })
-
-    xit('sets `el` property when state has changed', () => {
-      expect.assertions(4)
-
-      expect(plugin.el).toBe(undefined)
-
-      plugin.mount(mockTarget, mockPlugin)
-
-      expect(plugin.render.mock.calls[0][0]).toEqual({ some: 'state' })
-      expect(yo.update.mock.calls[0]).toEqual([undefined, { ren: 'der' }])
-      expect(plugin.el).toEqual({ yo: 'el' })
-    })
-
-    describe('when target is a DOM element', () => {
-      let mockElement
-      const appendChild = jest.fn()
-
-      beforeEach(() => {
-        mockElement = {
-          nodeName: 'FORM',
-          innerHTML: 'foo',
-          appendChild
-        }
-        mockPlugin.render = jest.fn(() => ({ el: 'lo' }))
-        findDOMElement.mockImplementation(() => mockElement)
-      })
-
-      afterEach(() => {
-        findDOMElement.mockReset()
-        findDOMElement.mockRestore()
-      })
-
-      it('logs installation', () => {
-        plugin.mount(mockTarget, mockPlugin)
-        expect(mockCore.log.mock.calls.length).toBe(1)
-        expect(/DOM element/.test(mockCore.log.mock.calls[0][0])).toBe(true)
-      })
-
-      it('sets form data to core\'s meta data when target is a form', () => {
-        plugin.mount(mockTarget, mockPlugin)
-        expect(getFormData.mock.calls[0][0]).toEqual(mockElement)
-        expect(mockCore.setMeta.mock.calls[0][0]).toEqual({ foo: 'bar' })
-      })
-
-      it('does not set data to core\'s meta data when `getMetaFromForm` isn\'t a Plugin option', () => {
-        plugin = new Plugin(mockCore)
-        plugin.render = () => {}
-        plugin.mount(mockTarget, mockPlugin)
-        expect(mockCore.setMeta.mock.calls.length).toBe(0)
-      })
-
-      it('does not set data to core\'s meta data when target is not a form', () => {
-        mockElement.nodeName = 'FOO'
-
-        plugin.mount(mockTarget, mockPlugin)
-        expect(mockCore.setMeta.mock.calls.length).toBe(0)
-      })
-
-      it('does not remove content from target when `replaceTargetContent` is not set', () => {
-        plugin = new Plugin(mockCore)
-        plugin.render = () => {}
-        plugin.mount(mockTarget, mockPlugin)
-        expect(mockElement.innerHTML).toBe('foo')
-      })
-
-      it('removes content from target when `replaceTargetContent` is set', () => {
-        plugin = new Plugin(mockCore, {replaceTargetContent: true})
-        plugin.render = () => {}
-        plugin.mount(mockTarget, mockPlugin)
-        expect(mockElement.innerHTML).toBe('')
-      })
-
-      it('sets `el` to plugin rendered with state', () => {
-        plugin.mount(mockTarget, mockPlugin)
-        expect(mockPlugin.render.mock.calls[0][0]).toBe('default')
-        expect(plugin.el).toEqual({ el: 'lo' })
-      })
-
-      it('appends plugin\'s element to target', () => {
-        plugin.mount(mockTarget, mockPlugin)
-        expect(mockElement.appendChild.mock.calls[0][0]).toEqual({ el: 'lo' })
-      })
-
-      it('adds updateUI method', () => {
-        plugin.mount(mockTarget, mockPlugin)
-        expect(typeof plugin.updateUI).toBe('function')
-      })
-
-      it('returns the target DOM element', () => {
-        plugin = new Plugin(mockCore)
-        plugin.render = () => {}
-        const target = plugin.mount(mockTarget, mockPlugin)
-        expect(target).toEqual({ el: 'lo' })
-      })
-    })
-
-    describe('when target is a plugin', () => {
-      it('logs installation', () => {
-        plugin.mount(mockTarget, mockPlugin)
-        expect(mockCore.log.mock.calls.length).toBe(1)
-        expect(/tID/.test(mockCore.log.mock.calls[0][0])).toBe(true)
-      })
-
-      it('adds plugin to target', () => {
-        plugin.mount(mockTarget, mockPlugin)
-        expect(addTarget.mock.calls[0][0]).toEqual(mockPlugin)
-      })
-
-      it('returns plugin\'s target', () => {
-        const target = plugin.mount(mockTarget, mockPlugin)
-        expect(target).toBe('body')
-      })
-    })
-  })
-
-  describe('.render', () => {
-    beforeEach(() => {
-      plugin = new Plugin()
-    })
-
-    it('is a function', () => {
-      expect(typeof Plugin.prototype.render).toBe('function')
-    })
-
-    it('accepts one parameter', () => {
-      expect(Plugin.prototype.render.length).toBe(1)
-    })
-
-    it('throws by default', () => {
-      expect(() => plugin.render()).toThrow()
-    })
-  })
-
-  describe('.addTarget', () => {
-    beforeEach(() => {
-      plugin = new Plugin()
-    })
-
-    it('is a function', () => {
-      expect(typeof Plugin.prototype.addTarget).toBe('function')
-    })
-
-    it('accepts one parameter', () => {
-      expect(Plugin.prototype.addTarget.length).toBe(1)
-    })
-
-    it('throws by default', () => {
-      expect(() => plugin.addTarget()).toThrow()
-    })
-  })
-
-  describe('.unmount', () => {
-    beforeEach(() => {
-      plugin = new Plugin()
-    })
-
-    it('is a function', () => {
-      expect(typeof Plugin.prototype.unmount).toBe('function')
-    })
-
-    it('removes plugin\'s UI element', () => {
-      const removeChild = jest.fn()
-      const el = {
-        parentNode: {
-          removeChild
-        }
-      }
-      plugin.el = el
-      plugin.unmount()
-      expect(removeChild.mock.calls.length).toBe(1)
-      expect(removeChild.mock.calls[0][0]).toEqual(el)
-    })
-
-    it('does nothing when no UI element or parent', () => {
-      plugin.el = {}
-      expect(() => plugin.unmount()).not.toThrow()
-    })
-  })
-
-  describe('.install', () => {
-    it('is a function', () => {
-      expect(typeof Plugin.prototype.install).toBe('function')
-    })
-  })
-
-  describe('.uninstall', () => {
-    it('is a function', () => {
-      expect(typeof Plugin.prototype.uninstall).toBe('function')
-    })
-
-    it('calls unmount method', () => {
-      const spy = jest.spyOn(Plugin.prototype, 'unmount')
-      const plugin = new Plugin()
-      plugin.uninstall()
-      expect(spy.mock.calls.length).toBe(1)
-      spy.mockReset()
-      spy.mockRestore()
-    })
-  })
-})

+ 3 - 3
src/plugins/ProgressBar.js

@@ -1,4 +1,4 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 const html = require('yo-yo')
 
 /**
@@ -6,8 +6,8 @@ const html = require('yo-yo')
  *
  */
 module.exports = class ProgressBar extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.id = this.opts.id || 'ProgressBar'
     this.title = 'Progress Bar'
     this.type = 'progressindicator'

+ 5 - 5
src/Provider.js → src/plugins/Provider/index.js

@@ -7,8 +7,8 @@ const _getName = (id) => {
 }
 
 module.exports = class Provider {
-  constructor (core, opts) {
-    this.core = core
+  constructor (uppy, opts) {
+    this.uppy = uppy
     this.opts = opts
     this.provider = opts.provider
     this.id = this.provider
@@ -19,18 +19,18 @@ module.exports = class Provider {
   }
 
   get hostname () {
-    const uppyServer = this.core.state.uppyServer || {}
+    const uppyServer = this.uppy.state.uppyServer || {}
     const host = this.opts.host
     return uppyServer[host] || host
   }
 
   onReceiveResponse (response) {
-    const uppyServer = this.core.state.uppyServer || {}
+    const uppyServer = this.uppy.state.uppyServer || {}
     const host = this.opts.host
     const headers = response.headers
     // Store the self-identified domain name for the uppy-server we just hit.
     if (headers.has('i-am') && headers.get('i-am') !== uppyServer[host]) {
-      this.core.setState({
+      this.uppy.setState({
         uppyServer: Object.assign({}, uppyServer, {
           [host]: headers.get('i-am')
         })

+ 0 - 0
src/generic-provider-views/AuthView.js → src/plugins/Provider/view/AuthView.js


+ 0 - 0
src/generic-provider-views/Breadcrumb.js → src/plugins/Provider/view/Breadcrumb.js


+ 0 - 0
src/generic-provider-views/Breadcrumbs.js → src/plugins/Provider/view/Breadcrumbs.js


+ 0 - 0
src/generic-provider-views/Browser.js → src/plugins/Provider/view/Browser.js


+ 0 - 0
src/generic-provider-views/Loader.js → src/plugins/Provider/view/Loader.js


+ 0 - 0
src/generic-provider-views/Table.js → src/plugins/Provider/view/Table.js


+ 0 - 0
src/generic-provider-views/TableRow.js → src/plugins/Provider/view/TableRow.js


+ 18 - 21
src/generic-provider-views/index.js → src/plugins/Provider/view/index.js

@@ -1,16 +1,13 @@
 const AuthView = require('./AuthView')
 const Browser = require('./Browser')
 const LoaderView = require('./Loader')
-const Utils = require('../core/Utils')
+const Utils = require('../../../core/Utils')
 
 /**
  * Class to easily generate generic views for plugins
  *
- * This class expects the plugin using to have the following attributes
  *
- * stateId {String} object key of which the plugin state is stored
- *
- * This class also expects the plugin instance using it to have the following
+ * This class expects the plugin instance using it to have the following
  * accessor methods.
  * Each method takes the item whose property is to be accessed
  * as a param
@@ -73,14 +70,14 @@ module.exports = class View {
     this.handleScroll = this.handleScroll.bind(this)
     this.donePicking = this.donePicking.bind(this)
 
-    this.plugin.core.on('core:file-removed', this.updateFolderState)
+    this.plugin.uppy.on('file-removed', this.updateFolderState)
 
     // Visual
     this.render = this.render.bind(this)
   }
 
   tearDown () {
-    this.plugin.core.off('core:file-removed', this.updateFolderState)
+    this.plugin.uppy.off('file-removed', this.updateFolderState)
   }
 
   _updateFilesAndFolders (res, files, folders) {
@@ -170,8 +167,8 @@ module.exports = class View {
       if (fileType && Utils.isPreviewSupported(fileType)) {
         tagFile.preview = this.plugin.getItemThumbnailUrl(file)
       }
-      this.plugin.core.log('Adding remote file')
-      this.plugin.core.addFile(tagFile)
+      this.plugin.uppy.log('Adding remote file')
+      this.plugin.uppy.addFile(tagFile)
       if (!isCheckbox) {
         this.donePicking()
       }
@@ -322,7 +319,7 @@ module.exports = class View {
       }
       return false
     }
-    return (itemId in this.plugin.core.getState().files)
+    return (itemId in this.plugin.uppy.getState().files)
   }
 
   /**
@@ -351,7 +348,7 @@ module.exports = class View {
       state = this.plugin.getPluginState()
       state.selectedFolders[folderId] = {loading: false, files: files}
       this.plugin.setPluginState({selectedFolders: folders})
-      const dashboard = this.plugin.core.getPlugin('Dashboard')
+      const dashboard = this.plugin.uppy.getPlugin('Dashboard')
       let message
       if (files.length) {
         message = dashboard.i18n('folderAdded', {
@@ -360,7 +357,7 @@ module.exports = class View {
       } else {
         message = dashboard.i18n('emptyFolderAdded')
       }
-      this.plugin.core.info(message)
+      this.plugin.uppy.info(message)
     }).catch((e) => {
       state = this.plugin.getPluginState()
       delete state.selectedFolders[folderId]
@@ -385,8 +382,8 @@ module.exports = class View {
     // is removed and 'core:file-removed' is emitted.
     const files = folder.files.concat([])
     for (const fileId of files) {
-      if (fileId in this.plugin.core.getState().files) {
-        this.plugin.core.removeFile(fileId)
+      if (fileId in this.plugin.uppy.getState().files) {
+        this.plugin.uppy.removeFile(fileId)
       }
     }
     delete folders[folderId]
@@ -452,8 +449,8 @@ module.exports = class View {
         if (this.plugin.isFolder(item)) {
           this.removeFolder(itemId)
         } else {
-          if (itemId in this.plugin.core.getState().files) {
-            this.plugin.core.removeFile(itemId)
+          if (itemId in this.plugin.uppy.getState().files) {
+            this.plugin.uppy.removeFile(itemId)
           }
         }
       }
@@ -515,10 +512,10 @@ module.exports = class View {
   }
 
   handleError (error) {
-    const core = this.plugin.core
-    const message = core.i18n('uppyServerError')
-    core.log(error.toString())
-    core.info({message: message, details: error.toString()}, 'error', 5000)
+    const uppy = this.plugin.uppy
+    const message = uppy.i18n('uppyServerError')
+    uppy.log(error.toString())
+    uppy.info({message: message, details: error.toString()}, 'error', 5000)
   }
 
   handleScroll (e) {
@@ -538,7 +535,7 @@ module.exports = class View {
   }
 
   donePicking () {
-    const dashboard = this.plugin.core.getPlugin('Dashboard')
+    const dashboard = this.plugin.uppy.getPlugin('Dashboard')
     if (dashboard) dashboard.hideAllPanels()
   }
 

+ 6 - 6
src/plugins/Redux.js

@@ -1,8 +1,8 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 
 module.exports = class Redux extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'state-sync'
     this.id = 'Redux'
     this.title = 'Redux Emitter'
@@ -23,11 +23,11 @@ module.exports = class Redux extends Plugin {
   }
 
   install () {
-    this.core.emitter.on('core:state-update', this.handleStateUpdate)
-    this.handleStateUpdate({}, this.core.state, this.core.state) // set the initial redux state
+    this.uppy.on('state-update', this.handleStateUpdate)
+    this.handleStateUpdate({}, this.uppy.state, this.uppy.state) // set the initial redux state
   }
 
   uninstall () {
-    this.core.emitter.off('core:state-update', this.handleStateUpdate)
+    this.uppy.off('state-update', this.handleStateUpdate)
   }
 }

+ 10 - 16
src/plugins/Redux.test.js

@@ -1,5 +1,5 @@
 import ReduxPlugin from './Redux'
-import Plugin from './Plugin'
+import Plugin from '../core/Plugin'
 
 describe('uploader/reduxPlugin', () => {
   it('should initialise successfully', () => {
@@ -33,9 +33,7 @@ describe('uploader/reduxPlugin', () => {
   describe('install', () => {
     it('should subscribe to uppy events', () => {
       const core = {
-        emitter: {
-          on: jest.fn()
-        }
+        on: jest.fn()
       }
 
       const redux = new ReduxPlugin(core, {
@@ -45,18 +43,16 @@ describe('uploader/reduxPlugin', () => {
       redux.handleStateUpdate = jest.fn()
       redux.install()
 
-      expect(core.emitter.on.mock.calls.length).toEqual(1)
-      expect(core.emitter.on.mock.calls[0]).toEqual([
-        'core:state-update',
+      expect(core.on.mock.calls.length).toEqual(1)
+      expect(core.on.mock.calls[0]).toEqual([
+        'state-update',
         redux.handleStateUpdate
       ])
     })
 
     it('should call this.handleStateUpdate with the current state on install', () => {
       const core = {
-        emitter: {
-          on: jest.fn()
-        }
+        on: jest.fn()
       }
 
       const redux = new ReduxPlugin(core, {
@@ -78,9 +74,7 @@ describe('uploader/reduxPlugin', () => {
   describe('uninstall', () => {
     it('should should unsubscribe from uppy events on uninstall', () => {
       const core = {
-        emitter: {
-          off: jest.fn()
-        }
+        off: jest.fn()
       }
 
       const redux = new ReduxPlugin(core, {
@@ -89,9 +83,9 @@ describe('uploader/reduxPlugin', () => {
       })
       redux.uninstall()
 
-      expect(core.emitter.off.mock.calls.length).toEqual(1)
-      expect(core.emitter.off.mock.calls[0]).toEqual([
-        'core:state-update',
+      expect(core.off.mock.calls.length).toEqual(1)
+      expect(core.off.mock.calls[0]).toEqual([
+        'state-update',
         redux.handleStateUpdate
       ])
     })

+ 10 - 10
src/plugins/ReduxDevTools.js

@@ -1,4 +1,4 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 
 /**
  * Add Redux DevTools support to Uppy
@@ -7,8 +7,8 @@ const Plugin = require('./Plugin')
  * and https://github.com/zalmoxisus/mobx-remotedev/blob/master/src/monitorActions.js
  */
 module.exports = class ReduxDevTools extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'debugger'
     this.id = 'ReduxDevTools'
     this.title = 'Redux DevTools'
@@ -36,18 +36,18 @@ module.exports = class ReduxDevTools extends Plugin {
         // Implement monitors actions
         switch (message.payload.type) {
           case 'RESET':
-            this.core.reset()
+            this.uppy.reset()
             return
           case 'IMPORT_STATE':
             const computedStates = message.payload.nextLiftedState.computedStates
-            this.core.state = Object.assign({}, this.core.state, computedStates[computedStates.length - 1].state)
-            this.core.updateAll(this.core.state)
+            this.uppy.state = Object.assign({}, this.uppy.state, computedStates[computedStates.length - 1].state)
+            this.uppy.updateAll(this.uppy.state)
             return
           case 'JUMP_TO_STATE':
           case 'JUMP_TO_ACTION':
             // this.setState(state)
-            this.core.state = Object.assign({}, this.core.state, JSON.parse(message.state))
-            this.core.updateAll(this.core.state)
+            this.uppy.state = Object.assign({}, this.uppy.state, JSON.parse(message.state))
+            this.uppy.updateAll(this.uppy.state)
         }
       }
     })
@@ -57,14 +57,14 @@ module.exports = class ReduxDevTools extends Plugin {
     this.withDevTools = typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION__
     if (this.withDevTools) {
       this.initDevTools()
-      this.core.on('core:state-update', this.handleStateChange)
+      this.uppy.on('state-update', this.handleStateChange)
     }
   }
 
   uninstall () {
     if (this.withDevTools) {
       this.devToolsUnsubscribe()
-      this.core.emitter.off('core:state-update', this.handleStateUpdate)
+      this.uppy.off('state-update', this.handleStateUpdate)
     }
   }
 }

+ 0 - 5
src/plugins/RestoreFiles/index.js

@@ -1,5 +0,0 @@
-const GoldenRetriever = require('../GoldenRetriever')
-
-console.warn('Using `uppy/lib/plugins/RestoreFiles` is deprecated and will be removed in v0.22. Please use `uppy/lib/plugins/GoldenRetriever` instead.')
-
-module.exports = GoldenRetriever

+ 9 - 9
src/plugins/StatusBar/index.js

@@ -1,4 +1,4 @@
-const Plugin = require('../Plugin')
+const Plugin = require('../../core/Plugin')
 const Translator = require('../../core/Translator')
 const StatusBar = require('./StatusBar')
 const { getSpeed } = require('../../core/Utils')
@@ -10,8 +10,8 @@ const prettyBytes = require('prettier-bytes')
  * A status bar.
  */
 module.exports = class StatusBarUI extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.id = this.opts.id || 'StatusBar'
     this.title = 'StatusBar'
     this.type = 'progressindicator'
@@ -139,7 +139,7 @@ module.exports = class StatusBarUI extends Plugin {
       !isAllErrored &&
       uploadStartedFiles.length > 0
 
-    const resumableUploads = this.core.getState().capabilities.resumableUploads || false
+    const resumableUploads = this.uppy.getState().capabilities.resumableUploads || false
 
     return StatusBar({
       error: state.error,
@@ -152,11 +152,11 @@ module.exports = class StatusBarUI extends Plugin {
       isAllErrored: isAllErrored,
       isUploadStarted: isUploadStarted,
       i18n: this.i18n,
-      pauseAll: this.core.pauseAll,
-      resumeAll: this.core.resumeAll,
-      retryAll: this.core.retryAll,
-      cancelAll: this.core.cancelAll,
-      startUpload: this.core.upload,
+      pauseAll: this.uppy.pauseAll,
+      resumeAll: this.uppy.resumeAll,
+      retryAll: this.uppy.retryAll,
+      cancelAll: this.uppy.cancelAll,
+      startUpload: this.uppy.upload,
       complete: completeFiles.length,
       newFiles: newFiles.length,
       inProgress: uploadStartedFiles.length,

+ 41 - 41
src/plugins/Transloadit/index.js

@@ -1,5 +1,5 @@
 const Translator = require('../../core/Translator')
-const Plugin = require('../Plugin')
+const Plugin = require('../../core/Plugin')
 const Client = require('./Client')
 const StatusSocket = require('./Socket')
 
@@ -7,8 +7,8 @@ const StatusSocket = require('./Socket')
  * Upload files to Transloadit using Tus.
  */
 module.exports = class Transloadit extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'uploader'
     this.id = 'Transloadit'
     this.title = 'Transloadit'
@@ -85,7 +85,7 @@ module.exports = class Transloadit extends Plugin {
     const options = this.opts
     return Promise.all(
       fileIDs.map((fileID) => {
-        const file = this.core.getFile(fileID)
+        const file = this.uppy.getFile(fileID)
         const promise = Promise.resolve()
           .then(() => options.getAssemblyOptions(file, options))
         return promise.then((assemblyOptions) => {
@@ -120,7 +120,7 @@ module.exports = class Transloadit extends Plugin {
   createAssembly (fileIDs, uploadID, options) {
     const pluginOptions = this.opts
 
-    this.core.log('Transloadit: create assembly')
+    this.uppy.log('Transloadit: create assembly')
 
     return this.client.createAssembly({
       params: options.params,
@@ -175,22 +175,22 @@ module.exports = class Transloadit extends Plugin {
         return newFile
       }
 
-      const files = Object.assign({}, this.core.state.files)
+      const files = Object.assign({}, this.uppy.state.files)
       fileIDs.forEach((id) => {
         files[id] = attachAssemblyMetadata(files[id], assembly)
       })
 
-      this.core.setState({ files })
+      this.uppy.setState({ files })
 
-      this.core.emit('transloadit:assembly-created', assembly, fileIDs)
+      this.uppy.emit('transloadit:assembly-created', assembly, fileIDs)
 
       return this.connectSocket(assembly)
         .then(() => assembly)
     }).then((assembly) => {
-      this.core.log('Transloadit: Created assembly')
+      this.uppy.log('Transloadit: Created assembly')
       return assembly
     }).catch((err) => {
-      this.core.info(this.i18n('creatingAssemblyFailed'), 'error', 0)
+      this.uppy.info(this.i18n('creatingAssemblyFailed'), 'error', 0)
 
       // Reject the promise.
       throw err
@@ -207,7 +207,7 @@ module.exports = class Transloadit extends Plugin {
    */
   reserveFiles (assembly, fileIDs) {
     return Promise.all(fileIDs.map((fileID) => {
-      const file = this.core.getFile(fileID)
+      const file = this.uppy.getFile(fileID)
       return this.client.reserveFile(assembly, file)
     }))
   }
@@ -217,7 +217,7 @@ module.exports = class Transloadit extends Plugin {
    * once they have been fully uploaded.
    */
   onFileUploadURLAvailable (fileID) {
-    const file = this.core.getFile(fileID)
+    const file = this.uppy.getFile(fileID)
     if (!file || !file.transloadit || !file.transloadit.assembly) {
       return
     }
@@ -226,13 +226,13 @@ module.exports = class Transloadit extends Plugin {
     const assembly = state.assemblies[file.transloadit.assembly]
 
     this.client.addFile(assembly, file).catch((err) => {
-      this.core.log(err)
-      this.core.emit('transloadit:import-error', assembly, file.id, err)
+      this.uppy.log(err)
+      this.uppy.emit('transloadit:import-error', assembly, file.id, err)
     })
   }
 
   findFile (uploadedFile) {
-    const files = this.core.state.files
+    const files = this.uppy.state.files
     for (const id in files) {
       if (!files.hasOwnProperty(id)) {
         continue
@@ -254,7 +254,7 @@ module.exports = class Transloadit extends Plugin {
         }
       })
     })
-    this.core.emit('transloadit:upload', uploadedFile, this.getAssembly(assemblyId))
+    this.uppy.emit('transloadit:upload', uploadedFile, this.getAssembly(assemblyId))
   }
 
   onResult (assemblyId, stepName, result) {
@@ -266,7 +266,7 @@ module.exports = class Transloadit extends Plugin {
     this.setPluginState({
       results: state.results.concat(result)
     })
-    this.core.emit('transloadit:result', stepName, result, this.getAssembly(assemblyId))
+    this.uppy.emit('transloadit:result', stepName, result, this.getAssembly(assemblyId))
   }
 
   onAssemblyFinished (url) {
@@ -277,7 +277,7 @@ module.exports = class Transloadit extends Plugin {
           [assembly.assembly_id]: assembly
         })
       })
-      this.core.emit('transloadit:complete', assembly)
+      this.uppy.emit('transloadit:complete', assembly)
     })
   }
 
@@ -290,7 +290,7 @@ module.exports = class Transloadit extends Plugin {
 
     socket.on('upload', this.onFileUploadComplete.bind(this, assembly.assembly_id))
     socket.on('error', (error) => {
-      this.core.emit('transloadit:assembly-error', assembly, error)
+      this.uppy.emit('transloadit:assembly-error', assembly, error)
     })
 
     if (this.opts.waitForEncoding) {
@@ -304,7 +304,7 @@ module.exports = class Transloadit extends Plugin {
     } else if (this.opts.waitForMetadata) {
       socket.on('metadata', () => {
         this.onAssemblyFinished(assembly.assembly_ssl_url)
-        this.core.emit('transloadit:complete', assembly)
+        this.uppy.emit('transloadit:complete', assembly)
       })
     }
 
@@ -312,7 +312,7 @@ module.exports = class Transloadit extends Plugin {
       socket.on('connect', resolve)
       socket.on('error', reject)
     }).then(() => {
-      this.core.log('Transloadit: Socket is ready')
+      this.uppy.log('Transloadit: Socket is ready')
     })
   }
 
@@ -321,7 +321,7 @@ module.exports = class Transloadit extends Plugin {
     fileIDs = fileIDs.filter((file) => !file.error)
 
     fileIDs.forEach((fileID) => {
-      this.core.emit('core:preprocess-progress', fileID, {
+      this.uppy.emit('preprocess-progress', fileID, {
         mode: 'indeterminate',
         message: this.i18n('creatingAssembly')
       })
@@ -334,7 +334,7 @@ module.exports = class Transloadit extends Plugin {
         }
       }).then(() => {
         fileIDs.forEach((fileID) => {
-          this.core.emit('core:preprocess-complete', fileID)
+          this.uppy.emit('preprocess-complete', fileID)
         })
       })
     }
@@ -396,7 +396,7 @@ module.exports = class Transloadit extends Plugin {
 
     return new Promise((resolve, reject) => {
       fileIDs.forEach((fileID) => {
-        this.core.emit('core:postprocess-progress', fileID, {
+        this.uppy.emit('postprocess-progress', fileID, {
           mode: 'indeterminate',
           message: this.i18n('encoding')
         })
@@ -414,7 +414,7 @@ module.exports = class Transloadit extends Plugin {
 
         const files = this.getAssemblyFiles(assembly.assembly_id)
         files.forEach((file) => {
-          this.core.emit('core:postprocess-complete', file.id)
+          this.uppy.emit('postprocess-complete', file.id)
         })
 
         checkAllComplete()
@@ -430,9 +430,9 @@ module.exports = class Transloadit extends Plugin {
         const files = this.getAssemblyFiles(assembly.assembly_id)
         files.forEach((file) => {
           // TODO Maybe make a postprocess-error event here?
-          this.core.emit('core:upload-error', file.id, error)
+          this.uppy.emit('upload-error', file.id, error)
 
-          this.core.emit('core:postprocess-complete', file.id)
+          this.uppy.emit('postprocess-complete', file.id)
         })
 
         checkAllComplete()
@@ -461,14 +461,14 @@ module.exports = class Transloadit extends Plugin {
       }
 
       const removeListeners = () => {
-        this.core.off('transloadit:complete', onAssemblyFinished)
-        this.core.off('transloadit:assembly-error', onAssemblyError)
-        this.core.off('transloadit:import-error', onImportError)
+        this.uppy.off('transloadit:complete', onAssemblyFinished)
+        this.uppy.off('transloadit:assembly-error', onAssemblyError)
+        this.uppy.off('transloadit:import-error', onImportError)
       }
 
-      this.core.on('transloadit:complete', onAssemblyFinished)
-      this.core.on('transloadit:assembly-error', onAssemblyError)
-      this.core.on('transloadit:import-error', onImportError)
+      this.uppy.on('transloadit:complete', onAssemblyFinished)
+      this.uppy.on('transloadit:assembly-error', onAssemblyError)
+      this.uppy.on('transloadit:import-error', onImportError)
     }).then(() => {
       // Clean up uploadID → assemblyIDs, they're no longer going to be used anywhere.
       const state = this.getPluginState()
@@ -479,11 +479,11 @@ module.exports = class Transloadit extends Plugin {
   }
 
   install () {
-    this.core.addPreProcessor(this.prepareUpload)
-    this.core.addPostProcessor(this.afterUpload)
+    this.uppy.addPreProcessor(this.prepareUpload)
+    this.uppy.addPostProcessor(this.afterUpload)
 
     if (this.opts.importFromUploadURLs) {
-      this.core.on('core:upload-success', this.onFileUploadURLAvailable)
+      this.uppy.on('upload-success', this.onFileUploadURLAvailable)
     }
 
     this.setPluginState({
@@ -499,11 +499,11 @@ module.exports = class Transloadit extends Plugin {
   }
 
   uninstall () {
-    this.core.removePreProcessor(this.prepareUpload)
-    this.core.removePostProcessor(this.afterUpload)
+    this.uppy.removePreProcessor(this.prepareUpload)
+    this.uppy.removePostProcessor(this.afterUpload)
 
     if (this.opts.importFromUploadURLs) {
-      this.core.off('core:upload-success', this.onFileUploadURLAvailable)
+      this.uppy.off('upload-success', this.onFileUploadURLAvailable)
     }
   }
 
@@ -513,9 +513,9 @@ module.exports = class Transloadit extends Plugin {
   }
 
   getAssemblyFiles (assemblyID) {
-    const fileIDs = Object.keys(this.core.state.files)
+    const fileIDs = Object.keys(this.uppy.state.files)
     return fileIDs.map((fileID) => {
-      return this.core.getFile(fileID)
+      return this.uppy.getFile(fileID)
     }).filter((file) => {
       return file && file.transloadit && file.transloadit.assembly === assemblyID
     })

+ 43 - 44
src/plugins/Tus.js

@@ -1,4 +1,4 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 const tus = require('tus-js-client')
 const UppySocket = require('../core/UppySocket')
 const {
@@ -50,8 +50,8 @@ function createEventTracker (emitter) {
  *
  */
 module.exports = class Tus extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'uploader'
     this.id = 'Tus'
     this.title = 'Tus'
@@ -75,7 +75,7 @@ module.exports = class Tus extends Plugin {
   }
 
   handleResetProgress () {
-    const files = Object.assign({}, this.core.state.files)
+    const files = Object.assign({}, this.uppy.state.files)
     Object.keys(files).forEach((fileID) => {
       // Only clone the file object if it has a Tus `uploadUrl` attached.
       if (files[fileID].tus && files[fileID].tus.uploadUrl) {
@@ -85,7 +85,7 @@ module.exports = class Tus extends Plugin {
       }
     })
 
-    this.core.setState({ files })
+    this.uppy.setState({ files })
   }
 
   /**
@@ -116,7 +116,7 @@ module.exports = class Tus extends Plugin {
    * @returns {Promise}
    */
   upload (file, current, total) {
-    this.core.log(`uploading ${current} of ${total}`)
+    this.uppy.log(`uploading ${current} of ${total}`)
 
     this.resetUploaderReferences(file.id)
 
@@ -131,8 +131,8 @@ module.exports = class Tus extends Plugin {
       )
 
       optsTus.onError = (err) => {
-        this.core.log(err)
-        this.core.emit('core:upload-error', file.id, err)
+        this.uppy.log(err)
+        this.uppy.emit('upload-error', file.id, err)
         err.message = `Failed because: ${err.message}`
 
         this.resetUploaderReferences(file.id)
@@ -141,7 +141,7 @@ module.exports = class Tus extends Plugin {
 
       optsTus.onProgress = (bytesUploaded, bytesTotal) => {
         this.onReceiveUploadUrl(file, upload.url)
-        this.core.emit('core:upload-progress', {
+        this.uppy.emit('upload-progress', {
           uploader: this,
           id: file.id,
           bytesUploaded: bytesUploaded,
@@ -150,10 +150,10 @@ module.exports = class Tus extends Plugin {
       }
 
       optsTus.onSuccess = () => {
-        this.core.emit('core:upload-success', file.id, upload, upload.url)
+        this.uppy.emit('upload-success', file.id, upload, upload.url)
 
         if (upload.url) {
-          this.core.log('Download ' + upload.file.name + ' from ' + upload.url)
+          this.uppy.log('Download ' + upload.file.name + ' from ' + upload.url)
         }
 
         this.resetUploaderReferences(file.id)
@@ -163,7 +163,7 @@ module.exports = class Tus extends Plugin {
 
       const upload = new tus.Upload(file.data, optsTus)
       this.uploaders[file.id] = upload
-      this.uploaderEvents[file.id] = createEventTracker(this.core)
+      this.uploaderEvents[file.id] = createEventTracker(this.uppy)
 
       this.onFileRemove(file.id, (targetFileID) => {
         this.resetUploaderReferences(file.id)
@@ -197,7 +197,7 @@ module.exports = class Tus extends Plugin {
         upload.start()
       }
       if (!file.isRestored) {
-        this.core.emit('core:upload-started', file.id, upload)
+        this.uppy.emit('upload-started', file.id, upload)
       }
     })
   }
@@ -206,7 +206,7 @@ module.exports = class Tus extends Plugin {
     this.resetUploaderReferences(file.id)
 
     return new Promise((resolve, reject) => {
-      this.core.log(file.remote.url)
+      this.uppy.log(file.remote.url)
       if (file.serverToken) {
         this.connectToServerSocket(file)
       } else {
@@ -215,7 +215,7 @@ module.exports = class Tus extends Plugin {
           endpoint = file.tus.endpoint
         }
 
-        this.core.emitter.emit('core:upload-started', file.id)
+        this.uppy.emit('upload-started', file.id)
 
         fetch(file.remote.url, {
           method: 'post',
@@ -238,9 +238,8 @@ module.exports = class Tus extends Plugin {
 
           res.json().then((data) => {
             const token = data.token
+            this.uppy.setFileState(file.id, { serverToken: token })
             file = this.getFile(file.id)
-            file.serverToken = token
-            this.updateFile(file)
             this.connectToServerSocket(file)
             resolve()
           })
@@ -254,7 +253,7 @@ module.exports = class Tus extends Plugin {
     const host = getSocketHost(file.remote.host)
     const socket = new UppySocket({ target: `${host}/api/${token}` })
     this.uploaderSockets[file.id] = socket
-    this.uploaderEvents[file.id] = createEventTracker(this.core)
+    this.uploaderEvents[file.id] = createEventTracker(this.uppy)
 
     this.onFileRemove(file.id, () => socket.send('pause', {}))
 
@@ -290,20 +289,20 @@ module.exports = class Tus extends Plugin {
     socket.on('progress', (progressData) => emitSocketProgress(this, progressData, file))
 
     socket.on('success', (data) => {
-      this.core.emitter.emit('core:upload-success', file.id, data, data.url)
+      this.uppy.emit('upload-success', file.id, data, data.url)
       this.resetUploaderReferences(file.id)
     })
   }
 
   getFile (fileID) {
-    return this.core.state.files[fileID]
+    return this.uppy.state.files[fileID]
   }
 
   updateFile (file) {
-    const files = Object.assign({}, this.core.state.files, {
+    const files = Object.assign({}, this.uppy.state.files, {
       [file.id]: file
     })
-    this.core.setState({ files })
+    this.uppy.setState({ files })
   }
 
   onReceiveUploadUrl (file, uploadURL) {
@@ -321,22 +320,22 @@ module.exports = class Tus extends Plugin {
   }
 
   onFileRemove (fileID, cb) {
-    this.uploaderEvents[fileID].on('core:file-removed', (targetFileID) => {
+    this.uploaderEvents[fileID].on('file-removed', (targetFileID) => {
       if (fileID === targetFileID) cb(targetFileID)
     })
   }
 
   onPause (fileID, cb) {
-    this.uploaderEvents[fileID].on('core:upload-pause', (targetFileID, isPaused) => {
+    this.uploaderEvents[fileID].on('upload-pause', (targetFileID, isPaused) => {
       if (fileID === targetFileID) {
-        // const isPaused = this.core.pauseResume(fileID)
+        // const isPaused = this.uppy.pauseResume(fileID)
         cb(isPaused)
       }
     })
   }
 
   onRetry (fileID, cb) {
-    this.uploaderEvents[fileID].on('core:upload-retry', (targetFileID) => {
+    this.uploaderEvents[fileID].on('upload-retry', (targetFileID) => {
       if (fileID === targetFileID) {
         cb()
       }
@@ -344,29 +343,29 @@ module.exports = class Tus extends Plugin {
   }
 
   onRetryAll (fileID, cb) {
-    this.uploaderEvents[fileID].on('core:retry-all', (filesToRetry) => {
-      if (!this.core.getFile(fileID)) return
+    this.uploaderEvents[fileID].on('retry-all', (filesToRetry) => {
+      if (!this.uppy.getFile(fileID)) return
       cb()
     })
   }
 
   onPauseAll (fileID, cb) {
-    this.uploaderEvents[fileID].on('core:pause-all', () => {
-      if (!this.core.getFile(fileID)) return
+    this.uploaderEvents[fileID].on('pause-all', () => {
+      if (!this.uppy.getFile(fileID)) return
       cb()
     })
   }
 
   onCancelAll (fileID, cb) {
-    this.uploaderEvents[fileID].on('core:cancel-all', () => {
-      if (!this.core.getFile(fileID)) return
+    this.uploaderEvents[fileID].on('cancel-all', () => {
+      if (!this.uppy.getFile(fileID)) return
       cb()
     })
   }
 
   onResumeAll (fileID, cb) {
-    this.uploaderEvents[fileID].on('core:resume-all', () => {
-      if (!this.core.getFile(fileID)) return
+    this.uploaderEvents[fileID].on('resume-all', () => {
+      if (!this.uppy.getFile(fileID)) return
       cb()
     })
   }
@@ -390,40 +389,40 @@ module.exports = class Tus extends Plugin {
 
   handleUpload (fileIDs) {
     if (fileIDs.length === 0) {
-      this.core.log('Tus: no files to upload!')
+      this.uppy.log('Tus: no files to upload!')
       return Promise.resolve()
     }
 
-    this.core.log('Tus is uploading...')
-    const filesToUpload = fileIDs.map((fileID) => this.core.getFile(fileID))
+    this.uppy.log('Tus is uploading...')
+    const filesToUpload = fileIDs.map((fileID) => this.uppy.getFile(fileID))
 
     return this.uploadFiles(filesToUpload)
   }
 
   addResumableUploadsCapabilityFlag () {
-    const newCapabilities = Object.assign({}, this.core.getState().capabilities)
+    const newCapabilities = Object.assign({}, this.uppy.getState().capabilities)
     newCapabilities.resumableUploads = true
-    this.core.setState({
+    this.uppy.setState({
       capabilities: newCapabilities
     })
   }
 
   install () {
     this.addResumableUploadsCapabilityFlag()
-    this.core.addUploader(this.handleUpload)
+    this.uppy.addUploader(this.handleUpload)
 
-    this.core.on('core:reset-progress', this.handleResetProgress)
+    this.uppy.on('reset-progress', this.handleResetProgress)
 
     if (this.opts.autoRetry) {
-      this.core.on('back-online', this.core.retryAll)
+      this.uppy.on('back-online', this.uppy.retryAll)
     }
   }
 
   uninstall () {
-    this.core.removeUploader(this.handleUpload)
+    this.uppy.removeUploader(this.handleUpload)
 
     if (this.opts.autoRetry) {
-      this.core.off('back-online', this.core.retryAll)
+      this.uppy.off('back-online', this.uppy.retryAll)
     }
   }
 }

+ 0 - 5
src/plugins/Tus10.js

@@ -1,5 +0,0 @@
-const Tus = require('./Tus')
-
-console.warn('Using `uppy/lib/plugins/Tus10` is deprecated and will be removed in v0.22. Please use `uppy/lib/plugins/Tus` instead.')
-
-module.exports = Tus

+ 10 - 10
src/plugins/Webcam/index.js

@@ -1,4 +1,4 @@
-const Plugin = require('../Plugin')
+const Plugin = require('../../core/Plugin')
 const Translator = require('../../core/Translator')
 const {
   getFileTypeExtension,
@@ -34,8 +34,8 @@ function getMediaDevices () {
  * Webcam
  */
 module.exports = class Webcam extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.mediaDevices = getMediaDevices()
     this.supportsUserMedia = !!this.mediaDevices
     this.protocol = location.protocol.match(/https/i) ? 'https' : 'http'
@@ -168,7 +168,7 @@ module.exports = class Webcam extends Plugin {
       })
       return this.getVideo()
     }).then((file) => {
-      return this.core.addFile(file)
+      return this.uppy.addFile(file)
     }).then(() => {
       this.recordingChunks = null
       this.recorder = null
@@ -207,11 +207,11 @@ module.exports = class Webcam extends Plugin {
         }
 
         if (count > 0) {
-          this.core.info(`${count}...`, 'warning', 800)
+          this.uppy.info(`${count}...`, 'warning', 800)
           count--
         } else {
           clearInterval(countDown)
-          this.core.info(this.i18n('smile'), 'success', 1500)
+          this.uppy.info(this.i18n('smile'), 'success', 1500)
           setTimeout(() => resolve(), 1500)
         }
       }, 1000)
@@ -224,14 +224,14 @@ module.exports = class Webcam extends Plugin {
 
     this.opts.onBeforeSnapshot().catch((err) => {
       const message = typeof err === 'object' ? err.message : err
-      this.core.info(message, 'error', 5000)
+      this.uppy.info(message, 'error', 5000)
       return Promise.reject(new Error(`onBeforeSnapshot: ${message}`))
     }).then(() => {
       return this.getImage()
     }).then((tagFile) => {
       this.captureInProgress = false
-      this.core.addFile(tagFile)
-      const dashboard = this.core.getPlugin('Dashboard')
+      this.uppy.addFile(tagFile)
+      const dashboard = this.uppy.getPlugin('Dashboard')
       if (dashboard) dashboard.hideAllPanels()
     }, (error) => {
       this.captureInProgress = false
@@ -286,7 +286,7 @@ module.exports = class Webcam extends Plugin {
   focus () {
     if (this.opts.countdown) return
     setTimeout(() => {
-      this.core.info(this.i18n('smile'), 'success', 1500)
+      this.uppy.info(this.i18n('smile'), 'success', 1500)
     }, 1000)
   }
 

+ 29 - 29
src/plugins/XHRUpload.js

@@ -1,4 +1,4 @@
-const Plugin = require('./Plugin')
+const Plugin = require('../core/Plugin')
 const cuid = require('cuid')
 const Translator = require('../core/Translator')
 const UppySocket = require('../core/UppySocket')
@@ -10,8 +10,8 @@ const {
 } = require('../core/Utils')
 
 module.exports = class XHRUpload extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'uploader'
     this.id = 'XHRUpload'
     this.title = 'XHRUpload'
@@ -64,13 +64,13 @@ module.exports = class XHRUpload extends Plugin {
   getOptions (file) {
     const opts = Object.assign({},
       this.opts,
-      this.core.state.xhrUpload || {},
+      this.uppy.state.xhrUpload || {},
       file.xhrUpload || {}
     )
     opts.headers = {}
     Object.assign(opts.headers, this.opts.headers)
-    if (this.core.state.xhrUpload) {
-      Object.assign(opts.headers, this.core.state.xhrUpload.headers)
+    if (this.uppy.state.xhrUpload) {
+      Object.assign(opts.headers, this.uppy.state.xhrUpload.headers)
     }
     if (file.xhrUpload) {
       Object.assign(opts.headers, file.xhrUpload.headers)
@@ -102,7 +102,7 @@ module.exports = class XHRUpload extends Plugin {
   upload (file, current, total) {
     const opts = this.getOptions(file)
 
-    this.core.log(`uploading ${current} of ${total}`)
+    this.uppy.log(`uploading ${current} of ${total}`)
     return new Promise((resolve, reject) => {
       const data = opts.formData
         ? this.createFormDataUpload(file, opts)
@@ -110,9 +110,9 @@ module.exports = class XHRUpload extends Plugin {
 
       const onTimedOut = () => {
         xhr.abort()
-        this.core.log(`[XHRUpload] ${id} timed out`)
+        this.uppy.log(`[XHRUpload] ${id} timed out`)
         const error = new Error(this.i18n('timedOut', { seconds: Math.ceil(opts.timeout / 1000) }))
-        this.core.emit('core:upload-error', file.id, error)
+        this.uppy.emit('upload-error', file.id, error)
         reject(error)
       }
       let aliveTimer
@@ -125,7 +125,7 @@ module.exports = class XHRUpload extends Plugin {
       const id = cuid()
 
       xhr.upload.addEventListener('loadstart', (ev) => {
-        this.core.log(`[XHRUpload] ${id} started`)
+        this.uppy.log(`[XHRUpload] ${id} started`)
         if (opts.timeout > 0) {
           // Begin checking for timeouts when loading starts.
           isAlive()
@@ -133,13 +133,13 @@ module.exports = class XHRUpload extends Plugin {
       })
 
       xhr.upload.addEventListener('progress', (ev) => {
-        this.core.log(`[XHRUpload] ${id} progress: ${ev.loaded} / ${ev.total}`)
+        this.uppy.log(`[XHRUpload] ${id} progress: ${ev.loaded} / ${ev.total}`)
         if (opts.timeout > 0) {
           isAlive()
         }
 
         if (ev.lengthComputable) {
-          this.core.emit('core:upload-progress', {
+          this.uppy.emit('upload-progress', {
             uploader: this,
             id: file.id,
             bytesUploaded: ev.loaded,
@@ -149,34 +149,34 @@ module.exports = class XHRUpload extends Plugin {
       })
 
       xhr.addEventListener('load', (ev) => {
-        this.core.log(`[XHRUpload] ${id} finished`)
+        this.uppy.log(`[XHRUpload] ${id} finished`)
         clearTimeout(aliveTimer)
 
         if (ev.target.status >= 200 && ev.target.status < 300) {
           const resp = opts.getResponseData(xhr)
           const uploadURL = resp[opts.responseUrlFieldName]
 
-          this.core.emit('core:upload-success', file.id, resp, uploadURL)
+          this.uppy.emit('upload-success', file.id, resp, uploadURL)
 
           if (uploadURL) {
-            this.core.log(`Download ${file.name} from ${file.uploadURL}`)
+            this.uppy.log(`Download ${file.name} from ${file.uploadURL}`)
           }
 
           return resolve(file)
         } else {
           const error = opts.getResponseError(xhr) || new Error('Upload error')
           error.request = xhr
-          this.core.emit('core:upload-error', file.id, error)
+          this.uppy.emit('upload-error', file.id, error)
           return reject(error)
         }
       })
 
       xhr.addEventListener('error', (ev) => {
-        this.core.log(`[XHRUpload] ${id} errored`)
+        this.uppy.log(`[XHRUpload] ${id} errored`)
         clearTimeout(aliveTimer)
 
         const error = opts.getResponseError(xhr) || new Error('Upload error')
-        this.core.emit('core:upload-error', file.id, error)
+        this.uppy.emit('upload-error', file.id, error)
         return reject(error)
       })
 
@@ -188,26 +188,26 @@ module.exports = class XHRUpload extends Plugin {
 
       xhr.send(data)
 
-      this.core.on('core:upload-cancel', (fileID) => {
+      this.uppy.on('upload-cancel', (fileID) => {
         if (fileID === file.id) {
           xhr.abort()
         }
       })
 
-      this.core.on('core:cancel-all', () => {
-        // const files = this.core.getState().files
+      this.uppy.on('cancel-all', () => {
+        // const files = this.uppy.getState().files
         // if (!files[file.id]) return
         xhr.abort()
       })
 
-      this.core.emit('core:upload-started', file.id)
+      this.uppy.emit('upload-started', file.id)
     })
   }
 
   uploadRemote (file, current, total) {
     const opts = this.getOptions(file)
     return new Promise((resolve, reject) => {
-      this.core.emit('core:upload-started', file.id)
+      this.uppy.emit('upload-started', file.id)
 
       const fields = {}
       const metaFields = Array.isArray(opts.metaFields)
@@ -247,7 +247,7 @@ module.exports = class XHRUpload extends Plugin {
           socket.on('progress', (progressData) => emitSocketProgress(this, progressData, file))
 
           socket.on('success', (data) => {
-            this.core.emit('core:upload-success', file.id, data, data.url)
+            this.uppy.emit('upload-success', file.id, data, data.url)
             socket.close()
             return resolve()
           })
@@ -280,24 +280,24 @@ module.exports = class XHRUpload extends Plugin {
 
   handleUpload (fileIDs) {
     if (fileIDs.length === 0) {
-      this.core.log('[XHRUpload] No files to upload!')
+      this.uppy.log('[XHRUpload] No files to upload!')
       return Promise.resolve()
     }
 
-    this.core.log('[XHRUpload] Uploading...')
+    this.uppy.log('[XHRUpload] Uploading...')
     const files = fileIDs.map(getFile, this)
     function getFile (fileID) {
-      return this.core.state.files[fileID]
+      return this.uppy.state.files[fileID]
     }
 
     return this.uploadFiles(files).then(() => null)
   }
 
   install () {
-    this.core.addUploader(this.handleUpload)
+    this.uppy.addUploader(this.handleUpload)
   }
 
   uninstall () {
-    this.core.removeUploader(this.handleUpload)
+    this.uppy.removeUploader(this.handleUpload)
   }
 }

+ 4 - 3
src/scss/_dashboard.scss

@@ -106,7 +106,7 @@
   }
 
   .UppyDashboard--modal & {
-    z-index: $zIndex-4;
+    z-index: $zIndex-5;
     display: block;
   }
 }
@@ -460,7 +460,7 @@
     float: left;
     width: 140px;
     height: 170px;
-    margin: 5px 21px;
+    margin: 5px 15px;
     // border-radius: 6px;
     border: 0;
     background-color: initial;
@@ -571,7 +571,7 @@
 }
 
 .UppyDashboardItem-info {
-  padding: 10px 19px 0 3px;
+  padding: 10px 19px 0 25px;
   position: relative;
   max-width: 70%;
 
@@ -579,6 +579,7 @@
     width: 100%;
     max-width: 100%;
     flex: 1;
+    padding-left: 3px;
     // border-bottom-left-radius: 6px;
     // border-bottom-right-radius: 6px;
     // border: 1px solid rgba($color-gray, 0.2);

+ 1 - 2
src/scss/_statusbar.scss

@@ -66,7 +66,6 @@
   padding-left: 15px;
   white-space: nowrap;
   text-overflow: ellipsis;
-  // overflow-x: hidden;
   color: $color-white;
 }
 
@@ -101,7 +100,7 @@
 }
 
 .UppyStatusBar.is-waiting .UppyStatusBar-actions {
-  left: 30px;
+  left: 20px;
   right: initial;
 }
 

+ 0 - 70
test/acceptance/dragdrop.spec.js

@@ -1,70 +0,0 @@
-var test = require('tape')
-var path = require('path')
-var tools = require('./tools')
-
-module.exports = function (driver, platform, host) {
-  var testName = 'DragDrop: upload one file'
-
-  test(tools.prettyTestName(testName, platform), function (t) {
-    t.plan(1)
-
-    // Go to the example URL
-    driver.get(host + '/examples/dragdrop/')
-    driver.manage().window().maximize()
-
-    // Set Saucelabs test name
-    tools.setSauceTestName(driver, testName)
-
-    driver.executeScript(tools.uppySelectFakeFile)
-    driver.findElement({css: '.UppyDragDrop-Two-Upload'}).click()
-
-    var platformBrowser = platform.browser.toLowerCase()
-    if (platformBrowser === 'safari' || platformBrowser === 'microsoftedge') {
-      console.log('fake-selecting a fake file')
-      driver.executeScript(tools.uppySelectFakeFile)
-      driver.findElement({css: '.UppyDragDrop-Two-Upload'}).click()
-    } else {
-      console.log('selecting a real file')
-      // Make file input “visible”
-      driver.executeScript('document.querySelector(".UppyDragDrop-One .uppy-DragDrop-input").style.opacity = 1')
-
-      // Find input by css selector & pass absolute image path to it
-      driver
-        .findElement({css: '.UppyDragDrop-One .uppy-DragDrop-input'})
-        .sendKeys(path.join(__dirname, 'image.jpg'))
-    }
-
-    function isUploaded () {
-      // return driver.findElement(By.id('console-log'))
-      //   .getAttribute('value')
-      //   .then(function (value) {
-      //     var isFileUploaded = value.indexOf('Download image.jpg') !== -1
-      //     return isFileUploaded
-      //   })
-
-      // .getText() only work on visible elements, so we use .getAttribute('textContent'), go figure
-      // http://stackoverflow.com/questions/21994261/gettext-not-working-on-a-select-from-dropdown
-
-      // TODO: figure out how to deal with multiple Uppy instances on the page
-      return driver.findElement({css: '.UppyDragDrop-One-Progress .UppyProgressBar-percentage'})
-        .getAttribute('textContent')
-        .then(function (value) {
-          var progress = parseInt(value)
-          var isFileUploaded = progress === 100
-          return isFileUploaded
-        })
-    }
-
-    driver.wait(isUploaded, 12000, 'File image.jpg should be uploaded within 15 seconds')
-      .then(function (result) {
-        tools.testEqual(driver, t, result)
-        driver.quit()
-      })
-      .catch(function (err) {
-        tools.collectErrors(driver).then(function () {
-          tools.testFail(driver, t, err)
-          driver.quit()
-        })
-      })
-  })
-}

+ 0 - 21
test/acceptance/dummy.spec.js

@@ -1,21 +0,0 @@
-var test = require('tape')
-var webdriver = require('selenium-webdriver')
-
-var driver = new webdriver
-  .Builder()
-  .forBrowser('firefox')
-  .build()
-
-test('open a page, create a variable and get its value', function (t) {
-  t.plan(1)
-
-  driver.get('http://ya.ru')
-  driver.executeScript('window.a = "blabla";')
-  driver.sleep(2000)
-  driver.executeScript('return a').then(function (val) {
-    console.log(val)
-    t.equal(val, 'blabla')
-  })
-  driver.sleep(5000)
-  driver.quit()
-})

+ 0 - 49
test/acceptance/fallback.spec.js

@@ -1,49 +0,0 @@
-var test = require('tape')
-var path = require('path')
-var tools = require('./tools')
-
-module.exports = function (driver, platform, host) {
-  var testName = 'Fallback: fall back to regular <form> upload when JS is not working, or not loaded yet, or browser is not supported by Uppy'
-
-  test(tools.prettyTestName(testName, platform), function (t) {
-    t.plan(1)
-
-    driver.get(host + '/examples/multipart/index.html')
-
-    driver.manage().window().maximize()
-
-    tools.setSauceTestName(driver, testName)
-
-    driver
-      .findElement({css: '.UppyForm input'})
-      .sendKeys(path.join(__dirname, 'image.jpg'))
-
-    // driver.switchTo().alert().dismiss()
-    //   .catch(function (err) {
-    //     console.log(err)
-    //   })
-    driver.findElement({css: '.UppyForm button'}).click()
-
-    function isRedirectedAfterUpload () {
-      // this should close the “Do you want to save this file?” alert when Travis runs the test
-
-      return driver.getCurrentUrl().then(function (val) {
-        console.log('current url is ', val)
-        var isPageRedirected = val.indexOf('api2.transloadit.com') !== -1
-        return isPageRedirected
-      })
-    }
-
-    driver.wait(isRedirectedAfterUpload, 12000, 'Browser should navigate to api2.transloadit.com after upload')
-      .then(function (isPageRedirected) {
-        tools.testEqual(driver, t, isPageRedirected === true)
-        driver.quit()
-      })
-      .catch(function (err) {
-        tools.collectErrors(driver).then(function () {
-          tools.testFail(driver, t, err)
-          driver.quit()
-        })
-      })
-  })
-}

+ 0 - 40
test/acceptance/i18n.spec.js

@@ -1,40 +0,0 @@
-var test = require('tape')
-var tools = require('./tools')
-
-module.exports = function (driver, platform, host) {
-  var testName = 'i18n: load DragDrop with Russian localization strings'
-
-  test(tools.prettyTestName(testName, platform), function (t) {
-    t.plan(1)
-
-    driver.get(host + '/examples/i18n')
-    driver.manage().window().maximize()
-
-    tools.setSauceTestName(driver, testName)
-
-    function findLabelTextElement () {
-      return driver.findElements({css: '.uppy-DragDrop-label'}).then(function (result) {
-        return result[0]
-      })
-    }
-
-    driver.wait(findLabelTextElement, 8000, 'Uppy should load within 8 seconds')
-      .then(function (element) {
-        element.getText().then(function (value) {
-          // why trim? Microsoft Edge:
-          // expected: 'Выберите файл или перенесите его сюда'
-          // actual:   'Выберите файл или перенесите его сюда '
-          var expectedValue = 'Перенесите файлы сюда или выберите'
-          console.log(value, '/', expectedValue)
-          tools.testEqual(driver, t, value.trim() === expectedValue)
-          driver.quit()
-        })
-      })
-      .catch(function (err) {
-        tools.collectErrors(driver).then(function () {
-          tools.testFail(driver, t, err)
-          driver.quit()
-        })
-      })
-  })
-}

BIN
test/acceptance/image.jpg


BIN
test/acceptance/image2.jpg


+ 0 - 135
test/acceptance/index.js

@@ -1,135 +0,0 @@
-// Docs aren't that great to find. Mostly JAVA based. Here are few helpful resources:
-// - https://www.browserstack.com/automate/node#testing-frameworks
-// - http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/firefox/index_exports_Driver.html
-// - https://github.com/SeleniumHQ/selenium/blob/8f988e07cc316a48e0ff94d8ff823c95142532e9/javascript/webdriver/webdriver.js
-// - https://github.com/SeleniumHQ/selenium/blob/c10e8a955883f004452cdde18096d70738397788/javascript/node/selenium-webdriver/test/upload_test.js
-//
-// - https://github.com/SeleniumHQ/selenium/wiki/WebDriverJs
-// - http://seleniumhq.github.io/selenium/docs/api/javascript/
-// - http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/firefox/index.html
-// - http://selenium.googlecode.com/git/docs/api/javascript/namespace_webdriver_By.html
-// - http://selenium.googlecode.com/git/docs/api/javascript/class_webdriver_WebElement.html
-
-// require('babel-register')
-
-var webdriver = require('selenium-webdriver')
-var remote = require('selenium-webdriver/remote')
-
-// The Travis Sauce Connect addon exports the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables,
-// and relays connections to the hub URL back to Sauce Labs.
-// See: https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-Sauce-Labs
-var username = process.env.SAUCE_USERNAME
-var accessKey = process.env.SAUCE_ACCESS_KEY
-
-var remoteHost = 'http://uppy.io'
-var localHost = 'http://localhost:4000'
-
-// if accessKey is supplied as env variable, this is a remote Saucelabs test
-var isTravisTest = process.env.TRAVIS === 'true'
-var isRemoteTest = !!accessKey
-
-var host = localHost
-if (isTravisTest) {
-  // @todo This should become localhost to utilize the Travis saucelabs addon tunnel
-  // But it seems Edge and Safari fail on that right now, so targeting uppy.io instead.
-  // That is unideal, as we are then testing a previous deploy, and not the current build
-  // host = remoteHost
-  host = localHost
-} else if (isRemoteTest) {
-  // We're not too sure about a working tunnel otherwise, best just test uppy.io
-  host = remoteHost
-} else {
-  // If we don't have any access keys set, we'll assume you'll be playing around with a local
-  // firefox webdriver.
-  host = localHost
-}
-
-console.log('Acceptance tests will be targetting: ' + host)
-
-var platforms = [
-  // { browser: 'Safari', version: '8.0', os: 'OS X 10.10' }
-  // { browser: 'MicrosoftEdge', version: '13.10586', os: 'Windows 10' },
-  { browser: 'Firefox', version: '38.0', os: 'Linux' },
-  { browser: 'Internet Explorer', version: '10.0', os: 'Windows 8' },
-  { browser: 'Internet Explorer', version: '11.103', os: 'Windows 10' },
-  { browser: 'Chrome', version: '48.0', os: 'Windows 7' },
-  { browser: 'Firefox', version: '34.0', os: 'Windows 7' }
-]
-
-var tests = [
-  require('./multipart.spec.js'),
-  require('./i18n.spec.js'),
-  require('./dragdrop.spec.js')
-]
-
-function buildDriver (platform) {
-  var driver
-  if (isRemoteTest) {
-    var capabilities = {
-      'browserName': platform.browser,
-      'platform': platform.os,
-      'version': platform.version,
-      'username': username,
-      'accessKey': accessKey
-    }
-
-    if (isTravisTest) {
-      // @todo Do we need a hub_url = "%s:%s@localhost:4445" % (username, access_key)
-      // as mentioned in https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-Sauce-Labs ?
-      capabilities['tunnel-identifier'] = process.env.TRAVIS_JOB_NUMBER
-      capabilities['build'] = process.env.TRAVIS_BUILD_NUMBER
-      capabilities['name'] = 'Travis ##' + process.env.TRAVIS_JOB_NUMBER
-      capabilities['tags'] = [process.env.TRAVIS_NODE_VERSION, 'CI']
-    }
-
-    driver = new webdriver
-      .Builder()
-      .withCapabilities(capabilities)
-      .usingServer('http://' + username + ':' + accessKey +
-                   '@ondemand.saucelabs.com:80/wd/hub')
-      .build()
-    driver.setFileDetector(new remote.FileDetector())
-  } else {
-    driver = new webdriver
-      .Builder()
-      .forBrowser('firefox')
-      .build()
-  }
-  return driver
-}
-
-var specificTests = {
-  fallback: function () {
-    var ancientPlatform = { browser: 'internet explorer', version: '8.0', os: 'Windows 7' }
-    var driver = buildDriver({ browser: 'internet explorer', version: '8.0', os: 'Windows 7' })
-    var test = require('./fallback.spec.js')
-
-    test(driver, ancientPlatform, host)
-  }
-}
-// RUN TESTS
-
-function runAllTests () {
-  if (isRemoteTest) {
-    // run custom platform-specific tests here
-    // <form> fallback test
-    console.log('Skipping the fallback test', specificTests.fallback)
-    // specificTests.fallback()
-
-    // run all tests for all platforms
-    platforms.forEach(function (platform) {
-      tests.forEach(function (test) {
-        var driver = buildDriver(platform)
-        test(driver, platform, host)
-      })
-    })
-  } else {
-    // run tests just for local Firefox
-    tests.forEach(function (test) {
-      var driver = buildDriver()
-      test(driver, { browser: 'Firefox', version: 'Version', os: 'Local' }, host)
-    })
-  }
-}
-
-runAllTests()

+ 0 - 65
test/acceptance/multipart.spec.js

@@ -1,65 +0,0 @@
-var test = require('tape')
-var tools = require('./tools')
-var path = require('path')
-
-module.exports = function (driver, platform, host) {
-  var testName = 'Multipart: upload a file'
-
-  test(tools.prettyTestName(testName, platform), function (t) {
-    t.plan(1)
-
-    driver.get(host + '/examples/multipart/')
-    driver.manage().window().maximize()
-
-    tools.setSauceTestName(driver, testName)
-
-    // driver.manage().timeouts().implicitlyWait(5 * 1000)
-
-    var platformBrowser = platform.browser.toLowerCase()
-    if (platformBrowser === 'safari' || platformBrowser === 'microsoftedge') {
-      console.log('fake-selecting a fake file')
-      driver.executeScript(tools.uppySelectFakeFile)
-      // driver.findElement({css: '.UppyForm-uploadBtn'}).click()
-    } else {
-      console.log('selecting a real file')
-      driver.executeScript('document.querySelector(".uppy-FileInput-input").style.opacity = 1')
-      // Find input by css selector & pass absolute image path to it
-      driver.findElement({css: '.uppy-FileInput-input'})
-        .then(function (el) {
-          el.sendKeys(path.join(__dirname, 'image.jpg'))
-          // el.sendKeys(path.join(__dirname, 'image2.jpg'))
-          // driver.findElement({css: '.UppyForm-uploadBtn'}).click()
-        })
-        .catch(function (err) {
-          throw err
-        })
-    }
-
-    function isUploaded () {
-      // .getText() only works on visible elements, so we use .getAttribute('textContent'), go figure
-      // http://stackoverflow.com/questions/21994261/gettext-not-working-on-a-select-from-dropdown
-      return driver.findElement({css: '.UppyProgressBar .UppyProgressBar-percentage'})
-        .getAttribute('textContent')
-        .then(function (value) {
-          var progress = parseInt(value)
-          var isFileUploaded = progress === 100
-          return isFileUploaded
-        })
-        .catch(function (err) {
-          console.log(err)
-        })
-    }
-
-    driver.wait(isUploaded, 12000, 'File image.jpg should be uploaded within 15 seconds')
-      .then(function (result) {
-        tools.testEqual(driver, t, result)
-        driver.quit()
-      })
-      .catch(function (err) {
-        tools.collectErrors(driver).then(function () {
-          tools.testFail(driver, t, err)
-          driver.quit()
-        })
-      })
-  })
-}

+ 0 - 49
test/acceptance/saucelabs-dummy.spec.js

@@ -1,49 +0,0 @@
-var webdriver = require('selenium-webdriver')
-var remote = require('selenium-webdriver/remote')
-
-var username = process.env.SAUCE_USERNAME
-var accessKey = process.env.SAUCE_ACCESS_KEY
-
-// var platform = { browser: 'firefox', version: '34.0', os: 'Windows 7' }
-var platform = { browser: 'Safari', version: '9.0', os: 'OS X 10.11' }
-
-function buildDriver (platform) {
-  var driver = new webdriver
-    .Builder()
-    .withCapabilities({
-      'browserName': platform.browser,
-      'platform': platform.os,
-      'version': platform.version,
-      'username': username,
-      'accessKey': accessKey
-    })
-    .usingServer('http://' + username + ':' + accessKey +
-                '@ondemand.saucelabs.com:80/wd/hub')
-    .build()
-  driver.setFileDetector(new remote.FileDetector())
-  return driver
-}
-
-function getBtnValue () {
-  return document.querySelector('.button__text').textContent
-}
-
-function runTest (driver, platform) {
-  console.log('Running dummy test in ' + platform.browser + ' on ' + platform.os)
-  driver.executeScript('sauce:job-name=dummy test')
-
-  driver.get('http://ya.ru')
-  driver.executeScript(getBtnValue).then(function (val) {
-    console.log(val)
-    driver.getTitle().then(function (title) {
-      console.log('title is: ' + title)
-      console.log('Finnished running dummy test, I quit!')
-      driver
-        .executeScript('sauce:job-result=passed')
-      driver.quit()
-    })
-  })
-}
-
-var driver = buildDriver(platform)
-runTest(driver, platform)

+ 0 - 118
test/acceptance/tools.js

@@ -1,118 +0,0 @@
-var webdriver = require('selenium-webdriver')
-// var firefox = require('selenium-webdriver/firefox')
-var By = webdriver.By
-// var path = require('path')
-var chalk = require('chalk')
-
-function uppySelectFakeFile () {
-  var blob = new Blob(
-    ['data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTIwIDEyMCI+CiAgPGNpcmNsZSBjeD0iNjAiIGN5PSI2MCIgcj0iNTAiLz4KPC9zdmc+Cg=='],
-    {type: 'image/svg+xml'}
-  )
-  window._uppy.addFile({
-    source: 'acceptance-test',
-    name: 'test-file',
-    type: 'image/svg+xml',
-    data: blob
-  })
-}
-
-function prettyTestName (name, platform) {
-  var testName = chalk.cyan.bold(name)
-  var platformName = chalk.yellow(
-        platform.os + ', ' +
-        platform.browser + ' ' +
-        platform.version
-      )
-  return testName + ' / ' + platformName
-}
-
-// https://wiki.saucelabs.com/display/DOCS/Annotating+Tests+with+Selenium's+JavaScript+Executor
-function setSauceTestStatus (driver, passed) {
-  driver
-    .executeScript('sauce:job-result=' + passed)
-    .catch(function (err) {
-      console.log('local test, so this is ok: ' + err)
-    })
-}
-
-function setSauceTestName (driver, testName) {
-  driver
-    .executeScript('sauce:job-name=' + testName)
-    .catch(function (err) {
-      console.log('local test, so this is ok: ' + err)
-    })
-}
-
-function testEqual (driver, t, condition) {
-  t.equal(condition, true)
-  if (condition) {
-    setSauceTestStatus(driver, true)
-  } else {
-    setSauceTestStatus(driver, false)
-  }
-}
-
-function testFail (driver, t, err) {
-  t.fail(err)
-  setSauceTestStatus(driver, false)
-}
-
-// Monitor for errors, and dump them
-function collectErrors (driver) {
-  return driver.executeScript('return uppyLog;')
-    .then(function (uppyLog) {
-      console.error([
-        '[uppy-log]',
-        chalk.red(uppyLog)
-      ].join(' '))
-    })
-    .catch(function (err) {
-      console.log('no uppyLog, that’s fine: ' + err)
-    })
-
-    // TODO: maybe figure out a way to get errors from all browsers
-    // return driver.executeScript('return window.JSErrorCollector_errors.pump()')
-    //   .then(function (errors) {
-    //     if (!errors || !errors.length) {
-    //       return
-    //     }
-    //     errors.forEach(function (error) {
-    //       console.error([
-    //         '[browser-error]',
-    //         chalk.magenta(error.sourceName),
-    //         chalk.dim('#' + error.lineNumber),
-    //         chalk.red(error.errorMessage)
-    //       ].join(' '))
-    //     })
-    //     return
-    //   })
-}
-
-// function setDriver () {
-//   var profile = new firefox.Profile()
-//   // profile.addExtension(path.join(__dirname, 'xpi', 'firebug-2.0.16.xpi'))
-//   // profile.addExtension(path.join(__dirname, 'xpi', 'JSErrorCollector.xpi'))
-//   // profile.setPreference('extensions.firebug.showChromeErrors', true)
-//
-//   var options = new firefox.Options().setProfile(profile)
-//   var driver = new firefox.Driver(options)
-//
-//   // var driver = new webdriver.Builder()
-//   //     .forBrowser('firefox')
-//   //     .build()
-//
-//   return driver
-// }
-
-module.exports = {
-  // setDriver,
-  prettyTestName,
-  uppySelectFakeFile,
-  collectErrors,
-  testEqual,
-  testFail,
-  setSauceTestName,
-  setSauceTestStatus,
-  By
-}

BIN
test/acceptance/xpi/JSErrorCollector.xpi


BIN
test/acceptance/xpi/firebug-2.0.16.xpi


+ 4 - 4
test/mocks/acquirerPlugin1.js

@@ -1,8 +1,8 @@
-import Plugin from '../../src/plugins/Plugin.js'
+import Plugin from '../../src/core/Plugin'
 
 export default class TestSelector1 extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'acquirer'
     this.id = 'TestSelector1'
     this.name = this.constructor.name
@@ -15,7 +15,7 @@ export default class TestSelector1 extends Plugin {
   }
 
   run (results) {
-    this.core.log({
+    this.uppy.log({
       class: this.constructor.name,
       method: 'run',
       results: results

+ 4 - 4
test/mocks/acquirerPlugin2.js

@@ -1,8 +1,8 @@
-import Plugin from '../../src/plugins/Plugin.js'
+import Plugin from '../../src/core/Plugin'
 
 export default class TestSelector2 extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'acquirer'
     this.id = 'TestSelector2'
     this.name = this.constructor.name
@@ -15,7 +15,7 @@ export default class TestSelector2 extends Plugin {
   }
 
   run (results) {
-    this.core.log({
+    this.uppy.log({
       class: this.constructor.name,
       method: 'run',
       results: results

+ 4 - 4
test/mocks/invalidPluginWithoutId.js

@@ -1,14 +1,14 @@
-import Plugin from '../../src/plugins/Plugin.js'
+import Plugin from '../../src/core/Plugin'
 
 export default class InvalidPluginWithoutName extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.type = 'acquirer'
     this.name = this.constructor.name
   }
 
   run (results) {
-    this.core.log({
+    this.uppy.log({
       class: this.constructor.name,
       method: 'run',
       results: results

+ 4 - 4
test/mocks/invalidPluginWithoutType.js

@@ -1,14 +1,14 @@
-import Plugin from '../../src/plugins/Plugin.js'
+import Plugin from '../../src/core/Plugin'
 
 export default class InvalidPluginWithoutType extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
+  constructor (uppy, opts) {
+    super(uppy, opts)
     this.id = 'InvalidPluginWithoutType'
     this.name = this.constructor.name
   }
 
   run (results) {
-    this.core.log({
+    this.uppy.log({
       class: this.constructor.name,
       method: 'run',
       results: results

+ 1 - 1
website/src/api-usage-example.ejs

@@ -14,6 +14,6 @@ const uppy = Uppy({autoProceed: false})
   })
 uppy.run()
  
-uppy.on('core:success', (files) => {
+uppy.on('success', (files) => {
   console.log(`Upload complete! We’ve uploaded these files: ${files}`)
 })

+ 1 - 1
website/src/docs/index.md

@@ -22,7 +22,7 @@ const uppy = Uppy({ autoProceed: false })
   .use(Tus, {endpoint: '//master.tus.io/files/'})
   .run()
  
-uppy.on('core:complete', (result) => {
+uppy.on('complete', (result) => {
   console.log(`Upload complete! We’ve uploaded these files: ${result.successful}`)
 })
 ```

+ 1 - 1
website/src/docs/react.md

@@ -27,7 +27,7 @@ const uppy = Uppy({
 
 uppy.use(Tus, { endpoint: '/upload' })
 
-uppy.on('core:complete', (result) => {
+uppy.on('complete', (result) => {
   const url = result.successful[0].uploadURL
   store.dispatch({
     type: SET_USER_AVATAR_URL,

+ 33 - 20
website/src/docs/uppy.md

@@ -13,6 +13,7 @@ Core module that orchistrated everything in Uppy, exposing `state`, `events` and
 const uppy = Uppy({
   id: 'uppy',
   autoProceed: true,
+  debug: false,
   restrictions: {
     maxFileSize: false,
     maxNumberOfFiles: false,
@@ -23,7 +24,8 @@ const uppy = Uppy({
   onBeforeFileAdded: (currentFile, files) => Promise.resolve(),
   onBeforeUpload: (files, done) => Promise.resolve(),
   locale: defaultLocale,
-  store: defaultStore()
+  store: new DefaultStore(),
+  thumbnailGeneration: true
 })
 ```
 
@@ -66,7 +68,7 @@ meta: {
 }
 ```
 
-Can be altered with `uppy.setMeta({username: 'Peter'})` method.
+Can be altered with `uppy.setMeta({ username: 'Peter' })` method.
 
 ### `onBeforeFileAdded: (currentFile, files) => Promise.resolve()`
 
@@ -74,10 +76,10 @@ A function run before a file is added to Uppy. Gets passed `(currentFile, files)
 
 ```js
 onBeforeFileAdded: (currentFile, files) => {
-  if (currentFile.name === 'pitercss-IMG_0616.jpg') {
+  if (currentFile.name === 'forest-IMG_0616.jpg') {
     return Promise.resolve()
   }
-  return Promise.reject('this is not the file I was looking for')
+  return Promise.reject('This is not the file I was looking for')
 }
 ```
 
@@ -110,7 +112,8 @@ locale: {
       1: 'You have to select at least %{smart_count} files'
     },
     exceedsSize: 'This file exceeds maximum allowed size of',
-    youCanOnlyUploadFileTypes: 'You can only upload:'
+    youCanOnlyUploadFileTypes: 'You can only upload:',
+    uppyServerError: 'Connection with Uppy Server failed'
   }
 }
 ```
@@ -130,8 +133,8 @@ We are using a forked [Polyglot.js](https://github.com/airbnb/polyglot.js/blob/m
 ## `store: defaultStore()`
 
 The Store to use to keep track of internal state. By default, a simple object is used.
-This option can be used to plug Uppy state into an external state management library, such as Redux.
-Then, you can write custom views with the library that is also used by the rest of the application.
+
+This option can be used to plug Uppy state into an external state management library, such as Redux. Then, you can write custom views with the library that is also used by the rest of the application.
 
 <!-- TODO document store API -->
 
@@ -165,7 +168,7 @@ Add a new file to Uppy’s internal state.
 uppy.addFile({
   name: 'my-file.jpg', // file name
   type: 'image/jpeg', // file type
-  data: fileBlob, // file blob
+  data: blob, // file blob
   source: 'Local', // optional, sets what added the file, for example, Instagram
   isRemote: false // optional, set to true if actual file is not in the browser, but on some remote server, like when using uppy-server + Instagram, for example
 })
@@ -193,13 +196,19 @@ Update `uppy.state`. Usually this method is called internally, but in some cases
 Uppy’s default state on initialization:
 
 ```js
-this.state = {
+{
+  plugins: {},
   files: {},
   capabilities: {
     resumableUploads: false
   },
   totalProgress: 0,
-  meta: Object.assign({}, this.opts.meta)
+  meta: Object.assign({}, this.opts.meta),
+  info: {
+    isHidden: true,
+    type: 'info',
+    message: ''
+  }
 }
 ```
 
@@ -237,15 +246,17 @@ Returns `uppy.state`, which you can also use directly.
 Alters global `meta` object is state, the one that can be set in Uppy options and gets merged with all newly added files.
 
 ```js
-uppy.setMeta({resize: 1500})
+uppy.setMeta({ resize: 1500 })
 ```
 
-### `uppy.updateMeta(data, fileID)`
+### `uppy.setFileMeta(fileID, data)`
 
 Updated metadata for a specific file.
 
 ```js
-uppy.updateMeta({resize: 1500}, 'myfileID')
+uppy.setFileMeta('myfileID', { 
+  resize: 1500 
+})
 ```
 
 ### `uppy.reset()`
@@ -303,7 +314,7 @@ Subscribe to an uppy-event. See full list of events below.
 
 Uppy exposes events that you can subscribe to in your app:
 
-### `core:upload-progress`
+### `upload-progress`
 
 Fired each time file upload progress is available, `data` object looks like this:
 
@@ -316,17 +327,17 @@ data = {
 ```
 
 ```javascript
-uppy.on('core:upload-progress', (data) => {
+uppy.on('upload-progress', (data) => {
   console.log(data.id, data.bytesUploaded, data.bytesTotal)
 })
 ```
 
-### `core:upload-success`
+### `upload-success`
 
 Fired when single upload is complete.
 
 ``` javascript
-uppy.on('core:upload-success', (fileId, url) => {
+uppy.on('upload-success', (fileId, url) => {
   console.log(url)
   var img = new Image()
   img.width = 300
@@ -336,13 +347,15 @@ uppy.on('core:upload-success', (fileId, url) => {
 })
 ```
 
-### `core:complete`
+### `complete`
 
 Fired when all uploads are complete.
+
 The `result` parameter is an object with arrays of `successful` and `failed` files, just like in [`uppy.upload()`](#uppy-upload)'s return value.
 
 ``` javascript
-uppy.on('core:complete', (result) => {
-  console.log(result)
+uppy.on('complete', (result) => {
+  console.log('successful files:', result.successful)
+  console.log('failed files:', result.failed)
 })
 ```

+ 2 - 2
website/src/docs/xhrupload.md

@@ -57,7 +57,7 @@ headers: {
 
 ### `getResponseData(xhr)`
 
-When an upload has completed, Uppy will extract response data from the upload endpoint and send it back in the `core:upload-success` event.
+When an upload has completed, Uppy will extract response data from the upload endpoint and send it back in the `upload-success` event.
 By default, Uppy assumes the endpoint will return JSON. So, if `POST /upload` responds with:
 
 ```json
@@ -67,7 +67,7 @@ By default, Uppy assumes the endpoint will return JSON. So, if `POST /upload` re
 }
 ```
 
-That object will be emitted in the `core:upload-success` event.
+That object will be emitted in the `upload-success` event.
 
 Not all endpoints respond with JSON. Providing a `getResponseData` function overrides this behavior.
 The `xhr` parameter is the `XMLHttpRequest` instance used to upload the file.

+ 6 - 9
website/src/examples/dashboard/app.es6

@@ -5,7 +5,6 @@ const Dropbox = require('uppy/lib/plugins/Dropbox')
 const Instagram = require('uppy/lib/plugins/Instagram')
 const Webcam = require('uppy/lib/plugins/Webcam')
 const Tus = require('uppy/lib/plugins/Tus')
-const MetaData = require('uppy/lib/plugins/MetaData')
 
 const UPPY_SERVER = require('../env')
 
@@ -37,7 +36,11 @@ function uppyInit () {
     trigger: '.UppyModalOpenerBtn',
     inline: opts.DashboardInline,
     target: opts.DashboardInline ? '.DashboardContainer' : 'body',
-    note: opts.restrictions ? 'Images and video only, 2–3 files, up to 1 MB' : ''
+    note: opts.restrictions ? 'Images and video only, 2–3 files, up to 1 MB' : '',
+    metaFields: [
+      { id: 'license', name: 'License', value: 'Creative Commons', placeholder: 'specify license' },
+      { id: 'caption', name: 'Caption', value: '', placeholder: 'describe what the image is about' }
+    ]
   })
 
   if (opts.GoogleDrive) {
@@ -57,15 +60,9 @@ function uppyInit () {
   }
 
   uppy.use(Tus, {endpoint: TUS_ENDPOINT, resume: true})
-  uppy.use(MetaData, {
-    fields: [
-      { id: 'license', name: 'License', value: 'Creative Commons', placeholder: 'specify license' },
-      { id: 'caption', name: 'Caption', value: 'none', placeholder: 'describe what the image is about' }
-    ]
-  })
   uppy.run()
 
-  uppy.on('core:complete', (result) => {
+  uppy.on('complete', (result) => {
     console.log('Yo, uploaded: ')
     console.log(result.successful)
   })

+ 6 - 9
website/src/examples/dashboard/index.ejs

@@ -26,7 +26,6 @@ const Dropbox = require('uppy/lib/plugins/Dropbox')
 const Instagram = require('uppy/lib/plugins/Instagram')
 const Webcam = require('uppy/lib/plugins/Webcam')
 const Tus = require('uppy/lib/plugins/Tus')
-const MetaData = require('uppy/lib/plugins/MetaData')
 
 const uppy = Uppy({
   debug: true,
@@ -42,22 +41,20 @@ const uppy = Uppy({
   trigger: '.UppyModalOpenerBtn',
   inline: true,
   target: '.DashboardContainer'
-  note: 'Images and video only, 2–3 files, up to 1 MB'
+  note: 'Images and video only, 2–3 files, up to 1 MB',
+  metaFields: [
+    { id: 'license', name: 'License', value: 'Creative Commons', placeholder: 'specify license' },
+    { id: 'caption', name: 'Caption', value: '', placeholder: 'describe what the image is about' }
+  ]
 })
 .use(GoogleDrive, {target: Dashboard, host: 'https://server.uppy.io'})
 .use(Dropbox, {target: Dashboard, host: 'https://server.uppy.io'})
 .use(Instagram, {target: Dashboard, host: 'https://server.uppy.io'})
 .use(Webcam, {target: Dashboard})
 .use(Tus, {endpoint: 'https://master.tus.io/files/'})
-.use(MetaData, {
-  fields: [
-    { id: 'license', name: 'License', value: 'Creative Commons', placeholder: 'specify license' },
-    { id: 'caption', name: 'Caption', value: 'none', placeholder: 'describe what the image is about' }
-  ]
-})
 .run()
 
-uppy.on('core:complete', (result) => {
+uppy.on('complete', (result) => {
   console.log('Successfully uploaded:', result.successful)
 })
 {% endcodeblock %}

+ 1 - 1
website/themes/uppy/layout/index.ejs

@@ -97,7 +97,7 @@
     })
   .run()
 
-  uppy.on('core:success', (files) => {
+  uppy.on('success', (files) => {
     console.log(`Upload complete! We’ve uploaded these files: ${files}`)
   })
 </script>

File diff suppressed because it is too large
+ 0 - 0
website/themes/uppy/layout/partials/frontpage-code-sample.html


Some files were not shown because too many files changed in this diff