kopia lustrzana https://github.com/c9/core
Merge pull request +14781 from c9/gui-fixes
Refactor watcher gui to stop so many prompts in standalone modepull/358/head
commit
0c248c596d
|
@ -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);
|
||||||
|
|
Ładowanie…
Reference in New Issue