Skip to content

Commit f7bb39c

Browse files
committed
Merge pull request #156 from parallaxinc/fileNewBehavior
File new behavior
2 parents d0b6458 + b1775cd commit f7bb39c

File tree

6 files changed

+305
-115
lines changed

6 files changed

+305
-115
lines changed

plugins/editor/key-extension.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ var { findNext, findPrevious } = require('../../src/actions/find');
44
var { moveByScrollUpLine, moveByScrollDownLine } = require('../../src/actions/editor-move');
55
var { indent } = require('../../src/actions/text-move');
66
var { print } = require('../../src/actions/system');
7+
var { hideOverlay, newFile, processSave } = require('../../src/actions/file');
78

89
const keyExtension = {
910
setup: function(app) {
@@ -50,13 +51,41 @@ const keyExtension = {
5051
evt.preventDefault();
5152
print();
5253
}
54+
},
55+
newFile: {
56+
code: 'CTRL_N',
57+
exec: (evt) => {
58+
evt.preventDefault();
59+
newFile();
60+
}
61+
},
62+
save: {
63+
code: 'CTRL_S',
64+
exec: (evt) => {
65+
evt.preventDefault();
66+
processSave();
67+
}
68+
},
69+
hideOverlay: {
70+
code: 'ESC',
71+
exec: (evt) => {
72+
evt.preventDefault();
73+
hideOverlay();
74+
}
5375
}
5476
};
5577

78+
const customPredicates = {
79+
CTRL_N: function({ ctrlKey, metaKey, keyCode }){
80+
return ((ctrlKey === true || metaKey === true) && keyCode === 78);
81+
}
82+
};
83+
5684
function setCodeMirrorCommands() {
5785
for (let cmd in cmCommands) {
5886
const code = cmCommands[cmd].code;
59-
cmCommands[cmd].removeCode = app.keypress(app.keypress[code], cmCommands[cmd].exec);
87+
const predicate = app.keypress[code] || customPredicates[code];
88+
cmCommands[cmd].removeCode = app.keypress(predicate, cmCommands[cmd].exec);
6089
}
6190
}
6291

plugins/sidebar/file-operations.js

Lines changed: 6 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const NewFileOverlay = require('./overlays/new-file');
99
const DownloadOverlay = require('./overlays/download');
1010
const DeleteConfirmOverlay = require('./overlays/delete-confirm');
1111
const { reloadDevices } = require('../../src/actions/device.js');
12-
const { clearName } = require('../../src/actions/file');
12+
const { clearName, deleteFile, newFile, processSave, hideOverlay } = require('../../src/actions/file');
1313

1414
const styles = require('./styles');
1515

