From 69475ad48e3043379348b5e81b81fd778d8e3d4b Mon Sep 17 00:00:00 2001 From: drquinn Date: Thu, 11 Jun 2015 12:43:21 -0700 Subject: [PATCH 1/8] create new files as untitled --- plugins/sidebar/file-operations.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/plugins/sidebar/file-operations.js b/plugins/sidebar/file-operations.js index 5664c60..971a906 100644 --- a/plugins/sidebar/file-operations.js +++ b/plugins/sidebar/file-operations.js @@ -85,6 +85,24 @@ const FileOperations = React.createClass({ const overlay = this.props.overlay; overlay.hide(); }, + newFile: function() { + const { workspace } = this.props; + workspace.current.update(() => ''); + + const directory = workspace.directory.deref(); + const untitledFiles = directory.filter(x => { + return x.get('name').match(/untitled/); + }); + + console.log(untitledFiles); + untitledFiles.takeLast(x => { + console.log(x.get('name').match(/\d+/g)); + }); + + const numUntitled = 2; + + workspace.filename.update(() => `untitled${numUntitled}`); + }, showCreateOverlay: function(evt){ evt.preventDefault(); @@ -162,7 +180,7 @@ const FileOperations = React.createClass({ icon="ion-compose" label="Save File" /> From 6c22743fb65ff3209f29d7c7146783e880c55c51 Mon Sep 17 00:00:00 2001 From: drquinn Date: Wed, 17 Jun 2015 16:22:01 -0700 Subject: [PATCH 2/8] updates to front end file handling, save and save as system --- plugins/editor/key-extension.js | 8 +++ plugins/sidebar/file-operations.js | 68 +----------------- plugins/sidebar/index.js | 90 +++++++++++++++++++++--- src/actions/file.js | 13 ++++ src/stores/file.js | 109 ++++++++++++++++++++++++++++- 5 files changed, 212 insertions(+), 76 deletions(-) diff --git a/plugins/editor/key-extension.js b/plugins/editor/key-extension.js index 4595705..dad5188 100644 --- a/plugins/editor/key-extension.js +++ b/plugins/editor/key-extension.js @@ -4,6 +4,7 @@ var { findNext, findPrevious } = require('../../src/actions/find'); var { moveByScrollUpLine, moveByScrollDownLine } = require('../../src/actions/editor-move'); var { indent } = require('../../src/actions/text-move'); var { print } = require('../../src/actions/system'); +var { processSave } = require('../../src/actions/file'); const keyExtension = { setup: function(app) { @@ -50,6 +51,13 @@ const keyExtension = { evt.preventDefault(); print(); } + }, + save: { + code: 'CTRL_S', + exec: (evt) => { + evt.preventDefault(); + processSave(); + } } }; diff --git a/plugins/sidebar/file-operations.js b/plugins/sidebar/file-operations.js index 971a906..dfeb7ad 100644 --- a/plugins/sidebar/file-operations.js +++ b/plugins/sidebar/file-operations.js @@ -9,7 +9,7 @@ const NewFileOverlay = require('./overlays/new-file'); const DownloadOverlay = require('./overlays/download'); const DeleteConfirmOverlay = require('./overlays/delete-confirm'); const { reloadDevices } = require('../../src/actions/device.js'); -const { clearName } = require('../../src/actions/file'); +const { clearName, newFile, processSave } = require('../../src/actions/file'); const styles = require('./styles'); @@ -26,35 +26,6 @@ const FileOperations = React.createClass({ toast.show(msg, { style: styles.successToast, timeout: 5000 }); }, - saveFile: function(evt){ - if(evt){ - evt.preventDefault(); - } - - const space = this.props.workspace; - - const name = space.filename.deref(); - - // TODO: these should transparently accept cursors for all non-function params - space.saveFile(name, space.current) - .tap(() => this.handleSuccess(`'${name}' saved successfully`)) - .catch(this.handleError); - }, - createFile: function(name){ - const { workspace, overlay, loadFile } = this.props; - - if(!name){ - return; - } - - workspace.filename.update(() => name); - workspace.current.update(() => ''); - // TODO: these should transparently accept cursors for all non-function params - workspace.saveFile(workspace.filename.deref(), workspace.current) - .tap(() => loadFile(name, () => this.handleSuccess(`'${name}' created successfully`))) - .catch(this.handleError) - .finally(overlay.hide); - }, deleteFile: function(name){ const space = this.props.workspace; const overlay = this.props.overlay; @@ -85,35 +56,6 @@ const FileOperations = React.createClass({ const overlay = this.props.overlay; overlay.hide(); }, - newFile: function() { - const { workspace } = this.props; - workspace.current.update(() => ''); - - const directory = workspace.directory.deref(); - const untitledFiles = directory.filter(x => { - return x.get('name').match(/untitled/); - }); - - console.log(untitledFiles); - untitledFiles.takeLast(x => { - console.log(x.get('name').match(/\d+/g)); - }); - - const numUntitled = 2; - - workspace.filename.update(() => `untitled${numUntitled}`); - }, - showCreateOverlay: function(evt){ - evt.preventDefault(); - - const component = ( - - ); - - this.renderOverlay(component); - }, showDeleteOverlay: function(evt){ evt.preventDefault(); @@ -150,13 +92,9 @@ const FileOperations = React.createClass({ this.renderOverlay(component); }, componentDidMount: function(){ - this.keySaveFile = app.keypress(app.keypress.CTRL_S, this.saveFile); this.keyCloseDialog = app.keypress(app.keypress.ESC, this.escapeDialog); }, componentWillUnmount: function(){ - if(this.keySaveFile) { - this.keySaveFile(); - } if(this.keyCloseDialog) { this.keyCloseDialog(); } @@ -176,11 +114,11 @@ const FileOperations = React.createClass({ icon="ion-backspace-outline" label="Delete File" /> diff --git a/plugins/sidebar/index.js b/plugins/sidebar/index.js index 92ab265..d941f3e 100644 --- a/plugins/sidebar/index.js +++ b/plugins/sidebar/index.js @@ -9,9 +9,13 @@ const File = require('./file'); const FileOperations = require('./file-operations'); const ProjectOperations = require('./project-operations'); +const NewFileOverlay = require('./overlays/new-file'); + const deviceStore = require('../../src/stores/device'); const editorStore = require('../../src/stores/editor'); +const fileStore = require('../../src/stores/file'); +const { processCreate, processSave } = require('../../src/actions/file'); function noop(){} function sidebar(app, opts, done){ @@ -24,14 +28,6 @@ function sidebar(app, opts, done){ const getBoard = app.getBoard.bind(irken); const scanBoards = app.scanBoards.bind(irken); - deviceStore.workspace = space; - deviceStore.toast = toast; - deviceStore.overlay = overlay; - deviceStore.getBoard = getBoard; - deviceStore.scanBoards = scanBoards; - - editorStore.workspace = space; - function refreshDirectory(){ // TODO: expose a method to refresh directory without changing it space.changeDir(space.cwd.deref()); @@ -45,8 +41,15 @@ function sidebar(app, opts, done){ }); chrome.syncFileSystem.onServiceStatusChanged.addListener(refreshDirectory); + // TODO: move to file store function loadFile(filename, cb = noop){ - if(filename){ + const previousFile = space.filename.deref(); + let unsaved = false; + if(previousFile) { + unsaved = _checkUnsaved(previousFile); + } + + if(filename && !unsaved){ space.loadFile(filename, (err) => { if(err){ cb(err); @@ -84,6 +87,75 @@ function sidebar(app, opts, done){ const lastFile = userConfig.get('last-file'); space.changeDir(cwd, () => loadFile(lastFile, done)); + + // Internal Helpers + function _checkUnsaved(file) { + const unnamed = space.directory.every(function(x) { + if(x.get('name') === file) { + return false; + } + else { + return true; + } + }); + if(unnamed) { + processSave(); + return true; + } + } + + function _onChangeFileStore() { + const { showSaveOverlay } = fileStore.getState(); + if (showSaveOverlay) { + _showCreateOverlay(); + } + } + + function _hideOverlay() { + overlay.hide(); + } + + function _renderOverlay(component){ + //const overlay = this.props.overlay; + + function renderer(el){ + React.render(component, el); + } + + overlay.render(renderer, { backdrop: true }); + } + + function _showCreateOverlay(){ + //evt.preventDefault(); + + const component = ( + + ); + + _renderOverlay(component); + } + + // Store bindings + deviceStore.workspace = space; + deviceStore.toast = toast; + deviceStore.overlay = overlay; + deviceStore.getBoard = getBoard; + deviceStore.scanBoards = scanBoards; + + editorStore.workspace = space; + + fileStore.workspace = space; + fileStore.userConfig = userConfig; + + fileStore.toast = toast; + fileStore.loadFile = loadFile; + fileStore.overlay = overlay; + + // Set up listeners + fileStore.listen(_onChangeFileStore); + } module.exports = sidebar; diff --git a/src/actions/file.js b/src/actions/file.js index c527304..d097a66 100644 --- a/src/actions/file.js +++ b/src/actions/file.js @@ -7,9 +7,22 @@ class FileActions { this.dispatch(); } + newFile() { + this.dispatch(); + } + + processCreate(name) { + this.dispatch(name); + } + + processSave() { + this.dispatch(); + } + updateName(value) { this.dispatch(value); } + } module.exports = alt.createActions(FileActions); diff --git a/src/stores/file.js b/src/stores/file.js index e7cdf83..62a5276 100644 --- a/src/stores/file.js +++ b/src/stores/file.js @@ -1,19 +1,26 @@ 'use strict'; const alt = require('../alt'); +const _ = require('lodash'); +const styles = require('../../plugins/sidebar/styles'); -const { clearName, updateName } = require('../actions/file'); +const { clearName, newFile, processCreate, + processSave, updateName } = require('../actions/file'); class FileStore { constructor() { this.bindListeners({ onClearName: clearName, + onNewFile: newFile, + onProcessCreate: processCreate, + onProcessSave: processSave, onUpdateName: updateName }); this.state = { - fileName: '' + fileName: '', + showSaveOverlay: false }; } @@ -24,12 +31,110 @@ class FileStore { }); } + onHideSave() { + this.setState({ + showSaveOverlay: false + }); + } + + onProcessCreate(name) { + const { loadFile, overlay, workspace } = this.getInstance(); + + if(!name){ + return; + } + + workspace.filename.update(() => name); + //workspace.current.update(() => ''); + // TODO: these should transparently accept cursors for all non-function params + workspace.saveFile(workspace.filename.deref(), workspace.current) + .tap(() => loadFile(name, () => this._handleSuccess(`'${name}' created successfully`))) + .catch(this._handleError) + .finally(overlay.hide); + + this.onHideSave(); + } + + onProcessSave() { + + const { workspace } = this.getInstance(); + + // TODO: reuse with checkUnsaved in sidebar index + const file = workspace.filename.deref(); + const unnamed = workspace.directory.every(function(x) { + if(x.get('name') === file) { + return false; + } + else { + return true; + } + }); + if(unnamed) { + this.setState({ + fileName: file, + showSaveOverlay: true + }); + } + else { + this.setState({ showSaveOverlay: false }); + this._save(); + } + } + + _save() { + const { workspace } = this.getInstance(); + + const name = workspace.filename.deref(); + + // TODO: these should transparently accept cursors for all non-function params + workspace.saveFile(name, workspace.current) + .tap(() => this._handleSuccess(`'${name}' saved successfully`)) + .catch(this._handleError); + } + + onNewFile() { + const { workspace, userConfig } = this.getInstance(); + workspace.current.update(() => ''); + + const directory = workspace.directory.deref(); + const untitledNums = directory.filter(x => { + return x.get('name').match(/untitled/); + }).map(x => { + const untitled = x.get('name').match(/\d+/); + if (untitled) { + return parseInt(untitled[0]); + } + }); + + const untitledLast = untitledNums.max() || 0; + const builtName = `untitled${untitledLast + 1}`; + + workspace.filename.update(() => builtName); + + userConfig.set('last-file', builtName); + } + onUpdateName(value) { this.setState({ fileName: value }); } + _handleError(err){ + // leaving this in for better debugging of errors + console.log(err); + const { toast } = this.getInstance(); + + toast.show(err.message, { style: styles.errorToast }); + } + + _handleSuccess(msg){ + const { toast } = this.getInstance(); + + toast.show(msg, { style: styles.successToast, timeout: 5000 }); + } + + } FileStore.config = { From bb106b5e435c0edf3b2827dd67258eed11e8a4b8 Mon Sep 17 00:00:00 2001 From: drquinn Date: Wed, 17 Jun 2015 17:27:44 -0700 Subject: [PATCH 3/8] Ctrl N function --- plugins/editor/key-extension.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/plugins/editor/key-extension.js b/plugins/editor/key-extension.js index dad5188..7a5493b 100644 --- a/plugins/editor/key-extension.js +++ b/plugins/editor/key-extension.js @@ -4,7 +4,7 @@ var { findNext, findPrevious } = require('../../src/actions/find'); var { moveByScrollUpLine, moveByScrollDownLine } = require('../../src/actions/editor-move'); var { indent } = require('../../src/actions/text-move'); var { print } = require('../../src/actions/system'); -var { processSave } = require('../../src/actions/file'); +var { newFile, processSave } = require('../../src/actions/file'); const keyExtension = { setup: function(app) { @@ -52,6 +52,13 @@ const keyExtension = { print(); } }, + newFile: { + code: 'CTRL_N', + exec: (evt) => { + evt.preventDefault(); + newFile(); + } + }, save: { code: 'CTRL_S', exec: (evt) => { @@ -61,10 +68,18 @@ const keyExtension = { } }; + const customPredicates = { + CTRL_N: function({ ctrlKey, metaKey, keyCode }){ + return ((ctrlKey === true || metaKey === true) && keyCode === 78); + } + }; + function setCodeMirrorCommands() { for (let cmd in cmCommands) { const code = cmCommands[cmd].code; - cmCommands[cmd].removeCode = app.keypress(app.keypress[code], cmCommands[cmd].exec); + const predicate = app.keypress[code] || customPredicates[code]; + console.log(code); + cmCommands[cmd].removeCode = app.keypress(predicate, cmCommands[cmd].exec); } } From fd787a478264e5233f8be2899b9b5f57ec231a37 Mon Sep 17 00:00:00 2001 From: drquinn Date: Wed, 17 Jun 2015 18:39:13 -0700 Subject: [PATCH 4/8] map/filter to reduce, remove console log, remove commented code --- plugins/editor/key-extension.js | 1 - plugins/sidebar/index.js | 14 +++++--------- src/stores/file.js | 21 +++++++++++---------- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/plugins/editor/key-extension.js b/plugins/editor/key-extension.js index 7a5493b..e8d5e2a 100644 --- a/plugins/editor/key-extension.js +++ b/plugins/editor/key-extension.js @@ -78,7 +78,6 @@ const keyExtension = { for (let cmd in cmCommands) { const code = cmCommands[cmd].code; const predicate = app.keypress[code] || customPredicates[code]; - console.log(code); cmCommands[cmd].removeCode = app.keypress(predicate, cmCommands[cmd].exec); } } diff --git a/plugins/sidebar/index.js b/plugins/sidebar/index.js index d941f3e..66a8c2b 100644 --- a/plugins/sidebar/index.js +++ b/plugins/sidebar/index.js @@ -83,11 +83,6 @@ function sidebar(app, opts, done){ React.render(Component, el, cb); }); - const cwd = userConfig.get('cwd') || opts.defaultProject; - const lastFile = userConfig.get('last-file'); - - space.changeDir(cwd, () => loadFile(lastFile, done)); - // Internal Helpers function _checkUnsaved(file) { const unnamed = space.directory.every(function(x) { @@ -116,8 +111,6 @@ function sidebar(app, opts, done){ } function _renderOverlay(component){ - //const overlay = this.props.overlay; - function renderer(el){ React.render(component, el); } @@ -126,8 +119,6 @@ function sidebar(app, opts, done){ } function _showCreateOverlay(){ - //evt.preventDefault(); - const component = ( loadFile(lastFile, done)); + } module.exports = sidebar; diff --git a/src/stores/file.js b/src/stores/file.js index 62a5276..fe9d370 100644 --- a/src/stores/file.js +++ b/src/stores/file.js @@ -45,7 +45,6 @@ class FileStore { } workspace.filename.update(() => name); - //workspace.current.update(() => ''); // TODO: these should transparently accept cursors for all non-function params workspace.saveFile(workspace.filename.deref(), workspace.current) .tap(() => loadFile(name, () => this._handleSuccess(`'${name}' created successfully`))) @@ -96,17 +95,19 @@ class FileStore { const { workspace, userConfig } = this.getInstance(); workspace.current.update(() => ''); - const directory = workspace.directory.deref(); - const untitledNums = directory.filter(x => { - return x.get('name').match(/untitled/); - }).map(x => { - const untitled = x.get('name').match(/\d+/); - if (untitled) { - return parseInt(untitled[0]); + const directory = workspace.directory.toJS(); + const untitledNums = _.reduce(directory, function(untitled, dirfile) { + if(dirfile.name.match(/untitled/)) { + const getnum = dirfile.name.match(/\d+/); + if (getnum) { + untitled.push(_.parseInt(getnum[0])); + } } - }); + return untitled; + }, [0]); + + const untitledLast = _.max(untitledNums); - const untitledLast = untitledNums.max() || 0; const builtName = `untitled${untitledLast + 1}`; workspace.filename.update(() => builtName); From 3d18c5544fd387b9599afa49fa3d458cfe353703 Mon Sep 17 00:00:00 2001 From: drquinn Date: Wed, 17 Jun 2015 18:42:17 -0700 Subject: [PATCH 5/8] require order --- src/stores/file.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stores/file.js b/src/stores/file.js index fe9d370..235f59d 100644 --- a/src/stores/file.js +++ b/src/stores/file.js @@ -1,7 +1,8 @@ 'use strict'; -const alt = require('../alt'); const _ = require('lodash'); + +const alt = require('../alt'); const styles = require('../../plugins/sidebar/styles'); const { clearName, newFile, processCreate, From 6b661b203fcd926481cd281b287801df370a1820 Mon Sep 17 00:00:00 2001 From: drquinn Date: Wed, 17 Jun 2015 19:40:42 -0700 Subject: [PATCH 6/8] fix for bug in delete. delete should create new file in the background --- plugins/editor/key-extension.js | 9 ++++++++- plugins/sidebar/file-operations.js | 25 ++++++------------------- src/actions/file.js | 8 ++++++++ src/stores/file.js | 28 +++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/plugins/editor/key-extension.js b/plugins/editor/key-extension.js index e8d5e2a..9c64bc1 100644 --- a/plugins/editor/key-extension.js +++ b/plugins/editor/key-extension.js @@ -4,7 +4,7 @@ var { findNext, findPrevious } = require('../../src/actions/find'); var { moveByScrollUpLine, moveByScrollDownLine } = require('../../src/actions/editor-move'); var { indent } = require('../../src/actions/text-move'); var { print } = require('../../src/actions/system'); -var { newFile, processSave } = require('../../src/actions/file'); +var { hideOverlay, newFile, processSave } = require('../../src/actions/file'); const keyExtension = { setup: function(app) { @@ -65,6 +65,13 @@ const keyExtension = { evt.preventDefault(); processSave(); } + }, + hideOverlay: { + code: 'ESC', + exec: (evt) => { + evt.preventDefault(); + hideOverlay(); + } } }; diff --git a/plugins/sidebar/file-operations.js b/plugins/sidebar/file-operations.js index dfeb7ad..b3d5220 100644 --- a/plugins/sidebar/file-operations.js +++ b/plugins/sidebar/file-operations.js @@ -9,7 +9,7 @@ const NewFileOverlay = require('./overlays/new-file'); const DownloadOverlay = require('./overlays/download'); const DeleteConfirmOverlay = require('./overlays/delete-confirm'); const { reloadDevices } = require('../../src/actions/device.js'); -const { clearName, newFile, processSave } = require('../../src/actions/file'); +const { clearName, deleteFile, newFile, processSave } = require('../../src/actions/file'); const styles = require('./styles'); @@ -26,19 +26,6 @@ const FileOperations = React.createClass({ toast.show(msg, { style: styles.successToast, timeout: 5000 }); }, - deleteFile: function(name){ - const space = this.props.workspace; - const overlay = this.props.overlay; - - if(!name){ - return; - } - - space.deleteFile(space.filename) - .tap(() => this.handleSuccess(`'${name}' deleted successfully`)) - .catch(this.handleError) - .finally(overlay.hide); - }, escapeDialog: function() { this.hideOverlay(); clearName(); @@ -70,7 +57,7 @@ const FileOperations = React.createClass({ const component = ( ); @@ -92,12 +79,12 @@ const FileOperations = React.createClass({ this.renderOverlay(component); }, componentDidMount: function(){ - this.keyCloseDialog = app.keypress(app.keypress.ESC, this.escapeDialog); + //this.keyCloseDialog = app.keypress(app.keypress.ESC, this.escapeDialog); }, componentWillUnmount: function(){ - if(this.keyCloseDialog) { - this.keyCloseDialog(); - } + //if(this.keyCloseDialog) { + //this.keyCloseDialog(); + //} }, render: function(){ return ( diff --git a/src/actions/file.js b/src/actions/file.js index d097a66..e677da3 100644 --- a/src/actions/file.js +++ b/src/actions/file.js @@ -7,6 +7,14 @@ class FileActions { this.dispatch(); } + deleteFile(name) { + this.dispatch(name); + } + + hideOverlay() { + this.dispatch(); + } + newFile() { this.dispatch(); } diff --git a/src/stores/file.js b/src/stores/file.js index 235f59d..3429d2a 100644 --- a/src/stores/file.js +++ b/src/stores/file.js @@ -5,7 +5,7 @@ const _ = require('lodash'); const alt = require('../alt'); const styles = require('../../plugins/sidebar/styles'); -const { clearName, newFile, processCreate, +const { clearName, deleteFile, hideOverlay, newFile, processCreate, processSave, updateName } = require('../actions/file'); class FileStore { @@ -13,6 +13,8 @@ class FileStore { this.bindListeners({ onClearName: clearName, + onDeleteFile: deleteFile, + onHideOverlay: hideOverlay, onNewFile: newFile, onProcessCreate: processCreate, onProcessSave: processSave, @@ -32,12 +34,35 @@ class FileStore { }); } + onDeleteFile(name) { + const { overlay, workspace } = this.getInstance(); + + if(!name){ + return; + } + + workspace.deleteFile(workspace.filename) + .tap(() => this._handleSuccess(`'${name}' deleted successfully`)) + .catch(this._handleError) + .finally(() => { + overlay.hide(); + this.onNewFile(); + }); + + } + onHideSave() { this.setState({ showSaveOverlay: false }); } + onHideOverlay() { + const { overlay } = this.getInstance(); + overlay.hide(); + this.onClearName(); + } + onProcessCreate(name) { const { loadFile, overlay, workspace } = this.getInstance(); @@ -112,6 +137,7 @@ class FileStore { const builtName = `untitled${untitledLast + 1}`; workspace.filename.update(() => builtName); + console.log('here, builtName', builtName); userConfig.set('last-file', builtName); } From 79a5d5b3e14d174b3c8c6e5106d415d7f7e29df0 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Wed, 17 Jun 2015 20:05:13 -0700 Subject: [PATCH 7/8] cleanup and fix new file on startup bug --- plugins/sidebar/file-operations.js | 22 +++------------------- plugins/sidebar/index.js | 11 +++++++++-- src/stores/file.js | 3 +-- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/plugins/sidebar/file-operations.js b/plugins/sidebar/file-operations.js index b3d5220..65ad545 100644 --- a/plugins/sidebar/file-operations.js +++ b/plugins/sidebar/file-operations.js @@ -9,7 +9,7 @@ const NewFileOverlay = require('./overlays/new-file'); const DownloadOverlay = require('./overlays/download'); const DeleteConfirmOverlay = require('./overlays/delete-confirm'); const { reloadDevices } = require('../../src/actions/device.js'); -const { clearName, deleteFile, newFile, processSave } = require('../../src/actions/file'); +const { clearName, deleteFile, newFile, processSave, hideOverlay } = require('../../src/actions/file'); const styles = require('./styles'); @@ -26,10 +26,6 @@ const FileOperations = React.createClass({ toast.show(msg, { style: styles.successToast, timeout: 5000 }); }, - escapeDialog: function() { - this.hideOverlay(); - clearName(); - }, renderOverlay: function(component){ const overlay = this.props.overlay; @@ -39,10 +35,6 @@ const FileOperations = React.createClass({ overlay.render(renderer, { backdrop: true }); }, - hideOverlay: function(){ - const overlay = this.props.overlay; - overlay.hide(); - }, showDeleteOverlay: function(evt){ evt.preventDefault(); @@ -58,7 +50,7 @@ const FileOperations = React.createClass({ + onCancel={hideOverlay} /> ); this.renderOverlay(component); @@ -70,7 +62,7 @@ const FileOperations = React.createClass({ const component = ( @@ -78,14 +70,6 @@ const FileOperations = React.createClass({ this.renderOverlay(component); }, - componentDidMount: function(){ - //this.keyCloseDialog = app.keypress(app.keypress.ESC, this.escapeDialog); - }, - componentWillUnmount: function(){ - //if(this.keyCloseDialog) { - //this.keyCloseDialog(); - //} - }, render: function(){ return ( diff --git a/plugins/sidebar/index.js b/plugins/sidebar/index.js index 66a8c2b..7ffad60 100644 --- a/plugins/sidebar/index.js +++ b/plugins/sidebar/index.js @@ -15,7 +15,7 @@ const deviceStore = require('../../src/stores/device'); const editorStore = require('../../src/stores/editor'); const fileStore = require('../../src/stores/file'); -const { processCreate, processSave } = require('../../src/actions/file'); +const { processCreate, processSave, newFile } = require('../../src/actions/file'); function noop(){} function sidebar(app, opts, done){ @@ -150,7 +150,14 @@ function sidebar(app, opts, done){ // Finish Loading Plugin const cwd = userConfig.get('cwd') || opts.defaultProject; const lastFile = userConfig.get('last-file'); - space.changeDir(cwd, () => loadFile(lastFile, done)); + console.log(lastFile); + space.changeDir(cwd, () => loadFile(lastFile, (err) => { + if(err){ + newFile(); + } + + done(); + })); } diff --git a/src/stores/file.js b/src/stores/file.js index 3429d2a..5886f8d 100644 --- a/src/stores/file.js +++ b/src/stores/file.js @@ -119,7 +119,6 @@ class FileStore { onNewFile() { const { workspace, userConfig } = this.getInstance(); - workspace.current.update(() => ''); const directory = workspace.directory.toJS(); const untitledNums = _.reduce(directory, function(untitled, dirfile) { @@ -137,7 +136,7 @@ class FileStore { const builtName = `untitled${untitledLast + 1}`; workspace.filename.update(() => builtName); - console.log('here, builtName', builtName); + workspace.updateContent(''); userConfig.set('last-file', builtName); } From b1775cdee3409c23222ed292cc71e3f474253a70 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Thu, 18 Jun 2015 12:55:58 -0700 Subject: [PATCH 8/8] lots of behavior fixes and cleanup --- plugins/sidebar/index.js | 59 ++------------- plugins/sidebar/overlays/new-file.js | 13 ++-- src/actions/file.js | 8 +++ src/stores/file.js | 104 +++++++++++++++++++-------- 4 files changed, 95 insertions(+), 89 deletions(-) diff --git a/plugins/sidebar/index.js b/plugins/sidebar/index.js index 7ffad60..1fe1dae 100644 --- a/plugins/sidebar/index.js +++ b/plugins/sidebar/index.js @@ -15,7 +15,7 @@ const deviceStore = require('../../src/stores/device'); const editorStore = require('../../src/stores/editor'); const fileStore = require('../../src/stores/file'); -const { processCreate, processSave, newFile } = require('../../src/actions/file'); +const { processCreate, processNoCreate, processSave, newFile, loadFile } = require('../../src/actions/file'); function noop(){} function sidebar(app, opts, done){ @@ -41,30 +41,6 @@ function sidebar(app, opts, done){ }); chrome.syncFileSystem.onServiceStatusChanged.addListener(refreshDirectory); - // TODO: move to file store - function loadFile(filename, cb = noop){ - const previousFile = space.filename.deref(); - let unsaved = false; - if(previousFile) { - unsaved = _checkUnsaved(previousFile); - } - - if(filename && !unsaved){ - space.loadFile(filename, (err) => { - if(err){ - cb(err); - return; - } - - userConfig.set('last-file', filename); - - cb(); - }); - } else { - cb(); - } - } - app.view('sidebar', function(el, cb){ console.log('sidebar render'); const directory = space.directory; @@ -84,32 +60,16 @@ function sidebar(app, opts, done){ }); // Internal Helpers - function _checkUnsaved(file) { - const unnamed = space.directory.every(function(x) { - if(x.get('name') === file) { - return false; - } - else { - return true; - } - }); - if(unnamed) { - processSave(); - return true; - } - } function _onChangeFileStore() { const { showSaveOverlay } = fileStore.getState(); if (showSaveOverlay) { _showCreateOverlay(); + } else { + overlay.hide(); } } - function _hideOverlay() { - overlay.hide(); - } - function _renderOverlay(component){ function renderer(el){ React.render(component, el); @@ -122,7 +82,7 @@ function sidebar(app, opts, done){ const component = ( + onCancel={processNoCreate} /> ); _renderOverlay(component); @@ -141,8 +101,6 @@ function sidebar(app, opts, done){ fileStore.userConfig = userConfig; fileStore.toast = toast; - fileStore.loadFile = loadFile; - fileStore.overlay = overlay; // Set up listeners fileStore.listen(_onChangeFileStore); @@ -151,13 +109,10 @@ function sidebar(app, opts, done){ const cwd = userConfig.get('cwd') || opts.defaultProject; const lastFile = userConfig.get('last-file'); console.log(lastFile); - space.changeDir(cwd, () => loadFile(lastFile, (err) => { - if(err){ - newFile(); - } - + space.changeDir(cwd, () => { + loadFile(lastFile); done(); - })); + }); } diff --git a/plugins/sidebar/overlays/new-file.js b/plugins/sidebar/overlays/new-file.js index 5a74c4c..7c12564 100644 --- a/plugins/sidebar/overlays/new-file.js +++ b/plugins/sidebar/overlays/new-file.js @@ -33,7 +33,7 @@ class NewFileOverlay extends React.Component { return ( -

Please name your file.

+

Do you want to save the changes you made to New file?

- - + + +
); @@ -54,16 +55,16 @@ class NewFileOverlay extends React.Component { clearName(); if(typeof onAccept === 'function'){ - onAccept(fileName, evt); + onAccept(fileName); } } - _onCancel(evt){ + _onCancel(status, evt){ const { onCancel } = this.props; clearName(); if(typeof onCancel === 'function'){ - onCancel(evt); + onCancel(status); } } diff --git a/src/actions/file.js b/src/actions/file.js index e677da3..bb383f9 100644 --- a/src/actions/file.js +++ b/src/actions/file.js @@ -19,10 +19,18 @@ class FileActions { this.dispatch(); } + loadFile(filename){ + this.dispatch(filename); + } + processCreate(name) { this.dispatch(name); } + processNoCreate(status){ + this.dispatch(status); + } + processSave() { this.dispatch(); } diff --git a/src/stores/file.js b/src/stores/file.js index 5886f8d..da6d858 100644 --- a/src/stores/file.js +++ b/src/stores/file.js @@ -6,7 +6,7 @@ const alt = require('../alt'); const styles = require('../../plugins/sidebar/styles'); const { clearName, deleteFile, hideOverlay, newFile, processCreate, - processSave, updateName } = require('../actions/file'); + processNoCreate, processSave, updateName, loadFile } = require('../actions/file'); class FileStore { constructor() { @@ -16,6 +16,8 @@ class FileStore { onDeleteFile: deleteFile, onHideOverlay: hideOverlay, onNewFile: newFile, + onLoadFile: loadFile, + onProcessNoCreate: processNoCreate, onProcessCreate: processCreate, onProcessSave: processSave, onUpdateName: updateName @@ -23,19 +25,28 @@ class FileStore { this.state = { fileName: '', + isNewFile: false, showSaveOverlay: false }; + this.loadQueue = []; } onClearName() { + const { workspace } = this.getInstance(); this.setState({ - fileName: '' + fileName: workspace.filename.deref() + }); + } + + onUpdateName(value) { + this.setState({ + fileName: value }); } onDeleteFile(name) { - const { overlay, workspace } = this.getInstance(); + const { workspace } = this.getInstance(); if(!name){ return; @@ -45,7 +56,7 @@ class FileStore { .tap(() => this._handleSuccess(`'${name}' deleted successfully`)) .catch(this._handleError) .finally(() => { - overlay.hide(); + this.setState({ showSaveOverlay: false }); this.onNewFile(); }); @@ -58,13 +69,12 @@ class FileStore { } onHideOverlay() { - const { overlay } = this.getInstance(); - overlay.hide(); + this.setState({ showSaveOverlay: false }); this.onClearName(); } onProcessCreate(name) { - const { loadFile, overlay, workspace } = this.getInstance(); + const { loadFile, workspace } = this.getInstance(); if(!name){ return; @@ -73,34 +83,36 @@ class FileStore { workspace.filename.update(() => name); // TODO: these should transparently accept cursors for all non-function params workspace.saveFile(workspace.filename.deref(), workspace.current) - .tap(() => loadFile(name, () => this._handleSuccess(`'${name}' created successfully`))) + .tap(() => { + this.setState({ isNewFile: false }); + if(this.loadQueue.length){ + this.onLoadFile(this.loadQueue.shift()); + } + }) + .tap(() => this._handleSuccess(`'${name}' created successfully`)) .catch(this._handleError) - .finally(overlay.hide); + .finally(() => this.setState({ showSaveOverlay: false })); this.onHideSave(); } - onProcessSave() { - - const { workspace } = this.getInstance(); - - // TODO: reuse with checkUnsaved in sidebar index - const file = workspace.filename.deref(); - const unnamed = workspace.directory.every(function(x) { - if(x.get('name') === file) { - return false; - } - else { - return true; + onProcessNoCreate(status){ + if(status.trash){ + this.setState({ isNewFile: false, showSaveOverlay: false }); + if(this.loadQueue.length){ + this.onLoadFile(this.loadQueue.shift()); } - }); - if(unnamed) { - this.setState({ - fileName: file, - showSaveOverlay: true - }); + } else { + this.setState({ showSaveOverlay: false }); } - else { + } + + onProcessSave() { + const { isNewFile } = this.state; + + if(isNewFile) { + this.setState({ showSaveOverlay: true }); + } else { this.setState({ showSaveOverlay: false }); this._save(); } @@ -139,11 +151,41 @@ class FileStore { workspace.updateContent(''); userConfig.set('last-file', builtName); - } - onUpdateName(value) { this.setState({ - fileName: value + fileName: builtName, + isNewFile: true + }); + } + + _queueLoad(filename){ + this.loadQueue.push(filename); + } + + onLoadFile(filename){ + const { workspace, userConfig } = this.getInstance(); + const { isNewFile } = this.state; + + const content = workspace.current.deref(); + + if(isNewFile && content.length){ + this._queueLoad(filename); + this.onProcessSave(); + return; + } + + workspace.loadFile(filename, (err) => { + if(err){ + this._handleError(err); + return; + } + + userConfig.set('last-file', filename); + + this.setState({ + fileName: filename, + isNewFile: false + }); }); }