diff --git a/src/preferences/PreferenceStorage.js b/src/preferences/PreferenceStorage.js index 202ca36f407..eb1e50f4f83 100644 --- a/src/preferences/PreferenceStorage.js +++ b/src/preferences/PreferenceStorage.js @@ -27,6 +27,8 @@ /** * PreferenceStorage defines an interface for persisting preference data as * name/value pairs for a module or plugin. + * + * @deprecated Use PreferencesManager APIs instead. */ define(function (require, exports, module) { "use strict"; diff --git a/src/preferences/PreferencesBase.js b/src/preferences/PreferencesBase.js index 14e9ce3178c..2a4ba5b118d 100644 --- a/src/preferences/PreferencesBase.js +++ b/src/preferences/PreferencesBase.js @@ -115,9 +115,9 @@ define(function (require, exports, module) { /** * MemoryStorage is not stored in a file, so fileChanged is ignored. * - * @param {string} filename File that has changed + * @param {string} filePath File that has changed */ - fileChanged: function (filename) { + fileChanged: function (filePath) { } }; @@ -241,10 +241,10 @@ define(function (require, exports, module) { /** * If the filename matches this Storage's path, a changed message is triggered. * - * @param {string} filename File that has changed + * @param {string} filePath File that has changed */ - fileChanged: function (filename) { - if (filename === this.path) { + fileChanged: function (filePath) { + if (filePath === this.path) { $(this).trigger("changed"); } } @@ -485,10 +485,10 @@ define(function (require, exports, module) { * Tells the Scope that the given file has been changed so that the * Storage can be reloaded if needed. * - * @param {string} filename Name of the file that has changed + * @param {string} filePath File that has changed */ - fileChanged: function (filename) { - this.storage.fileChanged(filename); + fileChanged: function (filePath) { + this.storage.fileChanged(filePath); }, /** @@ -1693,11 +1693,11 @@ define(function (require, exports, module) { * Tells the PreferencesSystem that the given file has been changed so that any * related Scopes can be reloaded. * - * @param {string} filename Name of the file that has changed + * @param {string} filePath File that has changed */ - fileChanged: function (filename) { + fileChanged: function (filePath) { _.forEach(this._scopes, function (scope) { - scope.fileChanged(filename); + scope.fileChanged(filePath); }); }, diff --git a/src/preferences/PreferencesImpl.js b/src/preferences/PreferencesImpl.js index 42fbc95c2ef..0ade1df22a9 100644 --- a/src/preferences/PreferencesImpl.js +++ b/src/preferences/PreferencesImpl.js @@ -32,6 +32,7 @@ define(function (require, exports, module) { "use strict"; var PreferencesBase = require("./PreferencesBase"), + ProjectManager = require("project/ProjectManager"), Async = require("utils/Async"), // The SETTINGS_FILENAME is used with a preceding "." within user projects @@ -103,6 +104,7 @@ define(function (require, exports, module) { }); }); + // "State" is stored like preferences but it is not generally intended to be user-editable. // It's for more internal, implicit things like window size, working set, etc. var stateManager = new PreferencesBase.PreferencesSystem(); @@ -112,6 +114,18 @@ define(function (require, exports, module) { smUserScope.addLayer(stateProjectLayer); var smUserScopeLoading = stateManager.addScope("user", smUserScope); + + // Listen for times where we might be unwatching a root that contains one of the user-level prefs files, + // and force a re-read of the file in order to ensure we can write to it later (see #7300). + $(ProjectManager).on("projectClose", function (event, rootDir) { + var prefsDir = brackets.app.getApplicationSupportDirectory() + "/"; + if (prefsDir.indexOf(rootDir.fullPath) === 0) { + manager.fileChanged(userPrefFile); + stateManager.fileChanged(userStateFile); + } + }); + + // Semi-Public API. Use this at your own risk. The public API is in PreferencesManager. exports.manager = manager; exports.projectStorage = projectStorage; diff --git a/src/project/ProjectManager.js b/src/project/ProjectManager.js index 929f7588b2c..f1d623a14bd 100644 --- a/src/project/ProjectManager.js +++ b/src/project/ProjectManager.js @@ -30,7 +30,8 @@ * the file tree. * * This module dispatches these events: - * - beforeProjectClose -- before _projectRoot changes + * - beforeProjectClose -- before _projectRoot changes, but working set files still open + * - projectClose -- *just* before _projectRoot changes; working set already cleared & project root unwatched * - beforeAppClose -- before Brackets quits entirely * - projectOpen -- after _projectRoot changes and the tree is re-rendered * - projectRefresh -- when project tree is re-rendered for a reason other than @@ -159,6 +160,7 @@ define(function (require, exports, module) { /** * @private * @see getProjectRoot() + * @type {Directory} */ var _projectRoot = null; @@ -674,15 +676,15 @@ define(function (require, exports, module) { var events = $._data(_projectTree[0], "events"), eventsForType = events ? events[type] : null, event = eventsForType ? _.find(eventsForType, function (e) { - return e.namespace === namespace && e.selector === selector; - }) : null, + return e.namespace === namespace && e.selector === selector; + }) : null, eventHandler = event ? event.handler : null; if (!eventHandler) { console.error(type + "." + namespace + " " + selector + " handler not found!"); } return eventHandler; }; - var createCustomHandler = function(originalHandler) { + var createCustomHandler = function (originalHandler) { return function (event) { var $node = $(event.target).parent("li"), methodName; @@ -1102,8 +1104,9 @@ define(function (require, exports, module) { if (_projectRoot && _projectRoot.fullPath === rootPath) { return (new $.Deferred()).resolve().promise(); } + + // About to close current project (if any) if (_projectRoot) { - // close current project $(exports).triggerHandler("beforeProjectClose", _projectRoot); } @@ -1111,6 +1114,11 @@ define(function (require, exports, module) { DocumentManager.closeAll(); _unwatchProjectRoot().always(function () { + // Done closing old project (if any) + if (_projectRoot) { + $(exports).triggerHandler("projectClose", _projectRoot); + } + startLoad.resolve(); }); }