mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-02-17 03:20:02 +00:00
Separate the saver handling out of the syncer
This commit is contained in:
parent
27f1f82a70
commit
f75af2c983
170
core/modules/saver-handler.js
Normal file
170
core/modules/saver-handler.js
Normal file
@ -0,0 +1,170 @@
|
||||
/*\
|
||||
title: $:/core/modules/saver-handler.js
|
||||
type: application/javascript
|
||||
module-type: global
|
||||
|
||||
The saver handler tracks changes to the store and handles saving the entire wiki via saver modules.
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Instantiate the saver handler with the following options:
|
||||
wiki: wiki to be synced
|
||||
*/
|
||||
function SaverHandler(options) {
|
||||
var self = this;
|
||||
this.wiki = options.wiki;
|
||||
// Make a logger
|
||||
this.logger = new $tw.utils.Logger("saver-handler");
|
||||
// Initialise our savers
|
||||
if($tw.browser) {
|
||||
this.initSavers();
|
||||
}
|
||||
// Compile the dirty tiddler filter
|
||||
this.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));
|
||||
// Count of tiddlers that have been changed but not yet saved
|
||||
this.numTasksInQueue = 0;
|
||||
// Listen out for changes to tiddlers
|
||||
this.wiki.addEventListener("change",function(changes) {
|
||||
var filteredChanges = self.filterFn.call(self.wiki,function(callback) {
|
||||
$tw.utils.each(changes,function(change,title) {
|
||||
var tiddler = self.wiki.getTiddler(title);
|
||||
callback(tiddler,title);
|
||||
});
|
||||
});
|
||||
self.numTasksInQueue += filteredChanges.length;
|
||||
self.updateDirtyStatus();
|
||||
});
|
||||
// Browser event handlers
|
||||
if($tw.browser) {
|
||||
// Set up our beforeunload handler
|
||||
window.addEventListener("beforeunload",function(event) {
|
||||
var confirmationMessage = undefined;
|
||||
if(self.isDirty()) {
|
||||
confirmationMessage = $tw.language.getString("UnsavedChangesWarning");
|
||||
event.returnValue = confirmationMessage; // Gecko
|
||||
}
|
||||
return confirmationMessage;
|
||||
});
|
||||
// Install the save action handlers
|
||||
$tw.rootWidget.addEventListener("tw-save-wiki",function(event) {
|
||||
self.saveWiki({
|
||||
template: event.param,
|
||||
downloadType: "text/plain"
|
||||
});
|
||||
});
|
||||
$tw.rootWidget.addEventListener("tw-auto-save-wiki",function(event) {
|
||||
self.saveWiki({
|
||||
method: "autosave",
|
||||
template: event.param,
|
||||
downloadType: "text/plain"
|
||||
});
|
||||
});
|
||||
$tw.rootWidget.addEventListener("tw-download-file",function(event) {
|
||||
self.saveWiki({
|
||||
method: "download",
|
||||
template: event.param,
|
||||
downloadType: "text/plain"
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SaverHandler.prototype.titleSyncFilter = "$:/config/SyncFilter";
|
||||
SaverHandler.prototype.titleAutoSave = "$:/config/AutoSave";
|
||||
SaverHandler.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done";
|
||||
|
||||
/*
|
||||
Select the appropriate saver modules and set them up
|
||||
*/
|
||||
SaverHandler.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
|
||||
*/
|
||||
SaverHandler.prototype.saveWiki = function(options) {
|
||||
options = options || {};
|
||||
var self = this,
|
||||
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(self.titleSavedNotification);
|
||||
if(options.callback) {
|
||||
options.callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
// Ignore autosave if disabled
|
||||
if(method === "autosave" && 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.logger.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.numTasksInQueue = 0;
|
||||
this.updateDirtyStatus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/*
|
||||
Checks whether the wiki is dirty (ie the window shouldn't be closed)
|
||||
*/
|
||||
SaverHandler.prototype.isDirty = function() {
|
||||
return this.numTasksInQueue > 0;
|
||||
};
|
||||
|
||||
/*
|
||||
Update the document body with the class "tw-dirty" if the wiki has unsaved/unsynced changes
|
||||
*/
|
||||
SaverHandler.prototype.updateDirtyStatus = function() {
|
||||
if($tw.browser) {
|
||||
$tw.utils.toggleClass(document.body,"tw-dirty",this.isDirty());
|
||||
}
|
||||
};
|
||||
|
||||
exports.SaverHandler = SaverHandler;
|
||||
|
||||
})();
|
@ -69,9 +69,11 @@ exports.startup = function() {
|
||||
$tw.syncadaptor = new module.adaptorClass({wiki: $tw.wiki});
|
||||
}
|
||||
});
|
||||
// Set up the syncer object
|
||||
// Set up the syncer object if we've got a syncadaptor, otherwise setup the saverhandler
|
||||
if($tw.syncadaptor) {
|
||||
$tw.syncer = new $tw.Syncer({wiki: $tw.wiki, syncadaptor: $tw.syncadaptor});
|
||||
} else {
|
||||
$tw.saverHandler = new $tw.SaverHandler({wiki: $tw.wiki});
|
||||
}
|
||||
// Host-specific startup
|
||||
if($tw.browser) {
|
||||
|
@ -23,10 +23,6 @@ function Syncer(options) {
|
||||
this.syncadaptor = options.syncadaptor
|
||||
// Make a logger
|
||||
this.logger = new $tw.utils.Logger("syncer" + ($tw.browser ? "-browser" : "") + ($tw.node ? "-server" : ""));
|
||||
// Initialise our savers
|
||||
if($tw.browser) {
|
||||
this.initSavers();
|
||||
}
|
||||
// Compile the dirty tiddler filter
|
||||
this.filterFn = this.wiki.compileFilter(this.wiki.getTiddlerText(this.titleSyncFilter));
|
||||
// Record information for known tiddlers
|
||||
@ -61,34 +57,11 @@ function Syncer(options) {
|
||||
$tw.rootWidget.addEventListener("tw-server-refresh",function() {
|
||||
self.handleRefreshEvent();
|
||||
});
|
||||
// Install the save action handlers
|
||||
$tw.rootWidget.addEventListener("tw-save-wiki",function(event) {
|
||||
self.saveWiki({
|
||||
template: event.param,
|
||||
downloadType: "text/plain"
|
||||
});
|
||||
});
|
||||
$tw.rootWidget.addEventListener("tw-auto-save-wiki",function(event) {
|
||||
self.saveWiki({
|
||||
method: "autosave",
|
||||
template: event.param,
|
||||
downloadType: "text/plain"
|
||||
});
|
||||
});
|
||||
$tw.rootWidget.addEventListener("tw-download-file",function(event) {
|
||||
self.saveWiki({
|
||||
method: "download",
|
||||
template: event.param,
|
||||
downloadType: "text/plain"
|
||||
});
|
||||
});
|
||||
}
|
||||
// Listen out for lazyLoad events
|
||||
if(this.syncadaptor) {
|
||||
this.wiki.addEventListener("lazyLoad",function(title) {
|
||||
self.handleLazyLoadEvent(title);
|
||||
});
|
||||
}
|
||||
this.wiki.addEventListener("lazyLoad",function(title) {
|
||||
self.handleLazyLoadEvent(title);
|
||||
});
|
||||
// Get the login status
|
||||
this.getStatus(function (err,isLoggedIn) {
|
||||
// Do a sync from the server
|
||||
@ -102,7 +75,6 @@ Constants
|
||||
Syncer.prototype.titleIsLoggedIn = "$:/status/IsLoggedIn";
|
||||
Syncer.prototype.titleUserName = "$:/status/UserName";
|
||||
Syncer.prototype.titleSyncFilter = "$:/config/SyncFilter";
|
||||
Syncer.prototype.titleAutoSave = "$:/config/AutoSave";
|
||||
Syncer.prototype.titleSavedNotification = "$:/language/Notifications/Save/Done";
|
||||
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...
|
||||
@ -129,79 +101,6 @@ Syncer.prototype.readTiddlerInfo = function() {
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
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 self = this,
|
||||
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(self.titleSavedNotification);
|
||||
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.logger.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 = {};
|
||||
this.updateDirtyStatus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/*
|
||||
Checks whether the wiki is dirty (ie the window shouldn't be closed)
|
||||
*/
|
||||
@ -453,9 +352,7 @@ Syncer.prototype.enqueueSyncTask = function(task) {
|
||||
this.updateDirtyStatus();
|
||||
}
|
||||
// Process the queue
|
||||
if(this.syncadaptor) {
|
||||
$tw.utils.nextTick(function() {self.processTaskQueue.call(self);});
|
||||
}
|
||||
$tw.utils.nextTick(function() {self.processTaskQueue.call(self);});
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user