Browse Source

Merge pull request #182 from goto-bus-stop/feature/dispose

Add `Uppy#close` for tearing down an Uppy instance.
Artur Paikin 8 years ago
parent
commit
fda551d26e

+ 31 - 0
src/core/Core.js

@@ -465,6 +465,37 @@ class Uppy {
     })
     })
   }
   }
 
 
+  /**
+   * Uninstall and remove a plugin.
+   *
+   * @param {Plugin} instance The plugin instance to remove.
+   */
+  removePlugin (instance) {
+    const list = this.plugins[instance.type]
+
+    if (instance.uninstall) {
+      instance.uninstall()
+    }
+
+    const index = list.indexOf(instance)
+    if (index !== -1) {
+      list.splice(index, 1)
+    }
+  }
+
+  /**
+   * Uninstall all plugins and close down this Uppy instance.
+   */
+  close () {
+    this.iteratePlugins((plugin) => {
+      plugin.uninstall()
+    })
+
+    if (this.socket) {
+      this.socket.close()
+    }
+  }
+
 /**
 /**
  * Logs stuff to console, only if `debug` is set to true. Silent in production.
  * Logs stuff to console, only if `debug` is set to true. Silent in production.
  *
  *

+ 48 - 20
src/plugins/Dashboard/index.js

@@ -69,6 +69,8 @@ module.exports = class DashboardUI extends Plugin {
     this.hideAllPanels = this.hideAllPanels.bind(this)
     this.hideAllPanels = this.hideAllPanels.bind(this)
     this.showPanel = this.showPanel.bind(this)
     this.showPanel = this.showPanel.bind(this)
     this.initEvents = this.initEvents.bind(this)
     this.initEvents = this.initEvents.bind(this)
+    this.handleEscapeKeyPress = this.handleEscapeKeyPress.bind(this)
+    this.handleFileCard = this.handleFileCard.bind(this)
     this.handleDrop = this.handleDrop.bind(this)
     this.handleDrop = this.handleDrop.bind(this)
     this.pauseAll = this.pauseAll.bind(this)
     this.pauseAll = this.pauseAll.bind(this)
     this.resumeAll = this.resumeAll.bind(this)
     this.resumeAll = this.resumeAll.bind(this)
@@ -166,6 +168,13 @@ module.exports = class DashboardUI extends Plugin {
     setTimeout(this.updateDashboardElWidth, 300)
     setTimeout(this.updateDashboardElWidth, 300)
   }
   }
 
 
+  // Close the Modal on esc key press
+  handleEscapeKeyPress (event) {
+    if (event.keyCode === 27) {
+      this.hideModal()
+    }
+  }
+
   initEvents () {
   initEvents () {
     // const dashboardEl = this.target.querySelector(`${this.opts.target} .UppyDashboard`)
     // const dashboardEl = this.target.querySelector(`${this.opts.target} .UppyDashboard`)
 
 
@@ -177,35 +186,29 @@ module.exports = class DashboardUI extends Plugin {
       this.core.log('Modal trigger wasn’t found')
       this.core.log('Modal trigger wasn’t found')
     }
     }
 
 
-    // Close the Modal on esc key press
-    document.body.addEventListener('keyup', (event) => {
-      if (event.keyCode === 27) {
-        this.hideModal()
-      }
-    })
+    document.body.addEventListener('keyup', this.handleEscapeKeyPress)
 
 
     // Drag Drop
     // Drag Drop
-    dragDrop(this.el, (files) => {
+    this.removeDragDropListener = dragDrop(this.el, (files) => {
       this.handleDrop(files)
       this.handleDrop(files)
     })
     })
   }
   }
 
 
-  actions () {
-    const bus = this.core.bus
+  removeEvents () {
+    const showModalTrigger = findDOMElement(this.opts.trigger)
+    if (!this.opts.inline && showModalTrigger) {
+      showModalTrigger.removeEventListener('click', this.showModal)
+    }
 
 
-    bus.on('core:file-add', () => {
-      this.hideAllPanels()
-    })
+    this.removeDragDropListener()
+    document.body.removeEventListener('keyup', this.handleEscapeKeyPress)
+  }
 
 
-    bus.on('dashboard:file-card', (fileId) => {
-      const modal = this.core.getState().modal
+  actions () {
+    const bus = this.core.bus
 
 
-      this.core.setState({
-        modal: Object.assign({}, modal, {
-          fileCardFor: fileId || false
-        })
-      })
-    })
+    bus.on('core:file-add', this.hideAllPanels)
+    bus.on('dashboard:file-card', this.handleFileCard)
 
 
     window.addEventListener('resize', this.updateDashboardElWidth)
     window.addEventListener('resize', this.updateDashboardElWidth)
 
 
@@ -219,6 +222,15 @@ module.exports = class DashboardUI extends Plugin {
     // })
     // })
   }
   }
 
 
+  removeActions () {
+    const bus = this.core.bus
+
+    window.removeEventListener('resize', this.updateDashboardElWidth)
+
+    bus.off('core:file-add', this.hideAllPanels)
+    bus.off('dashboard:file-card', this.handleFileCard)
+  }
+
   updateDashboardElWidth () {
   updateDashboardElWidth () {
     const dashboardEl = this.target.querySelector('.UppyDashboard-inner')
     const dashboardEl = this.target.querySelector('.UppyDashboard-inner')
     const containerWidth = dashboardEl.offsetWidth
     const containerWidth = dashboardEl.offsetWidth
@@ -232,6 +244,16 @@ module.exports = class DashboardUI extends Plugin {
     })
     })
   }
   }
 
 
+  handleFileCard (fileId) {
+    const modal = this.core.getState().modal
+
+    this.core.setState({
+      modal: Object.assign({}, modal, {
+        fileCardFor: fileId || false
+      })
+    })
+  }
+
   handleDrop (files) {
   handleDrop (files) {
     this.core.log('All right, someone dropped something...')
     this.core.log('All right, someone dropped something...')
 
 
@@ -432,4 +454,10 @@ module.exports = class DashboardUI extends Plugin {
     this.initEvents()
     this.initEvents()
     this.actions()
     this.actions()
   }
   }
+
+  uninstall () {
+    this.unmount()
+    this.removeActions()
+    this.removeEvents()
+  }
 }
 }

+ 7 - 1
src/plugins/DragDrop/index.js

@@ -165,9 +165,15 @@ module.exports = class DragDrop extends Plugin {
     const plugin = this
     const plugin = this
     this.target = this.mount(target, plugin)
     this.target = this.mount(target, plugin)
 
 
-    dragDrop(this.target.querySelector('.UppyDragDrop-container'), (files) => {
+    const dndContainer = this.target.querySelector('.UppyDragDrop-container')
+    this.removeDragDropListener = dragDrop(dndContainer, (files) => {
       this.handleDrop(files)
       this.handleDrop(files)
       this.core.log(files)
       this.core.log(files)
     })
     })
   }
   }
+
+  uninstall () {
+    this.removeDragDropListener()
+    this.unmount()
+  }
 }
 }

+ 4 - 0
src/plugins/Dropbox/index.js

@@ -66,6 +66,10 @@ module.exports = class Dropbox extends Plugin {
     return
     return
   }
   }
 
 
+  uninstall () {
+    this.unmount()
+  }
+
   onAuth (authenticated) {
   onAuth (authenticated) {
     this.view.updateState({authenticated})
     this.view.updateState({authenticated})
     if (authenticated) {
     if (authenticated) {

+ 4 - 0
src/plugins/FileInput.js

@@ -80,4 +80,8 @@ module.exports = class FileInput extends Plugin {
     const plugin = this
     const plugin = this
     this.target = this.mount(target, plugin)
     this.target = this.mount(target, plugin)
   }
   }
+
+  uninstall () {
+    this.unmount()
+  }
 }
 }

+ 4 - 0
src/plugins/GoogleDrive/index.js

@@ -64,6 +64,10 @@ module.exports = class Google extends Plugin {
     return
     return
   }
   }
 
 
+  uninstall () {
+    this.unmount()
+  }
+
   onAuth (authenticated) {
   onAuth (authenticated) {
     this.view.updateState({authenticated})
     this.view.updateState({authenticated})
     if (authenticated) {
     if (authenticated) {

+ 4 - 0
src/plugins/Informer.js

@@ -113,4 +113,8 @@ module.exports = class Informer extends Plugin {
     const plugin = this
     const plugin = this
     this.target = this.mount(target, plugin)
     this.target = this.mount(target, plugin)
   }
   }
+
+  uninstall () {
+    this.unmount()
+  }
 }
 }

+ 15 - 7
src/plugins/MagicLog.js

@@ -19,16 +19,24 @@ module.exports = class MagicLog extends Plugin {
 
 
     // merge default options with the ones set by user
     // merge default options with the ones set by user
     this.opts = Object.assign({}, defaultOptions, opts)
     this.opts = Object.assign({}, defaultOptions, opts)
+
+    this.handleStateUpdate = this.handleStateUpdate.bind(this)
+  }
+
+  handleStateUpdate (prev, state, patch) {
+    console.group('State')
+    console.log('Prev', prev)
+    console.log('Next', state)
+    console.log('Patch', patch)
+    console.groupEnd()
   }
   }
 
 
   install () {
   install () {
     const uppy = this.core.emitter
     const uppy = this.core.emitter
-    uppy.on('state-update', (prev, state, patch) => {
-      console.group('State')
-      console.log('Prev', prev)
-      console.log('Next', state)
-      console.log('Patch', patch)
-      console.groupEnd()
-    })
+    uppy.on('state-update', this.handleStateUpdate)
+  }
+
+  uninstall () {
+    this.core.emitter.off('state-update', this.handleStateUpdate)
   }
   }
 }
 }

+ 17 - 7
src/plugins/MetaData.js

@@ -17,6 +17,18 @@ module.exports = class MetaData extends Plugin {
 
 
     // merge default options with the ones set by user
     // merge default options with the ones set by user
     this.opts = Object.assign({}, defaultOptions, opts)
     this.opts = Object.assign({}, defaultOptions, opts)
+
+    this.handleFileAdded = this.handleFileAdded.bind(this)
+  }
+
+  handleFileAdded (fileID) {
+    const metaFields = this.opts.fields
+
+    metaFields.forEach((item) => {
+      const obj = {}
+      obj[item.id] = item.value
+      this.core.updateMeta(obj, fileID)
+    })
   }
   }
 
 
   addInitialMeta () {
   addInitialMeta () {
@@ -26,16 +38,14 @@ module.exports = class MetaData extends Plugin {
       metaFields: metaFields
       metaFields: metaFields
     })
     })
 
 
-    this.core.emitter.on('file-added', (fileID) => {
-      metaFields.forEach((item) => {
-        const obj = {}
-        obj[item.id] = item.value
-        this.core.updateMeta(obj, fileID)
-      })
-    })
+    this.core.emitter.on('file-added', this.handleFileAdded)
   }
   }
 
 
   install () {
   install () {
     this.addInitialMeta()
     this.addInitialMeta()
   }
   }
+
+  uninstall () {
+    this.core.emitter.off('file-added', this.handleFileAdded)
+  }
 }
 }

+ 11 - 0
src/plugins/Plugin.js

@@ -25,6 +25,7 @@ module.exports = class Plugin {
     this.mount = this.mount.bind(this)
     this.mount = this.mount.bind(this)
     this.focus = this.focus.bind(this)
     this.focus = this.focus.bind(this)
     this.install = this.install.bind(this)
     this.install = this.install.bind(this)
+    this.uninstall = this.uninstall.bind(this)
 
 
     // this.frame = null
     // this.frame = null
   }
   }
@@ -98,6 +99,12 @@ module.exports = class Plugin {
     }
     }
   }
   }
 
 
+  unmount () {
+    if (this.el && this.el.parentNode) {
+      this.el.parentNode.removeChild(this.el)
+    }
+  }
+
   focus () {
   focus () {
     return
     return
   }
   }
@@ -105,4 +112,8 @@ module.exports = class Plugin {
   install () {
   install () {
     return
     return
   }
   }
+
+  uninstall () {
+    return
+  }
 }
 }

+ 4 - 0
src/plugins/ProgressBar.js

@@ -38,4 +38,8 @@ module.exports = class ProgressBar extends Plugin {
     const plugin = this
     const plugin = this
     this.target = this.mount(target, plugin)
     this.target = this.mount(target, plugin)
   }
   }
+
+  uninstall () {
+    this.unmount()
+  }
 }
 }

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

@@ -216,6 +216,11 @@ module.exports = class Webcam extends Plugin {
     this.target = this.mount(target, plugin)
     this.target = this.mount(target, plugin)
   }
   }
 
 
+  uninstall () {
+    this.webcam.reset()
+    this.unmount()
+  }
+
   /**
   /**
    * Little shorthand to update the state with my new state
    * Little shorthand to update the state with my new state
    */
    */