Bug 1039484 - Prevent closing WebIDE or switch to a new project if any file hasn't been saved. r=paul

This commit is contained in:
Brian Grinstead 2014-08-13 13:35:00 -04:00
parent c9bb9a8cf5
commit fc1838f306
8 changed files with 125 additions and 6 deletions

View File

@ -155,7 +155,7 @@ var TextEditor = Class({
if (!this.editor.isAppended()) {
return true;
}
return this.editor.isClean();
return this.editor.getText() === this._savedResourceContents;
},
initialize: function(document, mode=Editor.modes.text) {
@ -212,6 +212,7 @@ var TextEditor = Class({
if (!this.editor) {
return;
}
this._savedResourceContents = resourceContents;
this.editor.setText(resourceContents);
this.editor.clearHistory();
this.editor.setClean();
@ -229,8 +230,9 @@ var TextEditor = Class({
* saved.
*/
save: function(resource) {
return resource.save(this.editor.getText()).then(() => {
this.editor.setClean();
let newText = this.editor.getText();
return resource.save(newText).then(() => {
this._savedResourceContents = newText;
this.emit("save", resource);
});
},

View File

@ -31,7 +31,12 @@ var DirtyPlugin = Class({
},
onAnnotate: function(resource, editor, elt) {
if (editor && editor.editor && !editor.editor.isClean()) {
// Only run on a TextEditor
if (!editor || !editor.editor) {
return;
}
if (!editor.isClean()) {
elt.textContent = '*' + resource.displayName;
return true;
}

View File

@ -20,6 +20,8 @@ const { ViewHelpers } = Cu.import("resource:///modules/devtools/ViewHelpers.jsm"
const { DOMHelpers } = Cu.import("resource:///modules/devtools/DOMHelpers.jsm");
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
const ITCHPAD_URL = "chrome://browser/content/devtools/projecteditor.xul";
const { confirm } = require("projecteditor/helpers/prompts");
const { getLocalizedString } = require("projecteditor/helpers/l10n");
// Enabled Plugins
require("projecteditor/plugins/dirty/dirty");
@ -728,7 +730,37 @@ var ProjectEditor = Class({
get menuEnabled() {
return this._menuEnabled;
},
/**
* Are there any unsaved resources in the Project?
*/
get hasUnsavedResources() {
return this.project.allResources().some(resource=> {
let editor = this.editorFor(resource);
return editor && !editor.isClean();
});
},
/**
* Check with the user about navigating away with unsaved changes.
*
* @returns Boolean
* True if there are no unsaved changes
* Otherwise, ask the user to confirm and return the outcome.
*/
confirmUnsaved: function() {
if (this.hasUnsavedResources) {
return confirm(
getLocalizedString("projecteditor.confirmUnsavedTitle"),
getLocalizedString("projecteditor.confirmUnsavedLabel")
);
}
return true;
}
});

View File

@ -7,6 +7,7 @@ support-files =
[browser_projecteditor_app_options.js]
skip-if = buildapp == 'mulet'
[browser_projecteditor_confirm_unsaved.js]
[browser_projecteditor_contextmenu_01.js]
[browser_projecteditor_contextmenu_02.js]
[browser_projecteditor_delete_file.js]

View File

@ -0,0 +1,60 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
loadHelperScript("helper_edits.js");
// Test that a prompt shows up when requested if a file is unsaved.
let test = asyncTest(function*() {
let projecteditor = yield addProjectEditorTabForTempDirectory();
ok(true, "ProjectEditor has loaded");
let resources = projecteditor.project.allResources();
yield selectFile(projecteditor, resources[2]);
let editor = projecteditor.currentEditor;
let originalText = editor.editor.getText();
ok (!projecteditor.hasUnsavedResources, "There are no unsaved resources");
ok (projecteditor.confirmUnsaved(), "When there are no unsaved changes, confirmUnsaved() is true");
editor.editor.setText("bar");
editor.editor.setText(originalText);
ok (!projecteditor.hasUnsavedResources, "There are no unsaved resources");
ok (projecteditor.confirmUnsaved(), "When an editor has changed but is still the original text, confirmUnsaved() is true");
editor.editor.setText("bar");
checkConfirmYes(projecteditor);
checkConfirmNo(projecteditor);
});
function checkConfirmYes(projecteditor, container) {
function confirmYes(aSubject) {
info("confirm dialog observed as expected, going to click OK");
Services.obs.removeObserver(confirmYes, "common-dialog-loaded");
Services.obs.removeObserver(confirmYes, "tabmodal-dialog-loaded");
aSubject.Dialog.ui.button0.click();
}
Services.obs.addObserver(confirmYes, "common-dialog-loaded", false);
Services.obs.addObserver(confirmYes, "tabmodal-dialog-loaded", false);
ok (projecteditor.hasUnsavedResources, "There are unsaved resources");
ok (projecteditor.confirmUnsaved(), "When there are unsaved changes, clicking OK makes confirmUnsaved() true");
}
function checkConfirmNo(projecteditor, container) {
function confirmNo(aSubject) {
info("confirm dialog observed as expected, going to click cancel");
Services.obs.removeObserver(confirmNo, "common-dialog-loaded");
Services.obs.removeObserver(confirmNo, "tabmodal-dialog-loaded");
aSubject.Dialog.ui.button1.click();
}
Services.obs.addObserver(confirmNo, "common-dialog-loaded", false);
Services.obs.addObserver(confirmNo, "tabmodal-dialog-loaded", false);
ok (projecteditor.hasUnsavedResources, "There are unsaved resources");
ok (!projecteditor.confirmUnsaved(), "When there are unsaved changes, clicking cancel makes confirmUnsaved() false");
}

View File

@ -100,6 +100,13 @@ let UI = {
window.removeEventListener("message", this.onMessage);
},
canWindowClose: function() {
if (this.projecteditor) {
return this.projecteditor.confirmUnsaved();
}
return true;
},
onfocus: function() {
// Because we can't track the activity in the folder project,
// we need to validate the project regularly. Let's assume that
@ -665,7 +672,9 @@ let UI = {
let Cmds = {
quit: function() {
window.close();
if (UI.canWindowClose()) {
window.close();
}
},
/**

View File

@ -14,7 +14,7 @@
<?xml-stylesheet href="chrome://global/skin/global.css"?>
<?xml-stylesheet href="chrome://webide/skin/webide.css"?>
<window id="webide"
<window id="webide" onclose="return UI.canWindowClose();"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
title="&windowTitle;"

View File

@ -11,6 +11,16 @@
# A good criteria is the language in which you'd find the best
# documentation on web development on the web.
# LOCALIZATION NOTE (projecteditor.confirmUnsavedTitle):
# This string is displayed as as the title of the confirm prompt that checks
# to make sure if the project editor can be closed without saving changes
projecteditor.confirmUnsavedTitle=Unsaved Changes
# LOCALIZATION NOTE (projecteditor.confirmUnsavedLabel):
# This string is displayed as the message of the confirm prompt that checks
# to make sure if the project editor can be closed without saving changes
projecteditor.confirmUnsavedLabel=You have unsaved changes that will be lost if you exit. Are you sure you want to continue?
# LOCALIZATION NOTE (projecteditor.deleteLabel):
# This string is displayed as a context menu item for allowing the selected
# file / folder to be deleted.