update from webodf th/ocpull branch

This commit is contained in:
Tobias Hintze 2013-07-17 00:17:58 +02:00
parent 84105a20db
commit 883608bcc5
9 changed files with 2646 additions and 1219 deletions

View File

@ -58,8 +58,9 @@ define("webodf/editor/Editor", [
* cursorAddedCallback:function(!string)=, * cursorAddedCallback:function(!string)=,
* cursorRemovedCallback:function(!string)=, * cursorRemovedCallback:function(!string)=,
* registerCallbackForShutdown:function(!function())= }} args * registerCallbackForShutdown:function(!function())= }} args
* @param {!ops.Server=} server
*/ */
function Editor(args) { function Editor(args, server) {
var self = this, var self = this,
// Private // Private
@ -86,13 +87,6 @@ define("webodf/editor/Editor", [
return myResources[key]; return myResources[key];
} }
runtime.currentDirectory = function () {
return "../../webodf/lib";
};
runtime.libraryPaths = function () {
return [ runtime.currentDirectory() ];
};
/** /**
* prepare all gui elements and load the given document. * prepare all gui elements and load the given document.
* after loading is completed, the given callback is called. * after loading is completed, the given callback is called.
@ -272,10 +266,12 @@ define("webodf/editor/Editor", [
self.loadSession = function (sessionId, editorReadyCallback) { self.loadSession = function (sessionId, editorReadyCallback) {
initGuiAndDoc("/session/" + sessionId + "/genesis", function () { initGuiAndDoc("/session/" + sessionId + "/genesis", function () {
// use the nowjs op-router when connected // use the nowjs op-router when connected
opRouter = opRouter || new ops.NowjsOperationRouter(sessionId, memberid); // opRouter = opRouter || new ops.NowjsOperationRouter(sessionId, memberid, server);
opRouter = opRouter || new ops.PullBoxOperationRouter(sessionId, memberid, server);
session.setOperationRouter(opRouter); session.setOperationRouter(opRouter);
userModel = userModel || new ops.NowjsUserModel(); // userModel = userModel || new ops.NowjsUserModel(server);
userModel = userModel || new ops.PullBoxUserModel(server);
session.setUserModel(userModel); session.setUserModel(userModel);
opRouter.requestReplay(function done() { opRouter.requestReplay(function done() {

View File

@ -44,8 +44,10 @@ define("webodf/editor/EditorSession", [
runtime.loadClass("ops.OdtDocument"); runtime.loadClass("ops.OdtDocument");
runtime.loadClass("ops.Session"); runtime.loadClass("ops.Session");
runtime.loadClass("ops.NowjsOperationRouter"); // runtime.loadClass("ops.NowjsOperationRouter");
runtime.loadClass("ops.NowjsUserModel"); // runtime.loadClass("ops.NowjsUserModel");
runtime.loadClass("ops.PullBoxOperationRouter");
runtime.loadClass("ops.PullBoxUserModel");
runtime.loadClass("odf.OdfCanvas"); runtime.loadClass("odf.OdfCanvas");
runtime.loadClass("gui.CaretFactory"); runtime.loadClass("gui.CaretFactory");
runtime.loadClass("gui.Caret"); runtime.loadClass("gui.Caret");

View File

@ -0,0 +1,159 @@
/**
* @license
* Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
*
* @licstart
* The JavaScript code in this page is free software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* (GNU AGPL) as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. The code is distributed
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
*
* As additional permission under GNU AGPL version 3 section 7, you
* may distribute non-source (e.g., minimized or compacted) forms of
* that code without the copy of the GNU GPL normally required by
* section 4, provided you include this license notice and a URL
* through which recipients can access the Corresponding Source.
*
* As a special exception to the AGPL, any HTML file which merely makes function
* calls to this code, and for that purpose includes it by reference shall be
* deemed a separate work for copyright law purposes. In addition, the copyright
* holders of this code give you permission to combine this code with free
* software libraries that are released under the GNU LGPL. You may copy and
* distribute such a system following the terms of the GNU AGPL for this code
* and the LGPL for the libraries. If you modify this code, you may extend this
* exception to your version of the code, but you are not obligated to do so.
* If you do not wish to do so, delete this exception statement from your
* version.
*
* This license applies to this entire compilation.
* @licend
* @source: http://www.webodf.org/
* @source: http://gitorious.org/webodf/webodf/
*/
/*global ops, runtime */
function PullBoxSessionList(server) {
"use strict";
var cachedSessionData = {},
subscribers = [],
/** HACK: allow to stop pulling, so that does not mess up the logs
* Remove before merging to master */
pullingActive = true;
function onSessionData(sessionData) {
var i,
isNew = ! cachedSessionData.hasOwnProperty(sessionData.id);
// cache
cachedSessionData[sessionData.id] = sessionData;
runtime.log("get session data for:"+sessionData.title+", is new:"+isNew);
for (i = 0; i < subscribers.length; i += 1) {
if (isNew) {
subscribers[i].onCreated(sessionData);
} else {
subscribers[i].onUpdated(sessionData);
}
}
}
function onSessionRemoved(sessionId) {
var i;
if (cachedSessionData.hasOwnProperty(sessionId)) {
delete cachedSessionData[sessionId];
for (i = 0; i < subscribers.length; i += 1) {
subscribers[i].onRemoved(sessionId);
}
}
}
function pullSessionList() {
if (!pullingActive) { return; }
server.call("session-list", function(responseData) {
var response = runtime.fromJson(responseData),
sessionList, i,
unupdatedSessions = {};
runtime.log("session-list reply: " + responseData);
if (response.hasOwnProperty("session_list")) {
// collect known sessions
for (i in cachedSessionData) {
if (cachedSessionData.hasOwnProperty(i)) {
unupdatedSessions[i] = ""; // some dummy value, unused
}
}
// add/update with all delivered sessions
sessionList = response.session_list;
for (i = 0; i < sessionList.length; i++) {
if (unupdatedSessions.hasOwnProperty(sessionList[i].id)) {
delete unupdatedSessions[sessionList[i].id];
}
onSessionData(sessionList[i]);
}
// remove unupdated sessions
for (i in unupdatedSessions) {
if (unupdatedSessions.hasOwnProperty(i)) {
onSessionRemoved(i);
}
}
// next update in 5 secs
runtime.getWindow().setTimeout(pullSessionList, 5000);
} else {
runtime.log("Meh, sessionlist data broken: " + responseData);
}
});
}
this.getSessions = function (subscriber) {
var i,
sessionList = [];
if (subscriber) {
subscribers.push(subscriber);
}
for (i in cachedSessionData) {
if (cachedSessionData.hasOwnProperty(i)) {
sessionList.push(cachedSessionData[i]);
}
}
return sessionList;
};
this.unsubscribe = function (subscriber) {
var i;
for (i=0; i<subscribers.length; i+=1) {
if (subscribers[i] === subscriber) {
break;
}
}
runtime.assert((i < subscribers.length),
"tried to unsubscribe when not subscribed.");
subscribers.splice(i,1);
};
this.stopPulling = function () {
pullingActive = false;
};
function init() {
pullSessionList();
}
init();
}

View File

@ -1,6 +1,7 @@
/** /**
* Copyright (C) 2012 KO GmbH <copyright@kogmbh.com> * @license
* Copyright (C) 2012-2013 KO GmbH <copyright@kogmbh.com>
*
* @licstart * @licstart
* The JavaScript code in this page is free software: you can redistribute it * The JavaScript code in this page is free software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License * and/or modify it under the terms of the GNU Affero General Public License
@ -34,86 +35,16 @@
/*global ops, runtime */ /*global ops, runtime */
function SessionList(net) { /**
"use strict"; * A model which provides information about sessions.
* @interface
*/
SessionList = function SessionList() {"use strict"; };
var cachedSessionData = {}, /**
subscribers = []; * @param {{onCreated:function(!Object),
* onUpdated:function(!Object),
function onSessionData(sessionData) { * onRemoved:function(!string) }} subscriber
var i, * @return {undefined}
isNew = ! cachedSessionData.hasOwnProperty(sessionData.id); */
SessionList.prototype.getSessions = function (subscriber) {"use strict"; };
// cache
cachedSessionData[sessionData.id] = sessionData;
runtime.log("get session data for:"+sessionData.title+", is new:"+isNew);
for (i = 0; i < subscribers.length; i += 1) {
if (isNew) {
subscribers[i].onCreated(sessionData);
} else {
subscribers[i].onUpdated(sessionData);
}
}
}
function onSessionRemoved(sessionId) {
var i;
if (cachedSessionData.hasOwnProperty(sessionId)) {
delete cachedSessionData[sessionId];
for (i = 0; i < subscribers.length; i += 1) {
subscribers[i].onRemoved(sessionId);
}
}
}
this.getSessions = function (subscriber) {
var i,
sessionList = [];
if (subscriber) {
subscribers.push(subscriber);
}
for (i in cachedSessionData) {
if (cachedSessionData.hasOwnProperty(i)) {
sessionList.push(cachedSessionData[i]);
}
}
return sessionList;
};
this.unsubscribe = function (subscriber) {
var i;
for (i=0; i<subscribers.length; i+=1) {
if (subscribers[i] === subscriber) {
break;
}
}
runtime.assert((i < subscribers.length),
"tried to unsubscribe when not subscribed.");
subscribers.splice(i,1);
};
function init() {
net.onSessionAdded = onSessionData;
net.onSessionChanged = onSessionData;
net.onSessionRemoved = onSessionRemoved;
net.getSessionList( function(sessionList) {
var idx;
runtime.log("get sessions on init:"+sessionList.length);
for (idx=0; idx<sessionList.length; idx+=1) {
onSessionData(sessionList[idx])
}
});
}
init();
}

View File

@ -47,16 +47,24 @@
* *
*/ */
/*global runtime, require, document, alert, gui, window, SessionList, SessionListView, FileReader, Uint8Array */ /*global runtime, require, document, alert, net, window, NowjsSessionList, PullBoxSessionList, SessionListView, ops */
// define the namespace/object we want to provide // define the namespace/object we want to provide
// this is the first line of API, the user gets. // this is the first line of API, the user gets.
var webodfEditor = (function () { var webodfEditor = (function () {
"use strict"; "use strict";
runtime.currentDirectory = function () {
return "../../webodf/lib";
};
runtime.libraryPaths = function () {
return [ runtime.currentDirectory() ];
};
var editorInstance = null, var editorInstance = null,
running = false, server = null,
loadedFilename = null; booting = false,
loadedFilename;
/** /**
* wait for a network connection through nowjs to establish. * wait for a network connection through nowjs to establish.
@ -69,29 +77,33 @@ var webodfEditor = (function () {
* @param {!function(!string)} callback * @param {!function(!string)} callback
* @return {undefined} * @return {undefined}
*/ */
function waitForNetwork(callback) { function connectNetwork(backend, callback) {
var net = runtime.getNetwork(), accumulated_waiting_time = 0; if (backend === "pullbox") {
function later_cb() { runtime.loadClass("ops.PullBoxServer");
if (net.networkStatus === "unavailable") { server = new ops.PullBoxServer();
runtime.log("connection to server unavailable."); } else if (backend === "nowjs") {
callback("unavailable"); runtime.loadClass("ops.NowjsServer");
return; server = new ops.NowjsServer();
} } else if (backend === "owncloud") {
if (net.networkStatus !== "ready") { runtime.loadClass("ops.PullBoxServer");
if (accumulated_waiting_time > 8000) { server = new ops.PullBoxServer({url: "../../ajax/otpoll.php"});
// game over } else {
runtime.log("connection to server timed out."); callback("unavailable");
callback("timeout");
return;
}
accumulated_waiting_time += 100;
runtime.getWindow().setTimeout(later_cb, 100);
} else {
runtime.log("connection to collaboration server established.");
callback("ready");
}
} }
later_cb(); server.connect(8000, callback);
}
/**
* try to auto-sense the server-backend.
*
* NOT IMPLEMENTED / MIGHT BE NICE TO HAVE...
* for now: try to connect to pullbox backend
*
* @param {!function(!string)} callback
* @return {undefined}
*/
function detectNetwork(callback) {
connectNetwork("pullbox", callback);
} }
/** /**
@ -192,7 +204,7 @@ var webodfEditor = (function () {
*/ */
function createLocalEditor(docUrl, editorOptions, editorReadyCallback) { function createLocalEditor(docUrl, editorOptions, editorReadyCallback) {
var pos; var pos;
running = true; booting = true;
editorOptions = editorOptions || {}; editorOptions = editorOptions || {};
editorOptions.memberid = "localuser"; editorOptions.memberid = "localuser";
editorOptions.loadCallback = load; editorOptions.loadCallback = load;
@ -207,7 +219,6 @@ var webodfEditor = (function () {
function (Editor) { function (Editor) {
editorInstance = new Editor(editorOptions); editorInstance = new Editor(editorOptions);
editorInstance.initAndLoadDocument(docUrl, function (editorSession) { editorInstance.initAndLoadDocument(docUrl, function (editorSession) {
editorSession.sessionController.setUndoManager(new gui.TrivialUndoManager());
editorSession.startEditing(); editorSession.startEditing();
editorReadyCallback(editorInstance); editorReadyCallback(editorInstance);
}); });
@ -239,7 +250,7 @@ var webodfEditor = (function () {
function (Editor) { function (Editor) {
// TODO: the networkSecurityToken needs to be retrieved via now.login // TODO: the networkSecurityToken needs to be retrieved via now.login
// (but this is to be implemented later) // (but this is to be implemented later)
editorInstance = new Editor(editorOptions); editorInstance = new Editor(editorOptions, server);
// load the document and get called back when it's live // load the document and get called back when it's live
editorInstance.loadSession(sessionId, function (editorSession) { editorInstance.loadSession(sessionId, function (editorSession) {
@ -262,10 +273,9 @@ var webodfEditor = (function () {
* @returns {undefined} * @returns {undefined}
*/ */
function startLoginProcess(callback) { function startLoginProcess(callback) {
var userid, token, var userid, token;
net = runtime.getNetwork();
running = true; booting = true;
runtime.assert(editorInstance === null, "cannot boot with instanciated editor"); runtime.assert(editorInstance === null, "cannot boot with instanciated editor");
@ -278,7 +288,8 @@ var webodfEditor = (function () {
function showSessions() { function showSessions() {
var sessionListDiv = document.getElementById("sessionList"), var sessionListDiv = document.getElementById("sessionList"),
sessionList = new SessionList(net), // sessionList = new NowjsSessionList(server),
sessionList = new PullBoxSessionList(server),
sessionListView = new SessionListView(sessionList, sessionListDiv, enterSession); sessionListView = new SessionListView(sessionList, sessionListDiv, enterSession);
// hide login view // hide login view
@ -301,7 +312,7 @@ var webodfEditor = (function () {
} }
function onLoginSubmit() { function onLoginSubmit() {
net.login(document.loginForm.login.value, document.loginForm.password.value, loginSuccess, loginFail); server.login(document.loginForm.login.value, document.loginForm.password.value, loginSuccess, loginFail);
// block the submit button, we already dealt with the input // block the submit button, we already dealt with the input
return false; return false;
@ -334,7 +345,7 @@ var webodfEditor = (function () {
*/ */
function boot(args) { function boot(args) {
var editorOptions = {}, loginProcedure = startLoginProcess; var editorOptions = {}, loginProcedure = startLoginProcess;
runtime.assert(!running, "editor creation already in progress"); runtime.assert(!booting, "editor creation already in progress");
args = args || {}; args = args || {};
@ -391,7 +402,7 @@ var webodfEditor = (function () {
if (args.collaborative === "auto") { if (args.collaborative === "auto") {
runtime.log("detecting network..."); runtime.log("detecting network...");
waitForNetwork(function (state) { detectNetwork(function (state) {
if (state === "ready") { if (state === "ready") {
runtime.log("... network available."); runtime.log("... network available.");
handleNetworkedSituation(); handleNetworkedSituation();
@ -400,11 +411,10 @@ var webodfEditor = (function () {
handleNonNetworkedSituation(); handleNonNetworkedSituation();
} }
}); });
} else if ((args.collaborative === "true") || } else if ((args.collaborative === "pullbox") ||
(args.collaborative === "1") || (args.collaborative === "owncloud")) {
(args.collaborative === "yes")) { runtime.log("starting collaborative editor for ["+args.collaborative+"].");
runtime.log("starting collaborative editor."); connectNetwork(args.collaborative, function (state) {
waitForNetwork(function (state) {
if (state === "ready") { if (state === "ready") {
handleNetworkedSituation(); handleNetworkedSituation();
} }
@ -415,16 +425,7 @@ var webodfEditor = (function () {
} }
} }
function shutdown() {
running = false;
editorInstance = null;
loadedFilename = null;
}
// exposed API // exposed API
return { return { boot: boot };
boot: boot,
shutdown: shutdown
};
}()); }());

View File

@ -116,10 +116,12 @@ define("webodf/editor/widgets/simpleStyles",
appliedStyles.forEach(function(appliedStyle) { appliedStyles.forEach(function(appliedStyle) {
var textProperties = appliedStyle['style:text-properties']; var textProperties = appliedStyle['style:text-properties'];
fontWeight = fontWeight || textProperties['fo:font-weight'] === 'bold'; if (textProperties) {
fontStyle = fontStyle || textProperties['fo:font-style'] === 'italic'; fontWeight = fontWeight || textProperties['fo:font-weight'] === 'bold';
underline = underline || textProperties['style:text-underline-style'] === 'solid'; fontStyle = fontStyle || textProperties['fo:font-style'] === 'italic';
strikethrough = strikethrough || textProperties['style:text-line-through-style'] === 'solid'; underline = underline || textProperties['style:text-underline-style'] === 'solid';
strikethrough = strikethrough || textProperties['style:text-line-through-style'] === 'solid';
}
}); });
// The 3rd parameter is false to avoid firing onChange when setting the value // The 3rd parameter is false to avoid firing onChange when setting the value

View File

@ -59,7 +59,7 @@ var officeMain = {
webodfEditor.boot( webodfEditor.boot(
{ {
collaborative: 0, collaborative: "owncloud",
docUrl: doclocation, docUrl: doclocation,
callback: function() { callback: function() {
// initialized. // initialized.

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long