From 1ef09677be563a5b84ee6cb4e025cb3b9ab1be9e Mon Sep 17 00:00:00 2001 From: Harry Hedger Date: Tue, 20 Sep 2016 20:45:04 -0400 Subject: [PATCH] Testing out Redux rough draft --- package.json | 1 + src/core/ReduxCoreDraft.js | 26 ++++++++ src/plugins/ReduxPluginDrafts/DragDrop.js | 60 ++++++++++++++++++ src/plugins/ReduxPluginDrafts/Informer.js | 62 ++++++++++++++++++ src/plugins/ReduxPluginDrafts/Remote.js | 77 +++++++++++++++++++++++ 5 files changed, 226 insertions(+) create mode 100644 src/core/ReduxCoreDraft.js create mode 100644 src/plugins/ReduxPluginDrafts/DragDrop.js create mode 100644 src/plugins/ReduxPluginDrafts/Informer.js create mode 100644 src/plugins/ReduxPluginDrafts/Remote.js diff --git a/package.json b/package.json index 0b2b887f8..c280fdec9 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "mime-types": "2.1.11", "namespace-emitter": "1.0.0", "pretty-bytes": "3.0.1", + "redux": "^3.6.0", "tus-js-client": "1.2.1", "uppy-base": "git+https://github.com/hedgerh/uppy-base.git", "whatwg-fetch": "1.0.0", diff --git a/src/core/ReduxCoreDraft.js b/src/core/ReduxCoreDraft.js new file mode 100644 index 000000000..b2a215011 --- /dev/null +++ b/src/core/ReduxCoreDraft.js @@ -0,0 +1,26 @@ +import { createStore, combineReducers } from 'redux' + +export default class Core { + constructor (opts) { + this.opts = opts + } + + parseFiles (files) { + // parse file or files + } + + use (Plugin, opts) { + const plugin = new Plugin(opts) + + // ... is same thing as using Object.assign + this.reducers = combineReducers({ + [plugin.id]: plugin.reducer, + ...this.reducers + }) + } + + init () { + this.store = createStore(this.reducers) + this.dispatch = this.store.dispatch + } +} diff --git a/src/plugins/ReduxPluginDrafts/DragDrop.js b/src/plugins/ReduxPluginDrafts/DragDrop.js new file mode 100644 index 000000000..797fb7c57 --- /dev/null +++ b/src/plugins/ReduxPluginDrafts/DragDrop.js @@ -0,0 +1,60 @@ +const DRAG_DROP_SUPPORTED = 'DRAG_DROP_SUPPORTED' + +/** + * Drag & Drop plugin + * + */ +export default class DragDrop { + constructor (opts) { + // Bind `this` to class methods + this.checkDragDropSupport = this.checkDragDropSupport.bind(this) + } + + getInitialState () { + return { + dragDropSupported: this.checkDragDropSupport() + } + } + + reducer (state = this.getInitialState(), action) { + switch (action.type) { + case DRAG_DROP_SUPPORTED: + return { + dragDropSupported: action.payload.dragDropSupported + } + } + } + + /** + * Checks if the browser supports Drag & Drop (not supported on mobile devices, for example). + * @return {Boolean} true if supported, false otherwise + */ + checkDragDropSupport () { + const div = document.createElement('div') + + if (!('draggable' in div) || !('ondragstart' in div && 'ondrop' in div)) { + return false + } + + if (!('FormData' in window)) { + return false + } + + if (!('FileReader' in window)) { + return false + } + + return true + } +} + +DragDrop.actions = { + checkDragDropSupport () { + return { + type: 'DRAG_DROP_SUPPORTED', + payload: { + dragDropSupported: this.checkDragDropSupport() + } + } + } +} diff --git a/src/plugins/ReduxPluginDrafts/Informer.js b/src/plugins/ReduxPluginDrafts/Informer.js new file mode 100644 index 000000000..81b7aabc9 --- /dev/null +++ b/src/plugins/ReduxPluginDrafts/Informer.js @@ -0,0 +1,62 @@ +/** + * Informer + * Shows rad message bubbles + * used like this: `bus.emit('informer', 'hello world', 'info', 5000)` + * or for errors: `bus.emit('informer', 'Error uploading img.jpg', 'error', 5000)` + * + */ + +const SHOW_INFORMER = 'SHOW_INFORMER' +const HIDE_INFORMER = 'HIDE_INFORMER' + +export default class Informer { + constructor (opts) { + // merge default options with the ones set by user + this.opts = opts + + this.getDefaultState = this.getDefaultState.bind(this) + this.reducer = this.reducer.bind(this) + } + + getInitialState () { + return { + isHidden: true, + msg: '', + duration: 0 + } + } + + reducer (state = this.getInitialState(), action) { + switch (action.type) { + case SHOW_INFORMER: + return { + isHidden: false, + msg: action.payload.msg, + duration: action.payload.duration + } + case HIDE_INFORMER: + return { + isHidden: true + } + default: + return state + } + } +} + +Informer.actions = { + show (msg, type, duration) { + return { + type: 'SHOW_INFORMER', + payload: { + msg, + duration + } + } + }, + hide () { + return { + type: 'HIDE_INFORMER' + } + } +} diff --git a/src/plugins/ReduxPluginDrafts/Remote.js b/src/plugins/ReduxPluginDrafts/Remote.js new file mode 100644 index 000000000..ba024d303 --- /dev/null +++ b/src/plugins/ReduxPluginDrafts/Remote.js @@ -0,0 +1,77 @@ +import { Remote as RemoteBase } from 'uppy-base' + +const REMOTE_AUTH = 'REMOTE_AUTH' +const REMOTE_LIST = 'REMOTE_LIST' +const REMOTE_LOGOUT = 'REMOTE_LOGOUT' + +class Remote extends RemoteBase { + constructor (opts) { + super(opts) + this.opts = opts + } + + reducer (state = this.getInitialState(), action) { + const { payload, type } = action + + // if this isn't the calling plugin, return + if (payload.source !== this.id) { + return state + } + + switch (type) { + case REMOTE_AUTH: + return Object.assign({}, state, { + authed: payload.authed + }) + case REMOTE_LIST: + return Object.assign({}, state, { + files: payload.files + }) + case REMOTE_LOGOUT: + return payload.result.ok ? this.getInitialState() : state + default: + return state + } + } +} + +Remote.actions = { + auth () { + return this.auth() + .then((authed) => { + return { + type: REMOTE_AUTH, + payload: { + source: this.id, + authed + } + } + }) + }, + list (directory) { + return this.list(directory) + .then((files) => { + return { + type: REMOTE_LIST, + payload: { + source: this.id, + files + } + } + }) + }, + logout () { + return this.logout() + .then((result) => { + return { + type: REMOTE_LOGOUT, + payload: { + source: this.id, + result + } + } + }) + } +} + +export default Remote