Introduce syncer mechanism

This commit is contained in:
Jeremy Ruston 2012-11-17 20:18:36 +00:00
parent 5c9b0d62c4
commit e194aed449
7 changed files with 101 additions and 132 deletions

View File

@ -34,9 +34,10 @@ exports.startup = function() {
$tw.wiki.initMacros(); $tw.wiki.initMacros();
$tw.wiki.initEditors(); $tw.wiki.initEditors();
$tw.wiki.initFieldViewers(); $tw.wiki.initFieldViewers();
$tw.wiki.initStoryViews();
$tw.wiki.initListViews(); $tw.wiki.initListViews();
$tw.wiki.initParsers(); $tw.wiki.initParsers();
$tw.wiki.initSyncers();
$tw.wiki.initServerConnections();
// Set up the command modules // Set up the command modules
$tw.Commander.initCommands(); $tw.Commander.initCommands();
// Host-specific startup // Host-specific startup
@ -57,6 +58,12 @@ exports.startup = function() {
document.addEventListener("tw-modal",function(event) { document.addEventListener("tw-modal",function(event) {
$tw.modal.display(event.param); $tw.modal.display(event.param);
},false); },false);
// Install the syncer message mechanism
var handleSyncerEvent = function(event) {
$tw.wiki.handleSyncerEvent.call($tw.wiki,event);
};
document.addEventListener("tw-login",handleSyncerEvent,false);
document.addEventListener("tw-logout",handleSyncerEvent,false);
// Install the scroller // Install the scroller
$tw.scroller = new $tw.utils.Scroller(); $tw.scroller = new $tw.utils.Scroller();
// Install the sprite factory // Install the sprite factory
@ -100,7 +107,7 @@ exports.startup = function() {
$tw.renderer.refreshInDom(changes); $tw.renderer.refreshInDom(changes);
}); });
} else { } else {
// Start a commander with the command line arguments // On the server, start a commander with the command line arguments
commander = new $tw.Commander( commander = new $tw.Commander(
Array.prototype.slice.call(process.argv,2), Array.prototype.slice.call(process.argv,2),
function(err) { function(err) {

View File

@ -557,18 +557,6 @@ exports.initListViews = function(moduleType) {
} }
}; };
/*
Install view modules for the story macro
*/
exports.initStoryViews = function(moduleType) {
moduleType = moduleType || "storyview";
var storyMacro = this.macros.story;
if(storyMacro) {
storyMacro.viewers = {};
$tw.modules.applyMethods(moduleType,storyMacro.viewers);
}
};
/* /*
Select the appropriate saver modules and set them up Select the appropriate saver modules and set them up
*/ */
@ -701,4 +689,39 @@ exports.search = function(text,options) {
return results; return results;
}; };
/*
Initialise syncers
*/
exports.initSyncers = function() {
this.syncers = {};
var self = this;
$tw.modules.forEachModuleOfType("syncer",function(title,module) {
if(module.name && module.syncer) {
self.syncers[module.name] = new module.syncer({
wiki: self
});
}
});
};
/*
Initialise server connections
*/
exports.initServerConnections = function() {
this.serverConnections = {};
var self = this;
$tw.modules.forEachModuleOfType("serverconnection",function(title,module) {
self.serverConnections[title] = module;
});
};
/*
Handle a syncer message
*/
exports.handleSyncerEvent = function(event) {
for(var syncer in this.syncers) {
this.syncers[syncer].handleEvent(event);
}
};
})(); })();

View File

