From a01bbd4b9c7ca284141078340c8f568b1e0561a2 Mon Sep 17 00:00:00 2001 From: Jermolene Date: Thu, 6 Feb 2014 21:36:30 +0000 Subject: [PATCH] Add automatic saving and warning on exit with unsaved changes We re-use some of the existing syncer mechanism. It was already keeping track of changes to tiddlers in the store when working with a tiddler syncadaptor. Now it also tracks changes when there is no syncadaptor, allowing us to provide a warning if there are unsaved changes. --- core/modules/startup.js | 16 +- core/modules/syncer.js | 188 +++++++++++++----- core/modules/widgets/navigator.js | 7 +- core/modules/wiki.js | 56 ------ core/ui/ControlPanel/Saving.tid | 5 + core/wiki/autosavestatus.tid | 10 + core/wiki/config/AutoSave.tid | 3 + core/wiki/config/SyncFilter.tid | 3 + editions/clientserver/tiddlers/AutoSave.tid | 11 + editions/clientserver/tiddlywiki.info | 5 - editions/codemirrordemo/tiddlywiki.info | 2 - editions/d3demo/tiddlywiki.info | 6 - editions/highlightdemo/tiddlywiki.info | 2 - editions/markdowndemo/tiddlywiki.info | 2 - editions/tw5.com/tiddlers/GettingStarted.tid | 2 +- .../tw5.com/tiddlers/Release 5.0.8beta.tid | 5 +- .../tiddlers/concepts/TiddlyWikiFolders.tid | 8 +- editions/tw5.com/tiddlers/roadmap/RoadMap.tid | 6 +- .../filesystem/filesystemadaptor.js | 53 ++--- 19 files changed, 216 insertions(+), 174 deletions(-) create mode 100644 core/wiki/autosavestatus.tid create mode 100644 core/wiki/config/AutoSave.tid create mode 100644 core/wiki/config/SyncFilter.tid create mode 100644 editions/clientserver/tiddlers/AutoSave.tid diff --git a/core/modules/startup.js b/core/modules/startup.js index 0b39d2212..84b3c1486 100755 --- a/core/modules/startup.js +++ b/core/modules/startup.js @@ -56,6 +56,15 @@ exports.startup = function() { $tw.wiki.addTiddler({title: storyTitle, text: "", list: story},$tw.wiki.getModificationFields()); // Host-specific startup if($tw.browser) { + // Set up our beforeunload handler + window.addEventListener("beforeunload",function(event) { + var confirmationMessage = null; + if($tw.syncer.isDirty()) { + confirmationMessage = "You have unsaved changes in TiddlyWiki"; + event.returnValue = confirmationMessage; // Gecko + } + return confirmationMessage; // Webkit, Safari, Chrome etc. + }); // Install the popup manager $tw.popup = new $tw.utils.Popup({ rootElement: document.body @@ -86,22 +95,21 @@ exports.startup = function() { $tw.pageScroller.handleEvent(event); }); // Install the save action handler - $tw.wiki.initSavers(); $tw.rootWidget.addEventListener("tw-save-wiki",function(event) { - $tw.wiki.saveWiki({ + $tw.syncer.saveWiki({ template: event.param, downloadType: "text/plain" }); }); $tw.rootWidget.addEventListener("tw-auto-save-wiki",function(event) { - $tw.wiki.saveWiki({ + $tw.syncer.saveWiki({ method: "autosave", template: event.param, downloadType: "text/plain" }); }); $tw.rootWidget.addEventListener("tw-download-file",function(event) { - $tw.wiki.saveWiki({ + $tw.syncer.saveWiki({ method: "download", template: event.param, downloadType: "text/plain" diff --git a/core/modules/syncer.js b/core/modules/syncer.js index 288d17d4a..496e0339d 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -3,7 +3,7 @@ title: $:/core/modules/syncer.js type: application/javascript module-type: global -The syncer transfers content to and from data sources using syncadaptor modules. +The syncer tracks changes to the store. If a syncadaptor is used then individual tiddlers are synchronised through it. If there is no syncadaptor then the entire wiki is saved via saver modules. \*/ (function(){ @@ -28,46 +28,16 @@ function Syncer(options) { self.syncadaptor = new module.adaptorClass(self); } }); - // Only do anything if we've got a syncadaptor - if(this.syncadaptor) { - this.init(); + // Initialise our savers + if($tw.browser) { + this.initSavers(); } -} - -/* -Error handling -*/ -Syncer.prototype.showError = function(error) { - this.log("Error: " + error); -}; - -/* -Constants -*/ -Syncer.prototype.titleIsLoggedIn = "$:/status/IsLoggedIn"; -Syncer.prototype.titleUserName = "$:/status/UserName"; -Syncer.prototype.taskTimerInterval = 1 * 1000; // Interval for sync timer -Syncer.prototype.throttleInterval = 1 * 1000; // Defer saving tiddlers if they've changed in the last 1s... -Syncer.prototype.fallbackInterval = 10 * 1000; // Unless the task is older than 10s -Syncer.prototype.pollTimerInterval = 60 * 1000; // Interval for polling for changes from the adaptor - -/* -Initialise the syncer -*/ -Syncer.prototype.init = function() { - var self = this; - // Hashmap by title of {revision:,changeCount:,adaptorInfo:} - this.tiddlerInfo = {}; + // Compile the dirty tiddler filter + this.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter)); // Record information for known tiddlers - this.wiki.forEachTiddler({includeSystem: true},function(title,tiddler) { - self.tiddlerInfo[title] = { - revision: tiddler.fields["revision"], - adaptorInfo: self.syncadaptor.getTiddlerInfo(tiddler), - changeCount: self.wiki.getChangeCount(title) - } - }); + this.readTiddlerInfo(); // Tasks are {type: "load"/"save"/"delete", title:, queueTime:, lastModificationTime:} - this.taskQueue = {}; // Hashmap of tasks to be performed + this.taskQueue = {}; // Hashmap of tasks yet to be performed this.taskInProgress = {}; // Hash of tasks in progress this.taskTimerId = null; // Timer for task dispatch this.pollTimerId = null; // Timer for polling server @@ -76,9 +46,11 @@ Syncer.prototype.init = function() { self.syncToServer(changes); }); // Listen out for lazyLoad events - this.wiki.addEventListener("lazyLoad",function(title) { - self.handleLazyLoadEvent(title); - }); + if(this.syncadaptor) { + this.wiki.addEventListener("lazyLoad",function(title) { + self.handleLazyLoadEvent(title); + }); + } // Listen out for login/logout/refresh events in the browser if($tw.browser) { document.addEventListener("tw-login",function(event) { @@ -98,6 +70,120 @@ Syncer.prototype.init = function() { self.syncFromServer(); } }); +} + +/* +Error handling +*/ +Syncer.prototype.showError = function(error) { + this.log("Error: " + error); +}; + +/* +Constants +*/ +Syncer.prototype.titleIsLoggedIn = "$:/status/IsLoggedIn"; +Syncer.prototype.titleUserName = "$:/status/UserName"; +Syncer.prototype.titleSyncFilter = "$:/config/SyncFilter"; +Syncer.prototype.titleAutoSave = "$:/config/AutoSave"; +Syncer.prototype.taskTimerInterval = 1 * 1000; // Interval for sync timer +Syncer.prototype.throttleInterval = 1 * 1000; // Defer saving tiddlers if they've changed in the last 1s... +Syncer.prototype.fallbackInterval = 10 * 1000; // Unless the task is older than 10s +Syncer.prototype.pollTimerInterval = 60 * 1000; // Interval for polling for changes from the adaptor + +/* +Read (or re-read) the latest tiddler info from the store +*/ +Syncer.prototype.readTiddlerInfo = function() { + // Hashmap by title of {revision:,changeCount:,adaptorInfo:} + this.tiddlerInfo = {}; + // Record information for known tiddlers + var self = this; + this.wiki.forEachTiddler({includeSystem: true},function(title,tiddler) { + self.tiddlerInfo[title] = { + revision: tiddler.fields["revision"], + adaptorInfo: self.syncadaptor && self.syncadaptor.getTiddlerInfo(tiddler), + changeCount: self.wiki.getChangeCount(title) + } + }); +}; + +/* +Select the appropriate saver modules and set them up +*/ +Syncer.prototype.initSavers = function(moduleType) { + moduleType = moduleType || "saver"; + // Instantiate the available savers + this.savers = []; + var self = this; + $tw.modules.forEachModuleOfType(moduleType,function(title,module) { + if(module.canSave(self)) { + self.savers.push(module.create(self.wiki)); + } + }); + // Sort the savers into priority order + this.savers.sort(function(a,b) { + if(a.info.priority < b.info.priority) { + return -1; + } else { + if(a.info.priority > b.info.priority) { + return +1; + } else { + return 0; + } + } + }); +}; + +/* +Save the wiki contents. Options are: + method: "save" or "download" + template: the tiddler containing the template to save + downloadType: the content type for the saved file +*/ +Syncer.prototype.saveWiki = function(options) { + options = options || {}; + var method = options.method || "save", + template = options.template || "$:/core/save/all", + downloadType = options.downloadType || "text/plain", + text = this.wiki.renderTiddler(downloadType,template), + callback = function(err) { + if(err) { + alert("Error while saving:\n\n" + err); + } else { + $tw.notifier.display("$:/messages/Saved"); + if(options.callback) { + options.callback(); + } + } + }; + // Ignore autosave if we've got a syncadaptor or autosave is disabled + if(method === "autosave") { + if(this.syncadaptor || this.wiki.getTiddlerText(this.titleAutoSave,"yes") !== "yes") { + return false; + } + } + // Call the highest priority saver that supports this method + for(var t=this.savers.length-1; t>=0; t--) { + var saver = this.savers[t]; + if(saver.info.capabilities.indexOf(method) !== -1 && saver.save(text,method,callback)) { + this.log("Saving wiki with method",method,"through saver",saver.info.name); + // Clear the task queue if we're saving (rather than downloading) + if(method !== "download") { + this.readTiddlerInfo(); + this.taskQueue = {}; + } + return true; + } + } + return false; +}; + +/* +Checks whether the wiki is dirty (ie the window shouldn't be closed) +*/ +Syncer.prototype.isDirty = function() { + return (this.numTasksInQueue() > 0) || (this.numTasksInProgress() > 0); }; /* @@ -118,7 +204,7 @@ Syncer.prototype.storeTiddler = function(tiddlerFields) { Syncer.prototype.getStatus = function(callback) { var self = this; // Check if the adaptor supports getStatus() - if(this.syncadaptor.getStatus) { + if(this.syncadaptor && this.syncadaptor.getStatus) { // Mark us as not logged in this.wiki.addTiddler({title: this.titleIsLoggedIn,text: "no"}); // Get login status @@ -130,7 +216,7 @@ Syncer.prototype.getStatus = function(callback) { // Set the various status tiddlers self.wiki.addTiddler({title: self.titleIsLoggedIn,text: isLoggedIn ? "yes" : "no"}); if(isLoggedIn) { - self.wiki.addTiddler({title: self.titleUserName,text: username}); + self.wiki.addTiddler({title: self.titleUserName,text: username || ""}); } else { self.wiki.deleteTiddler(self.titleUserName); } @@ -148,7 +234,7 @@ Syncer.prototype.getStatus = function(callback) { Synchronise from the server by reading the skinny tiddler list and queuing up loads for any tiddlers that we don't already have up to date */ Syncer.prototype.syncFromServer = function() { - if(this.syncadaptor.getSkinnyTiddlers) { + if(this.syncadaptor && this.syncadaptor.getSkinnyTiddlers) { this.log("Retrieving skinny tiddler list"); var self = this; if(this.pollTimerId) { @@ -198,10 +284,11 @@ Synchronise a set of changes to the server */ Syncer.prototype.syncToServer = function(changes) { var self = this, - now = new Date(); + now = new Date(), + filteredChanges = this.filterFn.call(this.wiki,changes); $tw.utils.each(changes,function(change,title,object) { // Ignore the change if it is a shadow tiddler - if((change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) || (!change.deleted && self.wiki.tiddlerExists(title))) { + if((change.deleted && $tw.utils.hop(self.tiddlerInfo,title)) || (!change.deleted && filteredChanges.indexOf(title) !== -1)) { // Queue a task to sync this tiddler self.enqueueSyncTask({ type: change.deleted ? "delete" : "save", @@ -215,6 +302,7 @@ Syncer.prototype.syncToServer = function(changes) { Lazily load a skinny tiddler if we can */ Syncer.prototype.handleLazyLoadEvent = function(title) { +console.log("Lazy loading",title) // Queue up a sync task to load this tiddler this.enqueueSyncTask({ type: "load", @@ -314,7 +402,7 @@ Syncer.prototype.enqueueSyncTask = function(task) { } // Check if this tiddler is already in the queue if($tw.utils.hop(this.taskQueue,task.title)) { - this.log("Re-queueing up sync task with type:",task.type,"title:",task.title); + // this.log("Re-queueing up sync task with type:",task.type,"title:",task.title); var existingTask = this.taskQueue[task.title]; // If so, just update the last modification time existingTask.lastModificationTime = task.lastModificationTime; @@ -323,12 +411,14 @@ Syncer.prototype.enqueueSyncTask = function(task) { existingTask.type = task.type; } } else { - this.log("Queuing up sync task with type:",task.type,"title:",task.title); + // this.log("Queuing up sync task with type:",task.type,"title:",task.title); // If it is not in the queue, insert it this.taskQueue[task.title] = task; } // Process the queue - $tw.utils.nextTick(function() {self.processTaskQueue.call(self);}); + if(this.syncadaptor) { + $tw.utils.nextTick(function() {self.processTaskQueue.call(self);}); + } }; /* diff --git a/core/modules/widgets/navigator.js b/core/modules/widgets/navigator.js index 81b316281..6312f9de8 100755 --- a/core/modules/widgets/navigator.js +++ b/core/modules/widgets/navigator.js @@ -52,6 +52,7 @@ NavigatorWidget.prototype.execute = function() { // Get our parameters this.storyTitle = this.getAttribute("story"); this.historyTitle = this.getAttribute("history"); + this.autosave = this.getAttribute("autosave","yes"); // Construct the child widgets this.makeChildWidgets(); }; @@ -61,7 +62,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ NavigatorWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.story || changedAttributes.history) { + if(changedAttributes.story || changedAttributes.history || changedAttributes.autosave) { this.refreshSelf(); return true; } else { @@ -290,7 +291,9 @@ NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) { this.saveStoryList(storyList); } // Send a notification event - this.dispatchEvent({type: "tw-auto-save-wiki"}); + if(this.autosave === "yes") { + this.dispatchEvent({type: "tw-auto-save-wiki"}); + } } } } diff --git a/core/modules/wiki.js b/core/modules/wiki.js index 35f97640b..a4c9fbb38 100755 --- a/core/modules/wiki.js +++ b/core/modules/wiki.js @@ -877,62 +877,6 @@ exports.renderTiddler = function(outputType,title,options) { return outputType === "text/html" ? container.innerHTML : container.textContent; }; -/* -Select the appropriate saver modules and set them up -*/ -exports.initSavers = function(moduleType) { - moduleType = moduleType || "saver"; - // Instantiate the available savers - this.savers = []; - var self = this; - $tw.modules.forEachModuleOfType(moduleType,function(title,module) { - if(module.canSave(self)) { - self.savers.push(module.create(self)); - } - }); - // Sort the savers into priority order - this.savers.sort(function(a,b) { - if(a.info.priority < b.info.priority) { - return -1; - } else { - if(a.info.priority > b.info.priority) { - return +1; - } else { - return 0; - } - } - }); -}; - -/* -Save the wiki contents. Options are: - method: "save" or "download" - template: the tiddler containing the template to save - downloadType: the content type for the saved file -*/ -exports.saveWiki = function(options) { - options = options || {}; - var method = options.method || "save", - template = options.template || "$:/core/save/all", - downloadType = options.downloadType || "text/plain", - text = this.renderTiddler(downloadType,template), - callback = function(err) { - if(err) { - alert("Error while saving:\n\n" + err); - } else { - $tw.notifier.display("$:/messages/Saved"); - } - }; - // Call the highest priority saver that supports this method - for(var t=this.savers.length-1; t>=0; t--) { - var saver = this.savers[t]; - if(saver.info.capabilities.indexOf(method) !== -1 && saver.save(text,method,callback)) { - return true; - } - } - return false; -}; - /* Return an array of tiddler titles that match a search string text: The text string to search for diff --git a/core/ui/ControlPanel/Saving.tid b/core/ui/ControlPanel/Saving.tid index 629233144..ac30498e5 100644 --- a/core/ui/ControlPanel/Saving.tid +++ b/core/ui/ControlPanel/Saving.tid @@ -12,6 +12,11 @@ http://$(userName)$.tiddlyspot.com/backup/ \end +! Saving + +|[[Autosave|$:/config/AutoSave]] |{{$:/snippets/autosavestatus}} | + + ! TiddlySpot |[[Wiki name|$:/UploadName]] |<$edit-text tiddler="$:/UploadName" default="" tag="input"/> | diff --git a/core/wiki/autosavestatus.tid b/core/wiki/autosavestatus.tid new file mode 100644 index 000000000..ec29aa41a --- /dev/null +++ b/core/wiki/autosavestatus.tid @@ -0,0 +1,10 @@ +title: $:/snippets/autosavestatus + +<$reveal type="match" state="$:/config/AutoSave" text="yes"> +Autosave is currently enabled +<$linkcatcher to="$:/config/AutoSave"><$link to="no">Disable + +<$reveal type="nomatch" state="$:/config/AutoSave" text="yes"> +Autosave is currently disabled +<$linkcatcher to="$:/config/AutoSave"><$link to="yes">Enable + \ No newline at end of file diff --git a/core/wiki/config/AutoSave.tid b/core/wiki/config/AutoSave.tid new file mode 100644 index 000000000..7dd676941 --- /dev/null +++ b/core/wiki/config/AutoSave.tid @@ -0,0 +1,3 @@ +title: $:/config/AutoSave + +yes \ No newline at end of file diff --git a/core/wiki/config/SyncFilter.tid b/core/wiki/config/SyncFilter.tid new file mode 100644 index 000000000..e2447c2ac --- /dev/null +++ b/core/wiki/config/SyncFilter.tid @@ -0,0 +1,3 @@ +title: $:/config/SyncFilter + +[is[tiddler]] -[[$:/HistoryList]] -[[$:/StoryList]] -[[$:/isEncrypted]] -[prefix[$:/status]] -[prefix[$:/state]] -[prefix[$:/temp]] \ No newline at end of file diff --git a/editions/clientserver/tiddlers/AutoSave.tid b/editions/clientserver/tiddlers/AutoSave.tid new file mode 100644 index 000000000..2ceb1058f --- /dev/null +++ b/editions/clientserver/tiddlers/AutoSave.tid @@ -0,0 +1,11 @@ +created: 20140206211715540 +modified: 20140206212334833 +tags: features +title: AutoSave +type: text/vnd.tiddlywiki + +If there is a SaverModule available that supports it, TiddlyWiki will automatically trigger a save of the current document on clicking {{$:/core/images/done-button}} ''tick'' after editing a tiddler. + +You should see a yellow notification at the top right of the window to confirm that an automatic save has taken place. + +Automatic saving can be enabled or disabled through the ''Saving'' tab of the [[control panel|$:/ControlPanel]]. Behind the scenes, it is controlled through the configuration tiddler [[$:/config/AutoSave]], which must have the value ''yes'' to enable automatic saving. diff --git a/editions/clientserver/tiddlywiki.info b/editions/clientserver/tiddlywiki.info index f8993ce0b..fc6bb51b3 100644 --- a/editions/clientserver/tiddlywiki.info +++ b/editions/clientserver/tiddlywiki.info @@ -9,11 +9,6 @@ "tiddlywiki/vanilla", "tiddlywiki/snowwhite" ], - "doNotSave": [ - "$:/HistoryList", - "$:/status/IsLoggedIn", - "$:/status/UserName" - ], "includeWikis": [ "../tw5.com" ] diff --git a/editions/codemirrordemo/tiddlywiki.info b/editions/codemirrordemo/tiddlywiki.info index f912fead8..a7d6bc947 100644 --- a/editions/codemirrordemo/tiddlywiki.info +++ b/editions/codemirrordemo/tiddlywiki.info @@ -6,8 +6,6 @@ "tiddlywiki/vanilla", "tiddlywiki/snowwhite" ], - "doNotSave": [ - ], "includeWikis": [ ] } diff --git a/editions/d3demo/tiddlywiki.info b/editions/d3demo/tiddlywiki.info index 704a211be..65e8fa412 100644 --- a/editions/d3demo/tiddlywiki.info +++ b/editions/d3demo/tiddlywiki.info @@ -6,12 +6,6 @@ "tiddlywiki/vanilla", "tiddlywiki/snowwhite" ], - "doNotSave": [ - "$:/StoryList", - "$:/HistoryList", - "$:/status/IsLoggedIn", - "$:/status/UserName" - ], "includeWikis": [ ] } \ No newline at end of file diff --git a/editions/highlightdemo/tiddlywiki.info b/editions/highlightdemo/tiddlywiki.info index aa8ad61f2..6f898b038 100644 --- a/editions/highlightdemo/tiddlywiki.info +++ b/editions/highlightdemo/tiddlywiki.info @@ -6,8 +6,6 @@ "tiddlywiki/vanilla", "tiddlywiki/snowwhite" ], - "doNotSave": [ - ], "includeWikis": [ ] } diff --git a/editions/markdowndemo/tiddlywiki.info b/editions/markdowndemo/tiddlywiki.info index 062fd2fcc..4c33621ca 100644 --- a/editions/markdowndemo/tiddlywiki.info +++ b/editions/markdowndemo/tiddlywiki.info @@ -6,8 +6,6 @@ "tiddlywiki/vanilla", "tiddlywiki/snowwhite" ], - "doNotSave": [ - ], "includeWikis": [ ] } diff --git a/editions/tw5.com/tiddlers/GettingStarted.tid b/editions/tw5.com/tiddlers/GettingStarted.tid index ec5a51cb4..0cf537840 100644 --- a/editions/tw5.com/tiddlers/GettingStarted.tid +++ b/editions/tw5.com/tiddlers/GettingStarted.tid @@ -1,5 +1,5 @@ created: 20131129090249275 -modified: 20140126130155435 +modified: 20140206212022007 tags: introduction title: GettingStarted type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/Release 5.0.8beta.tid b/editions/tw5.com/tiddlers/Release 5.0.8beta.tid index 5c0291197..c8f27b9ba 100644 --- a/editions/tw5.com/tiddlers/Release 5.0.8beta.tid +++ b/editions/tw5.com/tiddlers/Release 5.0.8beta.tid @@ -1,5 +1,5 @@ created: 20140127143652456 -modified: 20140127151028534 +modified: 20140206191028534 tags: releasenote title: Release 5.0.8-beta type: text/vnd.tiddlywiki @@ -18,7 +18,8 @@ These are changes that might affect users upgrading from previous betas. !! Improvements -* +* Added [[automatic saving|AutoSave]] on editing a tiddler +* Added a warning when attempting to close the window with unsaved changes !! Bug Fixes diff --git a/editions/tw5.com/tiddlers/concepts/TiddlyWikiFolders.tid b/editions/tw5.com/tiddlers/concepts/TiddlyWikiFolders.tid index f3dd330a5..38bdd29ec 100644 --- a/editions/tw5.com/tiddlers/concepts/TiddlyWikiFolders.tid +++ b/editions/tw5.com/tiddlers/concepts/TiddlyWikiFolders.tid @@ -1,5 +1,5 @@ created: 20130825214200000 -modified: 20140128194546203 +modified: 20140206174804112 tags: dev title: TiddlyWikiFolders type: text/vnd.tiddlywiki @@ -21,7 +21,6 @@ Only the ''tiddlywiki.info'' file is required, the ''tiddlers'' and ''plugins'' The `tiddlywiki.info` file in a wiki folder contains a JSON object comprising the following fields: * ''plugins'' - an array of plugin names to be included in the wiki -* ''doNotSave'' - an array of tiddler titles that should not be saved by the FileSystemAdaptorPlugin * ''includeWikis'' - an array of relative paths to external wiki folders to be included in the wiki For example: @@ -32,11 +31,6 @@ For example: "tiddlywiki/tiddlyweb", "tiddlywiki/filesystem" ], - "doNotSave": [ - "$:/HistoryList", - "$:/status/IsLoggedIn", - "$:/status/UserName" - ], "includeWikis": [ "../tw5.com" ] diff --git a/editions/tw5.com/tiddlers/roadmap/RoadMap.tid b/editions/tw5.com/tiddlers/roadmap/RoadMap.tid index 74887756e..c92a49c2c 100644 --- a/editions/tw5.com/tiddlers/roadmap/RoadMap.tid +++ b/editions/tw5.com/tiddlers/roadmap/RoadMap.tid @@ -1,5 +1,5 @@ created: 20130823203800000 -modified: 20140124204012349 +modified: 20140206174012349 tags: planning title: RoadMap type: text/vnd.tiddlywiki @@ -12,10 +12,6 @@ During the beta TiddlyWiki will be practical for cautious everyday use but as we The following additional features are planned or under consideration for implementation during the beta: -* Features affecting user data integrity -** Warning when attempting to close window without saving -** Use browser local storage to preserve changes in case browser crashes before saving/sync -** Automatic saving for saver modules that can support it * Features required for large scale adoption ** Multilanguage support ** Proper use of ARIA roles diff --git a/plugins/tiddlywiki/filesystem/filesystemadaptor.js b/plugins/tiddlywiki/filesystem/filesystemadaptor.js index c80cbb0a1..d495f700a 100644 --- a/plugins/tiddlywiki/filesystem/filesystemadaptor.js +++ b/plugins/tiddlywiki/filesystem/filesystemadaptor.js @@ -140,10 +140,6 @@ FileSystemAdaptor.prototype.saveTiddler = function(tiddler,callback) { if(err) { return callback(err); } - if($tw.boot.wikiInfo.doNotSave && $tw.boot.wikiInfo.doNotSave.indexOf(tiddler.fields.title) !== -1) { - // Don't save the tiddler if it is on the blacklist - return callback(null,{},0); - } if(self.watchers[fileInfo.filepath]) { self.watchers[fileInfo.filepath].close(); delete self.watchers[fileInfo.filepath]; @@ -197,34 +193,29 @@ FileSystemAdaptor.prototype.deleteTiddler = function(title,callback) { fileInfo = $tw.boot.files[title]; // Only delete the tiddler if we have writable information for the file if(fileInfo) { - if($tw.boot.wikiInfo.doNotSave && $tw.boot.wikiInfo.doNotSave.indexOf(title) !== -1) { - // Don't delete the tiddler if it is on the blacklist - callback(null); - } else { - if(this.watchers[fileInfo.filepath]) { - this.watchers[fileInfo.filepath].close(); - delete this.watchers[fileInfo.filepath]; - } - delete this.pending[fileInfo.filepath]; - // Delete the file - fs.unlink(fileInfo.filepath,function(err) { - if(err) { - return callback(err); - } - self.log("Deleted file",fileInfo.filepath); - // Delete the metafile if present - if(fileInfo.hasMetaFile) { - fs.unlink(fileInfo.filepath + ".meta",function(err) { - if(err) { - return callback(err); - } - callback(null); - }); - } else { - callback(null); - } - }); + if(this.watchers[fileInfo.filepath]) { + this.watchers[fileInfo.filepath].close(); + delete this.watchers[fileInfo.filepath]; } + delete this.pending[fileInfo.filepath]; + // Delete the file + fs.unlink(fileInfo.filepath,function(err) { + if(err) { + return callback(err); + } + self.log("Deleted file",fileInfo.filepath); + // Delete the metafile if present + if(fileInfo.hasMetaFile) { + fs.unlink(fileInfo.filepath + ".meta",function(err) { + if(err) { + return callback(err); + } + callback(null); + }); + } else { + callback(null); + } + }); } else { callback(null); }