diff --git a/src/core/Core.js b/src/core/Core.js index 4b0ac33505..642ae7088b 100644 --- a/src/core/Core.js +++ b/src/core/Core.js @@ -452,6 +452,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. * diff --git a/src/plugins/Dashboard/index.js b/src/plugins/Dashboard/index.js index 138daa7f23..ef02213f44 100644 --- a/src/plugins/Dashboard/index.js +++ b/src/plugins/Dashboard/index.js @@ -69,6 +69,8 @@ module.exports = class DashboardUI extends Plugin { this.hideAllPanels = this.hideAllPanels.bind(this) this.showPanel = this.showPanel.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.pauseAll = this.pauseAll.bind(this) this.resumeAll = this.resumeAll.bind(this) @@ -166,6 +168,13 @@ module.exports = class DashboardUI extends Plugin { setTimeout(this.updateDashboardElWidth, 300) } + // Close the Modal on esc key press + handleEscapeKeyPress (event) { + if (event.keyCode === 27) { + this.hideModal() + } + } + initEvents () { // const dashboardEl = document.querySelector(`${this.opts.target} .UppyDashboard`) @@ -177,35 +186,29 @@ module.exports = class DashboardUI extends Plugin { 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 - dragDrop(this.el, (files) => { + this.removeDragDropListener = dragDrop(this.el, (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) @@ -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 () { const dashboardEl = document.querySelector('.UppyDashboard-inner') 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) { this.core.log('All right, someone dropped something...') @@ -432,4 +454,10 @@ module.exports = class DashboardUI extends Plugin { this.initEvents() this.actions() } + + uninstall () { + this.unmount() + this.removeActions() + this.removeEvents() + } } diff --git a/src/plugins/DragDrop/index.js b/src/plugins/DragDrop/index.js index 9609d82921..357edec04b 100644 --- a/src/plugins/DragDrop/index.js +++ b/src/plugins/DragDrop/index.js @@ -166,9 +166,15 @@ module.exports = class DragDrop extends Plugin { const plugin = this 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.core.log(files) }) } + + uninstall () { + this.removeDragDropListener() + this.unmount() + } } diff --git a/src/plugins/Dropbox/index.js b/src/plugins/Dropbox/index.js index 99e13518dd..ee51c354de 100644 --- a/src/plugins/Dropbox/index.js +++ b/src/plugins/Dropbox/index.js @@ -66,6 +66,10 @@ module.exports = class Dropbox extends Plugin { return } + uninstall () { + this.unmount() + } + onAuth (authenticated) { this.view.updateState({authenticated}) if (authenticated) { diff --git a/src/plugins/FileInput.js b/src/plugins/FileInput.js index 26521927f0..ace7db88d1 100644 --- a/src/plugins/FileInput.js +++ b/src/plugins/FileInput.js @@ -80,4 +80,8 @@ module.exports = class FileInput extends Plugin { const plugin = this this.target = this.mount(target, plugin) } + + uninstall () { + this.unmount() + } } diff --git a/src/plugins/GoogleDrive/index.js b/src/plugins/GoogleDrive/index.js index 9c79cc2d5d..c02cbcccce 100644 --- a/src/plugins/GoogleDrive/index.js +++ b/src/plugins/GoogleDrive/index.js @@ -64,6 +64,10 @@ module.exports = class Google extends Plugin { return } + uninstall () { + this.unmount() + } + onAuth (authenticated) { this.view.updateState({authenticated}) if (authenticated) { diff --git a/src/plugins/Informer.js b/src/plugins/Informer.js index 088d7eb1ae..006e5a97a6 100644 --- a/src/plugins/Informer.js +++ b/src/plugins/Informer.js @@ -113,4 +113,8 @@ module.exports = class Informer extends Plugin { const plugin = this this.target = this.mount(target, plugin) } + + uninstall () { + this.unmount() + } } diff --git a/src/plugins/MagicLog.js b/src/plugins/MagicLog.js index 5efb1c6451..f9de3baae2 100644 --- a/src/plugins/MagicLog.js +++ b/src/plugins/MagicLog.js @@ -19,16 +19,24 @@ module.exports = class MagicLog extends Plugin { // merge default options with the ones set by user 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 () { 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) } } diff --git a/src/plugins/MetaData.js b/src/plugins/MetaData.js index 641abebe4f..41e560ff15 100644 --- a/src/plugins/MetaData.js +++ b/src/plugins/MetaData.js @@ -17,6 +17,18 @@ module.exports = class MetaData extends Plugin { // merge default options with the ones set by user 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 () { @@ -26,16 +38,14 @@ module.exports = class MetaData extends Plugin { 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 () { this.addInitialMeta() } + + uninstall () { + this.core.emitter.off('file-added', this.handleFileAdded) + } } diff --git a/src/plugins/Plugin.js b/src/plugins/Plugin.js index eb12a4c9ce..0aae6162ab 100644 --- a/src/plugins/Plugin.js +++ b/src/plugins/Plugin.js @@ -25,6 +25,7 @@ module.exports = class Plugin { this.mount = this.mount.bind(this) this.focus = this.focus.bind(this) this.install = this.install.bind(this) + this.uninstall = this.uninstall.bind(this) // 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 () { return } @@ -105,4 +112,8 @@ module.exports = class Plugin { install () { return } + + uninstall () { + return + } } diff --git a/src/plugins/ProgressBar.js b/src/plugins/ProgressBar.js index 587f4fffab..22b54b09be 100644 --- a/src/plugins/ProgressBar.js +++ b/src/plugins/ProgressBar.js @@ -38,4 +38,8 @@ module.exports = class ProgressBar extends Plugin { const plugin = this this.target = this.mount(target, plugin) } + + uninstall () { + this.unmount() + } } diff --git a/src/plugins/Webcam/index.js b/src/plugins/Webcam/index.js index 27243a5d5c..9f4ceb2ea7 100644 --- a/src/plugins/Webcam/index.js +++ b/src/plugins/Webcam/index.js @@ -216,6 +216,11 @@ module.exports = class Webcam extends Plugin { this.target = this.mount(target, plugin) } + uninstall () { + this.webcam.reset() + this.unmount() + } + /** * Little shorthand to update the state with my new state */