@ -3,10 +3,10 @@ title: HelloThere
Experimenting with TiddlyWeb integration for TiddlyWiki5. Experimenting with TiddlyWeb integration for TiddlyWiki5.
<<reveal state:[[$:/plugins/tiddlyweb/IsLoggedIn]] type:nomatch text:yes>< <<reveal state:[[$:/plugins/tiddlyweb/IsLoggedIn]] type:nomatch text:yes><
Log in to TiddlyWeb: <<tiddlyweb.login><Login>> Log in to TiddlyWeb: <<button message:login><Login>>
>> >>
<<reveal state:[[$:/plugins/tiddlyweb/IsLoggedIn]] type:match text:yes>< <<reveal state:[[$:/plugins/tiddlyweb/IsLoggedIn]] type:match text:yes><
Log out of TiddlyWeb: <<tiddlyweb.logout><Logout>> Log out of TiddlyWeb: <<button message:logout><Logout>>
>> >>
TiddlyWeb [[login status|$:/plugins/tiddlyweb/IsLoggedIn]]: (($:/plugins/tiddlyweb/IsLoggedIn)) TiddlyWeb [[login status|$:/plugins/tiddlyweb/IsLoggedIn]]: (($:/plugins/tiddlyweb/IsLoggedIn))

View File

@ -2,5 +2,6 @@ title: TiddlyWebConnection
type: application/x-tiddler-dictionary type: application/x-tiddler-dictionary
module-type: serverconnection module-type: serverconnection
protocol: http syncer: tiddlywebsyncer
host: tiddlyspace.com # replace with a tiddlyspace to which you have write access
server: http://tw5tiddlyweb.tiddlyspace.com/

View File

