Merge pull request +14781 from c9/gui-fixes

Refactor watcher gui to stop so many prompts in standalone mode
pull/358/head
Tim Robinson 2016-09-14 15:57:19 +02:00 zatwierdzone przez GitHub
commit 0c248c596d
1 zmienionych plików z 136 dodań i 158 usunięć

Wyświetl plik

@ -82,31 +82,23 @@ define(function(require, exports, module) {
}, plugin); }, plugin);
} }
tabManager.getTabs().forEach(function(tab) { function initializeTab(tab) {
if (!tab.path) if (!tab.path) return;
return;
if (tab.document.undoManager.isAtBookmark()) { if (tab.document.undoManager.isAtBookmark()) {
initializeDocument(tab.document); initializeDocument(tab.document);
} }
else {
console.error("Unsupported state");
}
if (tab.classList.contains("conflict")) { if (tab.classList.contains("conflict")) {
addChangedTab(tab, comparisonType.TIMESTAMP_AND_CONTENTS); addChangedTab(tab, comparisonType.TIMESTAMP_AND_CONTENTS);
} }
});
tabManager.on("open", function(e) {
initializeDocument(e.tab.document);
if (e.tab.classList.contains("conflict")) {
addChangedTab(e.tab, comparisonType.TIMESTAMP_AND_CONTENTS);
} }
tabManager.getTabs().forEach(initializeTab);
tabManager.on("open", function(e) {
initializeTab(e.tab);
}, plugin); }, plugin);
// Hook the save of the document value // Hook the save of the document value
save.on("beforeSave", function(e) { save.on("beforeSave", function(e) {
e.document.meta.$savingValue = e.save; e.document.meta.$savingValue = e.save;
if (e.tab.classList.contains("conflict")) { if (e.tab.classList.contains("conflict")) {
@ -178,6 +170,17 @@ define(function(require, exports, module) {
delete changedPaths[path]; delete changedPaths[path];
} }
function resolve(doc, path) {
if (collabEnabled && collab.send)
collab.send({type: "RESOLVE_CONFLICT", data: {docId: path}});
resolveConflict(doc, path);
}
function isTabSaving(tab) {
return !!tab.document.meta.$saving;
}
function addChangedTab(tab, doubleCheckComparisonType) { function addChangedTab(tab, doubleCheckComparisonType) {
// If we already have a dialog open, just update it, but mark the value dirty // If we already have a dialog open, just update it, but mark the value dirty
if (changedPaths[tab.path]) { if (changedPaths[tab.path]) {
@ -188,101 +191,83 @@ define(function(require, exports, module) {
} }
// Ignore changes that come in while tab is being saved // Ignore changes that come in while tab is being saved
if (tab.document.meta.$saving) { if (isTabSaving(tab)) return;
console.log("[watchers] Watcher fired, but tab is still saving", path);
return;
}
var doc = tab.document;
var path = tab.path;
changedPaths[tab.path] = { tab: tab, resolve: resolve };
// If the terminal is currently focussed, lets wait until // If the terminal is currently focussed, lets wait until
// another tab is focussed // another tab is focussed
if (tabManager.focussedTab if (tabManager.focussedTab && tabManager.focussedTab.editorType == "terminal") {
&& tabManager.focussedTab.editorType == "terminal") {
tabManager.once("focus", function(){ tabManager.once("focus", function(){
addChangedTab(tab, comparisonType.CONTENTS); addChangedTab(tab, comparisonType.CONTENTS);
}); });
return; return;
} }
function resolve() { var doc = tab.document;
if (collabEnabled && collab.send) var path = tab.path;
collab.send({type: "RESOLVE_CONFLICT", data: {docId: path}});
resolveConflict(doc, path); changedPaths[tab.path] = { tab: tab, resolve: resolve.bind(null, doc, path) };
}
switch (doubleCheckComparisonType) { switch (doubleCheckComparisonType) {
case comparisonType.TIMESTAMP_AND_CONTENTS: case comparisonType.TIMESTAMP_AND_CONTENTS:
checkByStatOrContents(); checkByStatOrContents(tab);
break; break;
case comparisonType.CONTENTS: case comparisonType.CONTENTS:
checkByContents(); checkByContents(tab);
break; break;
case comparisonType.NONE: case comparisonType.NONE:
dialog(); showChangeDialog(tab);
break; break;
} }
}
function createChangeDialog(tab, data) {
var doc = tab.document;
var path = tab.path;
function dialog(data) {
if (!changedPaths[path]) if (!changedPaths[path])
return; return;
changedPaths[path].data = data || changedPaths[path].data; changedPaths[path].data = data || changedPaths[path].data;
if (changeDialog) {
// The dialog is visible
if (changeDialog.visible === 1) {
question.all = true;
return;
}
// The dialog still is to become visible
else if (changeDialog.visible === undefined) {
changeDialog.on("show", function(){
question.all = true;
});
return;
}
}
if (tabManager.focussedTab && !changedPaths[tabManager.focussedTab.path]) { if (tabManager.focussedTab && !changedPaths[tabManager.focussedTab.path]) {
doc.tab.classList.add("conflict"); doc.tab.classList.add("conflict");
// Let's try again later, maybe then one of our paths gets focus // Let's try again later, maybe then one of our paths gets focus
return tabManager.once("focus", function() { tabManager.once("focus", function() {
dialog(); showChangeDialog(tab, data);
}); });
return;
} }
if (!tabManager.findTab(path)) // drat! tab is gone if (!tabManager.findTab(path)) // drat! tab is gone
return; return;
// Show dialogs for changed tabs // Show dialogs for changed tab
for (var changedPath in changedPaths) {
tab = changedPaths[changedPath].tab;
data = changedPaths[changedPath].data;
showChangeDialog(tab, data); showChangeDialog(tab, data);
} }
}
function checkByStatOrContents() { function checkByStatOrContents(tab) {
var doc = tab.document;
var path = tab.path;
fs.stat(path, function(err, stat) { fs.stat(path, function(err, stat) {
if (!err && doc.meta.timestamp >= stat.mtime) if (!err && doc.meta.timestamp >= stat.mtime)
return resolve(); return resolve(doc, path);
checkByContents(stat); checkByContents(tab, stat);
}); });
} }
function checkByContents(stat) { function checkByContents(tab, stat) {
var doc = tab.document;
var path = tab.path;
fs.readFile(path, function(err, data) { fs.readFile(path, function(err, data) {
if (err) { if (err) {
console.warn("[watchers] Could not read", path, "will assume it got changed"); console.warn("[watchers] Could not read", path, "will assume it got changed");
return dialog(); return createChangeDialog(tab);
} }
// false alarm. File content didn't change // false alarm. File content didn't change
if (data === doc.meta.$savedValue) if (data === doc.meta.$savedValue)
return resolve(); return resolve(doc, path);
// Store base value for merges // Store base value for merges
if (doc.meta.$mergeRoot == undefined) if (doc.meta.$mergeRoot == undefined)
@ -299,7 +284,7 @@ define(function(require, exports, module) {
doc.undoManager.bookmark(); doc.undoManager.bookmark();
// Mark as resolved // Mark as resolved
resolve(); resolve(doc, path);
return; return;
} else { } else {
@ -311,12 +296,11 @@ define(function(require, exports, module) {
} }
if (automerge(tab, data)) if (automerge(tab, data))
resolve(); resolve(doc, path);
else else
dialog(data); createChangeDialog(tab, data);
}); });
} }
}
function automerge(tab, data) { function automerge(tab, data) {
if (!settings.getBool("user/general/@automerge")) if (!settings.getBool("user/general/@automerge"))
@ -368,8 +352,8 @@ define(function(require, exports, module) {
var doc = tab.document; var doc = tab.document;
doc.setBookmarkedValue(data, true); doc.setBookmarkedValue(data, true);
doc.meta.timestamp = Date.now() - settings.timeOffset; doc.meta.timestamp = Date.now() - settings.timeOffset;
save.save(tab);
changedPaths[path].resolve(); changedPaths[path].resolve();
save.save(tab);
} }
function mergeChangedPath(err, path, data) { function mergeChangedPath(err, path, data) {
@ -380,13 +364,19 @@ define(function(require, exports, module) {
function showChangeDialog(tab, data) { function showChangeDialog(tab, data) {
var path, merge; var path, merge;
if (!tab) { if (changeDialog) {
for (path in changedPaths) { // The dialog is visible
tab = changedPaths[path].tab; if (changeDialog.visible === 1) {
data = changedPaths[path].data; question.all = true;
break; return;
}
// The dialog still is to become visible
else if (changeDialog.visible === undefined) {
changeDialog.on("show", function(){
question.all = true;
});
return;
} }
if (!tab) return;
} }
path = tab.path; path = tab.path;
@ -404,7 +394,7 @@ define(function(require, exports, module) {
changedPaths[path].tab.document.undoManager.bookmark(-2); changedPaths[path].tab.document.undoManager.bookmark(-2);
changedPaths[path].resolve(); changedPaths[path].resolve();
} }
checkEmptyQueue(); checkIfQueueIsEmpty();
} }
function yes(all) { // Remote | Yes function yes(all) { // Remote | Yes
@ -414,12 +404,10 @@ define(function(require, exports, module) {
} }
} }
else { else {
getLatestValue(path, function(err, path, data) { getLatestValue(path, updateChangedPath);
updateChangedPath(err, path, data);
});
} }
checkEmptyQueue(); checkIfQueueIsEmpty();
} }
if (merge) { if (merge) {
@ -439,13 +427,10 @@ define(function(require, exports, module) {
} }
else { else {
askAutoMerge(); askAutoMerge();
getLatestValue(path, mergeChangedPath);
getLatestValue(path, function(err, path, data) {
mergeChangedPath(err, path, data);
});
} }
checkEmptyQueue(); checkIfQueueIsEmpty();
}, },
{ {
merge: true, merge: true,
@ -487,7 +472,7 @@ define(function(require, exports, module) {
fs.stat(tab.path, function(err, data) { fs.stat(tab.path, function(err, data) {
if (err && err.code === "ENOENT") { if (err && err.code === "ENOENT") {
removedPaths[tab.path] = tab; removedPaths[tab.path] = {tab: tab};
if (deleteDialog) { if (deleteDialog) {
// The dialog is visible // The dialog is visible
@ -517,16 +502,7 @@ define(function(require, exports, module) {
} }
function showDeleteDialog(tab) { function showDeleteDialog(tab) {
var path; var path = tab.path;
if (!tab) {
for (path in removedPaths) {
tab = removedPaths[path];
break;
}
if (!tab) return;
}
path = tab.path;
deleteDialog = question.show( deleteDialog = question.show(
"File removed, keep tab open?", "File removed, keep tab open?",
@ -537,36 +513,34 @@ define(function(require, exports, module) {
if (all) { if (all) {
for (var id in removedPaths) { for (var id in removedPaths) {
doc = removedPaths[id].document; doc = removedPaths[id].tab.document;
doc.undoManager.bookmark(-2); doc.undoManager.bookmark(-2);
doc.meta.newfile = true; doc.meta.newfile = true;
} }
removedPaths = {}; removedPaths = {};
} }
else { else {
doc = removedPaths[path].document; doc = removedPaths[path].tab.document;
doc.undoManager.bookmark(-2); doc.undoManager.bookmark(-2);
doc.meta.newfile = true; doc.meta.newfile = true;
delete removedPaths[path]; delete removedPaths[path];
showDeleteDialog();
} }
checkEmptyQueue(); checkIfQueueIsEmpty();
}, },
function(all, cancel) { // No function(all, cancel) { // No
if (all) { if (all) {
for (var id in removedPaths) { for (var id in removedPaths) {
closeTab(removedPaths[id], true); closeTab(removedPaths[id].tab, true);
} }
removedPaths = {}; removedPaths = {};
} }
else { else {
closeTab(removedPaths[path]); closeTab(removedPaths[path].tab);
delete removedPaths[path]; delete removedPaths[path];
showDeleteDialog();
} }
checkEmptyQueue(); checkIfQueueIsEmpty();
}, },
{ all: Object.keys(removedPaths).length > 1 } { all: Object.keys(removedPaths).length > 1 }
); );
@ -583,9 +557,13 @@ define(function(require, exports, module) {
tabManager.focusTab(tab); tabManager.focusTab(tab);
} }
function checkEmptyQueue(){ function checkIfQueueIsEmpty(){
for (var prop in changedPaths) return; for (var path in changedPaths) {
for (var prop in removedPaths) return; return showChangeDialog(changedPaths[path].tab, changedPaths[path].data);
}
for (var path in removedPaths) {
return showDeleteDialog(removedPaths[path].tab);
};
if (initialFocus) { if (initialFocus) {
tabManager.focusTab(initialFocus); tabManager.focusTab(initialFocus);