kopia lustrzana https://github.com/c9/core
reimplement autosave after dalay option in collab-friendly way
rodzic
7c23e8e7ac
commit
2ca11b2d7d
|
@ -14,16 +14,20 @@ define(function(require, exports, module) {
|
|||
var Plugin = imports.Plugin;
|
||||
var settings = imports.settings;
|
||||
|
||||
var lang = require("ace/lib/lang");
|
||||
|
||||
/***** Initialization *****/
|
||||
|
||||
var plugin = new Plugin("Ajax.org", main.consumes);
|
||||
|
||||
var CHANGE_TIMEOUT = 500;
|
||||
var CHANGE_TIMEOUT = options.changeTimeout || 1000;
|
||||
var SLOW_CHANGE_TIMEOUT = options.slowChangeTimeout || 30000;
|
||||
var SLOW_SAVE_THRESHOLD = 100 * 1024; // 100KB
|
||||
|
||||
var docChangeTimeout;
|
||||
var lastSaveTime = 0;
|
||||
var sessionId;
|
||||
var autosave;
|
||||
var saveWhenIdle;
|
||||
|
||||
function load() {
|
||||
prefs.add({
|
||||
|
@ -31,10 +35,16 @@ define(function(require, exports, module) {
|
|||
position: 150,
|
||||
"Save": {
|
||||
position: 100,
|
||||
"Enable Auto-Save On Blur": {
|
||||
type: "checkbox",
|
||||
"Auto-Save Files": {
|
||||
type: "dropdown",
|
||||
position: 100,
|
||||
path: "user/general/@autosave"
|
||||
path: "user/general/@autosave",
|
||||
width: 130,
|
||||
items: [
|
||||
{ caption: "Off", value: false },
|
||||
{ caption: "On Focus Change", value: "onFocusChange" },
|
||||
{ caption: "After Delay", value: "afterDelay" },
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,25 +62,69 @@ define(function(require, exports, module) {
|
|||
/***** Helpers *****/
|
||||
|
||||
function onSettingChange() {
|
||||
autosave = settings.getBool("user/general/@autosave");
|
||||
autosave = settings.get("user/general/@autosave");
|
||||
if (autosave == "off" || autosave == "false")
|
||||
autosave = false;
|
||||
|
||||
disable();
|
||||
if (autosave == "afterDelay")
|
||||
enableDelay();
|
||||
if (autosave)
|
||||
enable();
|
||||
else
|
||||
disable();
|
||||
}
|
||||
|
||||
function enableDelay() {
|
||||
saveWhenIdle = lang.delayedCall(function() {
|
||||
var tab = tabs.focussedTab;
|
||||
var ace = tab && tab.editor && tab.editor.ace;
|
||||
if (ace && ace.session && sessionId == ace.session.id) {
|
||||
saveTab(tab);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function enable() {
|
||||
apf.on("movefocus", scheduleCheck);
|
||||
tabs.on("tabAfterActivate", scheduleCheck, plugin);
|
||||
if (saveWhenIdle)
|
||||
tabs.on("focusSync", attachToTab, plugin);
|
||||
window.addEventListener("blur", scheduleCheck);
|
||||
}
|
||||
|
||||
function disable() {
|
||||
sessionId = null;
|
||||
if (saveWhenIdle) {
|
||||
saveWhenIdle.cancel();
|
||||
saveWhenIdle = null;
|
||||
}
|
||||
if (docChangeTimeout) {
|
||||
clearTimeout(docChangeTimeout);
|
||||
docChangeTimeout = null;
|
||||
}
|
||||
apf.off("movefocus", scheduleCheck);
|
||||
tabs.off("tabAfterActivate", scheduleCheck);
|
||||
tabs.off("focusSync", attachToTab);
|
||||
window.removeEventListener("blur", scheduleCheck);
|
||||
}
|
||||
|
||||
function attachToTab(e) {
|
||||
var ace = e.tab && e.tab.editor && e.tab.editor.ace;
|
||||
if (ace)
|
||||
ace.on("beforeEndOperation", beforeEndOperation);
|
||||
}
|
||||
|
||||
function beforeEndOperation(e, ace) {
|
||||
if (!saveWhenIdle)
|
||||
return ace.off("beforeEndOperation", beforeEndOperation);
|
||||
if (!ace.isFocused() && !options.ignoreFocusForTesting)
|
||||
return;
|
||||
sessionId = ace.session.id;
|
||||
if (sessionId && ace.curOp.docChanged && ace.curOp.command.name) {
|
||||
var timeout = Math.min(Math.max(CHANGE_TIMEOUT, lastSaveTime || 0), SLOW_CHANGE_TIMEOUT);
|
||||
saveWhenIdle.delay(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleCheck(e) {
|
||||
if (docChangeTimeout)
|
||||
return;
|
||||
|
@ -117,11 +171,6 @@ define(function(require, exports, module) {
|
|||
function saveTab(tab, force) {
|
||||
if (!autosave) return;
|
||||
|
||||
if (!c9.has(c9.STORAGE)) {
|
||||
save.setSavingState(tab, "offline");
|
||||
return;
|
||||
}
|
||||
|
||||
var doc;
|
||||
if (!force && (!tab.path
|
||||
|| !(doc = tab.document).changed
|
||||
|
@ -132,10 +181,19 @@ define(function(require, exports, module) {
|
|||
|| doc.meta.preview
|
||||
|| !doc.hasValue()))
|
||||
return;
|
||||
|
||||
if (!c9.has(c9.STORAGE)) {
|
||||
save.setSavingState(tab, "offline");
|
||||
return;
|
||||
}
|
||||
|
||||
var t = Date.now();
|
||||
save.save(tab, {
|
||||
silentsave: true,
|
||||
}, function() {});
|
||||
noUi: true,
|
||||
}, function() {
|
||||
lastSaveTime = t - Date.now();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -146,12 +204,8 @@ define(function(require, exports, module) {
|
|||
load();
|
||||
});
|
||||
plugin.on("unload", function() {
|
||||
window.removeEventListener("blur", scheduleCheck);
|
||||
disable();
|
||||
autosave = false;
|
||||
if (docChangeTimeout) {
|
||||
clearTimeout(docChangeTimeout);
|
||||
docChangeTimeout = null;
|
||||
}
|
||||
});
|
||||
|
||||
/***** Register and define API *****/
|
||||
|
|
|
@ -46,6 +46,8 @@ require(["lib/chai/chai"], function (chai) {
|
|||
"plugins/c9.ide.save/save",
|
||||
{
|
||||
packagePath: "plugins/c9.ide.save/autosave",
|
||||
ignoreFocusForTesting: true,
|
||||
changeTimeout: 5,
|
||||
},
|
||||
{
|
||||
packagePath: "plugins/c9.vfs.client/vfs_client_mock",
|
||||
|
@ -175,6 +177,30 @@ require(["lib/chai/chai"], function (chai) {
|
|||
});
|
||||
});
|
||||
|
||||
it("should automatically save after delay", function(done) {
|
||||
settings.set("user/general/@autosave", "afterDelay");
|
||||
var path = "/autosave2.txt";
|
||||
createAndChangeTab(path, function(tab) {
|
||||
expect(tab.document.changed).to.ok;
|
||||
|
||||
setTimeout(function() {
|
||||
expect(tab.document.changed).to.ok;
|
||||
tab.editor.ace.execCommand("insertstring", "x");
|
||||
}, 10);
|
||||
save.once("afterSave", function() {
|
||||
fs.readFile(path, function(err, data) {
|
||||
if (err) throw err;
|
||||
expect(data).to.equal("testx" + path);
|
||||
expect(tab.document.changed).to.not.ok;
|
||||
|
||||
fs.unlink(path, function() {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if (!onload.remain) {
|
||||
describe("unload()", function() {
|
||||
it('should destroy all ui elements when it is unloaded', function(done) {
|
||||
|
|
|
@ -412,7 +412,7 @@ define(function(require, exports, module) {
|
|||
doc.meta.$saveBuffer = true;
|
||||
}
|
||||
|
||||
setSavingState(tab, "saving");
|
||||
setSavingState(tab, "saving", null, options.noUi);
|
||||
|
||||
var bookmark = doc.undoManager.position;
|
||||
var loadStartT = Date.now();
|
||||
|
@ -450,7 +450,7 @@ define(function(require, exports, module) {
|
|||
if (options.path)
|
||||
tab.path = options.path;
|
||||
|
||||
setSavingState(tab, "saved", options.timeout);
|
||||
setSavingState(tab, "saved", options.timeout, options.noUi);
|
||||
settings.save();
|
||||
logger.log("Successfully saved " + path);
|
||||
}
|
||||
|
@ -541,7 +541,7 @@ define(function(require, exports, module) {
|
|||
}
|
||||
|
||||
var stateTimer = null, pageTimers = {};
|
||||
function setSavingState(tab, state, timeout) {
|
||||
function setSavingState(tab, state, timeout, silent) {
|
||||
clearTimeout(stateTimer);
|
||||
clearTimeout(pageTimers[tab.name]);
|
||||
|
||||
|
@ -554,6 +554,12 @@ define(function(require, exports, module) {
|
|||
else
|
||||
delete doc.meta.$saving;
|
||||
|
||||
if (!silent)
|
||||
updateSavingUi();
|
||||
emit("tabSavingState", { tab: tab });
|
||||
}
|
||||
|
||||
function updateSavingUi(tab, state, timeout) {
|
||||
if (state == "saving") {
|
||||
btnSave.show();
|
||||
|
||||
|
@ -621,7 +627,6 @@ define(function(require, exports, module) {
|
|||
btnSave.setCaption("Not saved");
|
||||
tab.classList.add("error");
|
||||
}
|
||||
emit("tabSavingState", { tab: tab });
|
||||
}
|
||||
|
||||
/***** Lifecycle *****/
|
||||
|
|
Ładowanie…
Reference in New Issue