@ -1,41 +0,0 @@
/*\
title: $:/plugins/tiddlywiki/tiddlyweb/loginmacro.js
type: application/javascript
module-type: macro
TiddlyWeb login plugin
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "tiddlyweb.login",
params: {}
};
exports.handleEvent = function (event) {
if(event.type === "click") {
$tw.plugins.tiddlyweb.promptLogin();
}
};
exports.executeMacro = function() {
// Create the link
var child = $tw.Tree.Element(
"a",
null,
this.content,
{
events: ["click"],
eventHandler: this
}
);
child.execute(this.parents,this.tiddlerTitle);
return child;
};
})();

View File

@ -1,41 +0,0 @@
/*\
title: $:/plugins/tiddlywiki/tiddlyweb/logoutmacro.js
type: application/javascript
module-type: macro
TiddlyWeb logout plugin
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "tiddlyweb.logout",
params: {}
};
exports.handleEvent = function (event) {
if(event.type === "click") {
$tw.plugins.tiddlyweb.logout();
}
};
exports.executeMacro = function() {
// Create the link
var child = $tw.Tree.Element(
"a",
null,
this.content,
{
events: ["click"],
eventHandler: this
}
);
child.execute(this.parents,this.tiddlerTitle);
return child;
};
})();

View File

@ -1,7 +1,7 @@
/*\ /*\
title: $:/plugins/tiddlywiki/tiddlyweb/tiddlyweb.js title: $:/plugins/tiddlywiki/tiddlyweb/tiddlyweb.js
type: application/javascript type: application/javascript
module-type: browser-startup module-type: syncer
Main TiddlyWeb integration module Main TiddlyWeb integration module
@ -12,45 +12,55 @@ Main TiddlyWeb integration module
/*global $tw: false */ /*global $tw: false */
"use strict"; "use strict";
$tw.plugins.tiddlyweb = {
titleIsLoggedIn: "$:/plugins/tiddlyweb/IsLoggedIn",
titleUserName: "$:/plugins/tiddlyweb/UserName"
};
/* /*
Startup function that sets up TiddlyWeb and logs the user in. After login, any tiddlyweb-startup modules are executed. Creates a TiddlyWebSyncer object
*/ */
exports.startup = function() { var TiddlyWebSyncer = function(options) {
if(!$tw.browser) {
return;
}
// Mark us as not logged in // Mark us as not logged in
$tw.wiki.addTiddler({ $tw.wiki.addTiddler({
title: $tw.plugins.tiddlyweb.titleIsLoggedIn, title: TiddlyWebSyncer.titleIsLoggedIn,
text: "no" text: "no"
}); });
// Get the login status // Get the login status
$tw.plugins.tiddlyweb.getStatus(); this.getStatus();
}; };
TiddlyWebSyncer.titleIsLoggedIn = "$:/plugins/tiddlyweb/IsLoggedIn";
TiddlyWebSyncer.titleUserName = "$:/plugins/tiddlyweb/UserName";
/* /*
Error handling Error handling
*/ */
$tw.plugins.tiddlyweb.showError = function(error) { TiddlyWebSyncer.prototype.showError = function(error) {
alert("TiddlyWeb error: " + error); alert("TiddlyWeb error: " + error);
console.log("TiddlyWeb error: " + error); console.log("TiddlyWeb error: " + error);
}; };
/*
Handle syncer messages
*/
TiddlyWebSyncer.prototype.handleEvent = function(event) {
switch(event.type) {
case "tw-login":
this.promptLogin();
break;
case "tw-logout":
this.logout();
break;
}
};
/* /*
Invoke any tiddlyweb-startup modules Invoke any tiddlyweb-startup modules
*/ */
$tw.plugins.tiddlyweb.invokeTiddlyWebStartupModules = function(loggedIn) { TiddlyWebSyncer.prototype.invokeTiddlyWebStartupModules = function(loggedIn) {
$tw.modules.forEachModuleOfType("tiddlyweb-startup",function(title,module) { $tw.modules.forEachModuleOfType("tiddlyweb-startup",function(title,module) {
module.startup(loggedIn); module.startup(loggedIn);
}); });
}; };
$tw.plugins.tiddlyweb.getCsrfToken = function() { TiddlyWebSyncer.prototype.getCsrfToken = function() {
var regex = /^(?:.*; )?csrf_token=([^(;|$)]*)(?:;|$)/, var regex = /^(?:.*; )?csrf_token=([^(;|$)]*)(?:;|$)/,
match = regex.exec(document.cookie), match = regex.exec(document.cookie),
csrf = null; csrf = null;
@ -58,11 +68,12 @@ $tw.plugins.tiddlyweb.getCsrfToken = function() {
csrf = match[1]; csrf = match[1];
} }
return csrf; return csrf;
}; };
$tw.plugins.tiddlyweb.getStatus = function(callback) { TiddlyWebSyncer.prototype.getStatus = function(callback) {
// Get status // Get status
$tw.plugins.tiddlyweb.httpRequest({ this.httpRequest({
url: "http://tw5tiddlyweb.tiddlyspace.com/status", url: "http://tw5tiddlyweb.tiddlyspace.com/status",
callback: function(err,data) { callback: function(err,data) {
// Decode the status JSON // Decode the status JSON
@ -76,16 +87,16 @@ $tw.plugins.tiddlyweb.getStatus = function(callback) {
var isLoggedIn = json.username !== "GUEST"; var isLoggedIn = json.username !== "GUEST";
// Set the various status tiddlers // Set the various status tiddlers
$tw.wiki.addTiddler({ $tw.wiki.addTiddler({
title: $tw.plugins.tiddlyweb.titleIsLoggedIn, title: TiddlyWebSyncer.titleIsLoggedIn,
text: isLoggedIn ? "yes" : "no" text: isLoggedIn ? "yes" : "no"
}); });
if(isLoggedIn) { if(isLoggedIn) {
$tw.wiki.addTiddler({ $tw.wiki.addTiddler({
title: $tw.plugins.tiddlyweb.titleUserName, title: TiddlyWebSyncer.titleUserName,
text: json.username text: json.username
}); });
} else { } else {
$tw.wiki.deleteTiddler($tw.plugins.tiddlyweb.titleUserName); $tw.wiki.deleteTiddler(TiddlyWebSyncer.titleUserName);
} }
} }
// Invoke the callback if present // Invoke the callback if present
@ -99,13 +110,14 @@ $tw.plugins.tiddlyweb.getStatus = function(callback) {
/* /*
Dispay a password prompt and allow the user to login Dispay a password prompt and allow the user to login
*/ */
$tw.plugins.tiddlyweb.promptLogin = function() { TiddlyWebSyncer.prototype.promptLogin = function() {
$tw.plugins.tiddlyweb.getStatus(function(isLoggedIn,json) { var self = this;
this.getStatus(function(isLoggedIn,json) {
if(!isLoggedIn) { if(!isLoggedIn) {
$tw.passwordPrompt.createPrompt({ $tw.passwordPrompt.createPrompt({
serviceName: "Login to TiddlySpace", serviceName: "Login to TiddlySpace",
callback: function(data) { callback: function(data) {
$tw.plugins.tiddlyweb.login(data.username,data.password); self.login(data.username,data.password);
return true; // Get rid of the password prompt return true; // Get rid of the password prompt
} }
}); });
@ -119,8 +131,9 @@ Attempt to login to TiddlyWeb.
password: password password: password
callback: invoked with arguments (err,isLoggedIn) callback: invoked with arguments (err,isLoggedIn)
*/ */
$tw.plugins.tiddlyweb.login = function(username,password,callback) { TiddlyWebSyncer.prototype.login = function(username,password,callback) {
var httpRequest = $tw.plugins.tiddlyweb.httpRequest({ var self = this;
var httpRequest = this.httpRequest({
url: "http://tw5tiddlyweb.tiddlyspace.com/challenge/tiddlywebplugins.tiddlyspace.cookie_form", url: "http://tw5tiddlyweb.tiddlyspace.com/challenge/tiddlywebplugins.tiddlyspace.cookie_form",
type: "POST", type: "POST",
data: { data: {
@ -134,7 +147,7 @@ $tw.plugins.tiddlyweb.login = function(username,password,callback) {
callback(err); callback(err);
} }
} else { } else {
$tw.plugins.tiddlyweb.getStatus(function(isLoggedIn,json) { self.getStatus(function(isLoggedIn,json) {
if(callback) { if(callback) {
callback(null,isLoggedIn); callback(null,isLoggedIn);
} }
@ -147,20 +160,21 @@ $tw.plugins.tiddlyweb.login = function(username,password,callback) {
/* /*
Attempt to log out of TiddlyWeb Attempt to log out of TiddlyWeb
*/ */
$tw.plugins.tiddlyweb.logout = function(options) { TiddlyWebSyncer.prototype.logout = function(options) {
options = options || {}; options = options || {};
var httpRequest = $tw.plugins.tiddlyweb.httpRequest({ var self = this;
var httpRequest = this.httpRequest({
url: "http://tw5tiddlyweb.tiddlyspace.com/logout", url: "http://tw5tiddlyweb.tiddlyspace.com/logout",
type: "POST", type: "POST",
data: { data: {
csrf_token: $tw.plugins.tiddlyweb.getCsrfToken(), csrf_token: this.getCsrfToken(),
tiddlyweb_redirect: "/status" // workaround to marginalize automatic subsequent GET tiddlyweb_redirect: "/status" // workaround to marginalize automatic subsequent GET
}, },
callback: function(err,data) { callback: function(err,data) {
if(err) { if(err) {
console.log("logout error",err); console.log("logout error",err);
} else { } else {
$tw.plugins.tiddlyweb.getStatus(function(isLoggedIn,json) { self.getStatus(function(isLoggedIn,json) {
console.log("after logout, isLoggedIn",isLoggedIn); console.log("after logout, isLoggedIn",isLoggedIn);
}); });
console.log("Result of logout",data,httpRequest); console.log("Result of logout",data,httpRequest);
@ -175,7 +189,7 @@ Some quick and dirty HTTP functions; to be refactored later. Options are:
type: GET, PUT, POST etc type: GET, PUT, POST etc
callback: function invoked with (err,data) callback: function invoked with (err,data)
*/ */
$tw.plugins.tiddlyweb.httpRequest = function(options) { TiddlyWebSyncer.prototype.httpRequest = function(options) {
var type = options.type || "GET", var type = options.type || "GET",
client = new XMLHttpRequest(), client = new XMLHttpRequest(),
data = "", data = "",
@ -212,4 +226,10 @@ $tw.plugins.tiddlyweb.httpRequest = function(options) {
return client; return client;
}; };
// Only export anything on the browser
if($tw.browser) {
exports.name = "tiddlywebsyncer";
exports.syncer = TiddlyWebSyncer;
}
})(); })();