@@ -26,52 +26,6 @@ const FileOperations = React.createClass({
2626

2727
toast.show(msg, { style: styles.successToast, timeout: 5000 });
2828
},
29-
saveFile: function(evt){
30-
if(evt){
31-
evt.preventDefault();
32-
}
33-
34-
const space = this.props.workspace;
35-
36-
const name = space.filename.deref();
37-
38-
// TODO: these should transparently accept cursors for all non-function params
39-
space.saveFile(name, space.current)
40-
.tap(() => this.handleSuccess(`'${name}' saved successfully`))
41-
.catch(this.handleError);
42-
},
43-
createFile: function(name){
44-
const { workspace, overlay, loadFile } = this.props;
45-
46-
if(!name){
47-
return;
48-
}
49-
50-
workspace.filename.update(() => name);
51-
workspace.current.update(() => '');
52-
// TODO: these should transparently accept cursors for all non-function params
53-
workspace.saveFile(workspace.filename.deref(), workspace.current)
54-
.tap(() => loadFile(name, () => this.handleSuccess(`'${name}' created successfully`)))
55-
.catch(this.handleError)
56-
.finally(overlay.hide);
57-
},
58-
deleteFile: function(name){
59-
const space = this.props.workspace;
60-
const overlay = this.props.overlay;
61-
62-
if(!name){
63-
return;
64-
}
65-
66-
space.deleteFile(space.filename)
67-
.tap(() => this.handleSuccess(`'${name}' deleted successfully`))
68-
.catch(this.handleError)
69-
.finally(overlay.hide);
70-
},
71-
escapeDialog: function() {
72-
this.hideOverlay();
73-
clearName();
74-
},
7529
renderOverlay: function(component){
7630
const overlay = this.props.overlay;
7731

@@ -81,21 +35,6 @@ const FileOperations = React.createClass({
8135

8236
overlay.render(renderer, { backdrop: true });
8337
},
84-
hideOverlay: function(){
85-
const overlay = this.props.overlay;
86-
overlay.hide();
87-
},
88-
showCreateOverlay: function(evt){
89-
evt.preventDefault();
90-
91-
const component = (
92-
<NewFileOverlay
93-
onAccept={this.createFile}
94-
onCancel={this.hideOverlay} />
95-
);
96-
97-
this.renderOverlay(component);
98-
},
9938
showDeleteOverlay: function(evt){
10039
evt.preventDefault();
10140

@@ -110,8 +49,8 @@ const FileOperations = React.createClass({
11049
const component = (
11150
<DeleteConfirmOverlay
11251
name={name}
113-
onAccept={this.deleteFile}
114-
onCancel={this.hideOverlay} />
52+
onAccept={deleteFile}
53+
onCancel={hideOverlay} />
11554
);
11655

11756
this.renderOverlay(component);
@@ -123,26 +62,14 @@ const FileOperations = React.createClass({
12362

12463
const component = (
12564
<DownloadOverlay
126-
onCancel={this.hideOverlay}
65+
onCancel={hideOverlay}
12766
irken={this.props.irken}
12867
handleSuccess={this.handleSuccess}
12968
handleError={this.handleError} />
13069
);
13170

13271
this.renderOverlay(component);
13372
},
134-
componentDidMount: function(){
135-
this.keySaveFile = app.keypress(app.keypress.CTRL_S, this.saveFile);
136-
this.keyCloseDialog = app.keypress(app.keypress.ESC, this.escapeDialog);
137-
},
138-
componentWillUnmount: function(){
139-
if(this.keySaveFile) {
140-
this.keySaveFile();
141-
}
142-
if(this.keyCloseDialog) {
143-
this.keyCloseDialog();
144-
}
145-
},
14673
render: function(){
14774
return (
14875
<Menu effect="zoomin" method="click" position="bl">
@@ -158,11 +85,11 @@ const FileOperations = React.createClass({
15885
icon="ion-backspace-outline"
15986
label="Delete File" />
16087
<ChildButton
161-
onClick={this.saveFile}
88+
onClick={processSave}
16289
icon="ion-compose"
16390
label="Save File" />
16491
<ChildButton
165-
onClick={this.showCreateOverlay}
92+
onClick={newFile}
16693
icon="ion-document"
16794
label="New File" />
16895
</Menu>

plugins/sidebar/index.js

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ const File = require('./file');
99
const FileOperations = require('./file-operations');
1010
const ProjectOperations = require('./project-operations');
1111

12+
const NewFileOverlay = require('./overlays/new-file');
13+
1214
const deviceStore = require('../../src/stores/device');
1315
const editorStore = require('../../src/stores/editor');
16+
const fileStore = require('../../src/stores/file');
1417

18+
const { processCreate, processNoCreate, processSave, newFile, loadFile } = require('../../src/actions/file');
1519
function noop(){}
1620

1721
function sidebar(app, opts, done){
@@ -24,14 +28,6 @@ function sidebar(app, opts, done){
2428
const getBoard = app.getBoard.bind(irken);
2529
const scanBoards = app.scanBoards.bind(irken);
2630

27-
deviceStore.workspace = space;
28-
deviceStore.toast = toast;
29-
deviceStore.overlay = overlay;
30-
deviceStore.getBoard = getBoard;
31-
deviceStore.scanBoards = scanBoards;
32-
33-
editorStore.workspace = space;
34-
3531
function refreshDirectory(){
3632
// TODO: expose a method to refresh directory without changing it
3733
space.changeDir(space.cwd.deref());
@@ -45,23 +41,6 @@ function sidebar(app, opts, done){
4541
});
4642
chrome.syncFileSystem.onServiceStatusChanged.addListener(refreshDirectory);
4743

48-
function loadFile(filename, cb = noop){
49-
if(filename){
50-
space.loadFile(filename, (err) => {
51-
if(err){
52-
cb(err);
53-
return;
54-
}
55-
56-
userConfig.set('last-file', filename);
57-
58-
cb();
59-
});
60-
} else {
61-
cb();
62-
}
63-
}
64-
6544
app.view('sidebar', function(el, cb){
6645
console.log('sidebar render');
6746
const directory = space.directory;
@@ -80,10 +59,61 @@ function sidebar(app, opts, done){
8059
React.render(Component, el, cb);
8160
});
8261

62+
// Internal Helpers
63+
64+
function _onChangeFileStore() {
65+
const { showSaveOverlay } = fileStore.getState();
66+
if (showSaveOverlay) {
67+
_showCreateOverlay();
68+
} else {
69+
overlay.hide();
70+
}
71+
}
72+
73+
function _renderOverlay(component){
74+
function renderer(el){
75+
React.render(component, el);
76+
}
77+
78+
overlay.render(renderer, { backdrop: true });
79+
}
80+
81+
function _showCreateOverlay(){
82+
const component = (
83+
<NewFileOverlay
84+
onAccept={processCreate}
85+
onCancel={processNoCreate} />
86+
);
87+
88+
_renderOverlay(component);
89+
}
90+
91+
// Store bindings
92+
deviceStore.workspace = space;
93+
deviceStore.toast = toast;
94+
deviceStore.overlay = overlay;
95+
deviceStore.getBoard = getBoard;
96+
deviceStore.scanBoards = scanBoards;
97+
98+
editorStore.workspace = space;
99+
100+
fileStore.workspace = space;
101+
fileStore.userConfig = userConfig;
102+
103+
fileStore.toast = toast;
104+
105+
// Set up listeners
106+
fileStore.listen(_onChangeFileStore);
107+
108+
// Finish Loading Plugin
83109
const cwd = userConfig.get('cwd') || opts.defaultProject;
84110
const lastFile = userConfig.get('last-file');
111+
console.log(lastFile);
112+
space.changeDir(cwd, () => {
113+
loadFile(lastFile);
114+
done();
115+
});
85116

86-
space.changeDir(cwd, () => loadFile(lastFile, done));
87117
}
88118

89119
module.exports = sidebar;

plugins/sidebar/overlays/new-file.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class NewFileOverlay extends React.Component {
3333

3434
return (
3535
<Card styles={styles.overlay}>
36-
<h3 style={styles.overlayTitle}>Please name your file.</h3>
36+
<h3 style={styles.overlayTitle}>Do you want to save the changes you made to New file?</h3>
3737
<TextField
3838
value={fileName}
3939
ref="filename"
@@ -42,8 +42,9 @@ class NewFileOverlay extends React.Component {
4242
floatingLabel
4343
onChange={this._onUpdateName} />
4444
<div style={styles.overlayButtonContainer}>
45-
<Button onClick={this._onAccept}>Create</Button>
46-
<Button onClick={this._onCancel}>Cancel</Button>
45+
<Button onClick={this._onAccept}>Save As</Button>
46+
<Button onClick={() => this._onCancel({ trash: true })}>Don't Save</Button>
47+
<Button onClick={() => this._onCancel({ trash: false })}>Cancel</Button>
4748
</div>
4849
</Card>
4950
);
@@ -54,16 +55,16 @@ class NewFileOverlay extends React.Component {
5455

5556
clearName();
5657
if(typeof onAccept === 'function'){
57-
onAccept(fileName, evt);
58+
onAccept(fileName);
5859
}
5960
}
6061

61-
_onCancel(evt){
62+
_onCancel(status, evt){
6263
const { onCancel } = this.props;
6364

6465
clearName();
6566
if(typeof onCancel === 'function'){
66-
onCancel(evt);
67+
onCancel(status);
6768
}
6869
}
6970

src/actions/file.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,38 @@ class FileActions {
77
this.dispatch();
88
}
99

10+
deleteFile(name) {
11+
this.dispatch(name);
12+
}
13+
14+
hideOverlay() {
15+
this.dispatch();
16+
}
17+
18+
newFile() {
19+
this.dispatch();
20+
}
21+
22+
loadFile(filename){
23+
this.dispatch(filename);
24+
}
25+
26+
processCreate(name) {
27+
this.dispatch(name);
28+
}
29+
30+
processNoCreate(status){
31+
this.dispatch(status);
32+
}
33+
34+
processSave() {
35+
this.dispatch();
36+
}
37+
1038
updateName(value) {
1139
this.dispatch(value);
1240
}
41+
1342
}
1443

1544
module.exports = alt.createActions(FileActions);

0 commit comments

Comments
 (0)