-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmain.js
161 lines (144 loc) · 5.56 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, $, brackets, window */
/**
* Autosaves all files when leaving Brackets, in the style of PHPStorm/WebStorm.
*
* The functions are essentially copied from document/DocumentCommandHandlers.js. The only
* modification is a check if the current document in the loop is untitled (i.e. hasn't
* been saved to a permanent disk location). If it is, don't bother trying to save it.
*/
define(function() {
'use strict';
/** Unique token used to indicate user-driven cancellation of Save As (as opposed to file IO error) */
var USER_CANCELED = { userCanceled: true };
/** Namespaced name of this module */
var MODULE_NAME = 'martypenner.autosave-files-on-window-blur';
/** Name of the preference used to store whether we're enabled or not */
var PREF_NAME = MODULE_NAME + '.enabled';
/** Name the command package-style to avoid collisions */
var ENABLE_COMMAND_ID = PREF_NAME;
var AppInit = require('utils/AppInit'),
CommandManager = require('command/CommandManager'),
Commands = require('command/Commands'),
DocumentManager = require('document/DocumentManager'),
MainViewManager = require('view/MainViewManager'),
Async = require('utils/Async'),
PreferencesManager = require('preferences/PreferencesManager'),
Menus = require('command/Menus');
var prefs = PreferencesManager.getExtensionPrefs(MODULE_NAME);
/**
* Saves all unsaved documents. Returns a Promise that will be resolved once ALL the save
* operations have been completed. If ANY save operation fails, an error dialog is immediately
* shown but after dismissing we continue saving the other files; after all files have been
* processed, the Promise is rejected if any ONE save operation failed (the error given is the
* first one encountered). If the user cancels any Save As dialog (for untitled files), the
* Promise is immediately rejected.
*
* @param {!Array.<File>} fileList
* @return {!$.Promise} Resolved with {!Array.<File>}, which may differ from 'fileList'
* if any of the files were Unsaved documents. Or rejected with {?FileSystemError}.
* @private
*/
function _saveFileList(fileList) {
// Do in serial because doSave shows error UI for each file, and we don't want to stack
// multiple dialogs on top of each other
var userCanceled = false,
filesAfterSave = [];
return Async.doSequentially(
fileList,
function(file) {
// Abort remaining saves if user canceled any Save As dialog
if (userCanceled) {
return new $.Deferred().reject().promise();
}
var doc = DocumentManager.getOpenDocumentForPath(file.fullPath);
if (doc && !doc.isUntitled()) {
var savePromise = CommandManager.execute(Commands.FILE_SAVE, { doc: doc });
savePromise
.done(function(newFile) {
filesAfterSave.push(newFile);
})
.fail(function(error) {
if (error === USER_CANCELED) {
userCanceled = true;
}
});
return savePromise;
} else {
// working set entry that was never actually opened - ignore
filesAfterSave.push(file);
return new $.Deferred().resolve().promise();
}
},
false // if any save fails, continue trying to save other files anyway; then reject at end
).then(function() {
return filesAfterSave;
});
}
/**
* Save all changed (but not untitled) documents when Brackets loses focus
*
* @private
*/
function _blurHandler() {
_saveFileList(MainViewManager.getWorkingSet(MainViewManager.ALL_PANES));
}
/**
* Add/remove event listeners for the window blur event
*
* @param {boolean} preference
* @private
*/
function _setupEventListeners(preference) {
if (!preference) {
$(window).off('blur', _blurHandler);
} else {
$(window).on('blur', _blurHandler);
}
}
/**
* Create a function that will toggle the named preference.
*
* @param {string} prefName Name of preference that should be toggled by the function
* @private
*/
function _getToggler(prefName) {
return function() {
var newPreference = !PreferencesManager.get(prefName);
PreferencesManager.set(prefName, newPreference);
_updateCheckedState(newPreference);
_setupEventListeners(newPreference);
};
}
/**
* Update the command checked status based on the preference name given.
*
* @param {boolean} isChecked Whether to set the menu item to enabled or not
* @private
*/
function _updateCheckedState(isChecked) {
CommandManager.get(ENABLE_COMMAND_ID).setChecked(isChecked);
}
/**
* Kick things off.
*
* @private
*/
function _init() {
prefs.definePreference(PREF_NAME, 'boolean', true);
prefs.on('change', function() {
// This gets the current value of "enabled" where current means for the
// file being edited right now.
_updateCheckedState(prefs.get(PREF_NAME));
});
prefs.save();
// First, register a command - a UI-less object associating an id to a handler
CommandManager.register('Enable Autosave On Window Blur', ENABLE_COMMAND_ID, _getToggler(PREF_NAME));
var menu = Menus.getMenu(Menus.AppMenuBar.EDIT_MENU);
// Add the menu item and keyboard shortcut
// (Note: "Ctrl" is automatically mapped to "Cmd" on Mac)
menu.addMenuItem(ENABLE_COMMAND_ID, 'Ctrl-Alt-Shift-W');
_setupEventListeners(prefs.get(PREF_NAME));
}
AppInit.htmlReady(_init);
});