From 805e492e74d0f673783c46f7d27e217a0b49c174 Mon Sep 17 00:00:00 2001 From: s1341 Date: Sat, 21 Dec 2013 19:25:25 +0200 Subject: [PATCH] Handle new author info and revisions Handle upstream new revisions and added users/authors. --- src/static/js/broadcast_slider.js | 59 --------------------------- src/static/js/revisioncache.js | 49 +++++++++++++++++++++++ src/static/js/revisionslider.js | 5 ++- src/static/js/timeslider.js | 66 ++++++++++++++++++++++++++----- 4 files changed, 109 insertions(+), 70 deletions(-) diff --git a/src/static/js/broadcast_slider.js b/src/static/js/broadcast_slider.js index 659a07374..35da14198 100644 --- a/src/static/js/broadcast_slider.js +++ b/src/static/js/broadcast_slider.js @@ -52,65 +52,6 @@ function init(connection, fireWhenAllScriptsAreLoaded) $('#editorcontainerbox').css({marginTop: height}); }, 600); - function setAuthors(authors) - { - var authorsList = $("#authorsList"); - authorsList.empty(); - var numAnonymous = 0; - var numNamed = 0; - var colorsAnonymous = []; - _.each(authors, function(author) - { - var authorColor = clientVars.colorPalette[author.colorId] || author.colorId; - if (author.name) - { - if (numNamed !== 0) authorsList.append(', '); - - $('') - .text(author.name || "unnamed") - .css('background-color', authorColor) - .addClass('author') - .appendTo(authorsList); - - numNamed++; - } - else - { - numAnonymous++; - if(authorColor) colorsAnonymous.push(authorColor); - } - }); - if (numAnonymous > 0) - { - var anonymousAuthorString = html10n.get("timeslider.unnamedauthors", { num: numAnonymous }); - - if (numNamed !== 0){ - authorsList.append(' + ' + anonymousAuthorString); - } else { - authorsList.append(anonymousAuthorString); - } - - if(colorsAnonymous.length > 0){ - authorsList.append(' ('); - _.each(colorsAnonymous, function(color, i){ - if( i > 0 ) authorsList.append(' '); - $(' ') - .css('background-color', color) - .addClass('author author-anonymous') - .appendTo(authorsList); - }); - authorsList.append(')'); - } - - } - if (authors.length === 0) - { - authorsList.append(html10n.get("timeslider.toolbar.authorsList")); - } - - fixPadHeight(); - } - // assign event handlers to html UI elements after page load //$(window).load(function () fireWhenAllScriptsAreLoaded.push(function() diff --git a/src/static/js/revisioncache.js b/src/static/js/revisioncache.js index 2164dbe7f..56311cdaf 100644 --- a/src/static/js/revisioncache.js +++ b/src/static/js/revisioncache.js @@ -152,6 +152,13 @@ $.Class("RevisionCache", this.head_revision = this.getRevision(head_revnum || 0); this.loader.start(); }, + /** + * Get the head revision. + * @returns {Revision} - the head revision. + */ + getHeadRevision: function () { + return this.head_revision; + }, /** * Get a Revision instance for the specified revision number. * If we don't yet have a Revision instance for this revision, create a @@ -171,6 +178,18 @@ $.Class("RevisionCache", } return revision; }, + /** + * Add a new revision at the head. + * @param {number} revnum - the revision number of the new revision. + * @param {string} forward - the forward changeset to get here from previous head. + * @param {string} reverse - the reverse changeset. + * @param {string} timedelta - the time difference. + */ + appendHeadRevision: function (revnum, forward, reverse, timedelta) { + this.addChangesetPair(this.head_revision.revnum, revnum, forward, reverse, timedelta); + this.head_revision = this.getRevision(revnum); + //TODO: render it if we are currently at the head_revision? + }, /** * Links two revisions, specified by from and to with the changeset data * in value and reverseValue respectively. @@ -448,6 +467,7 @@ Thread("ChangesetLoader", * Enqueue a request for changesets. The changesets will be retrieved * asynchronously. * @param {number} start - The revision from which to start. + * * @param {number} granularity - The granularity of the changesets. If this * is 1, the response will include changesets which * can be applied to go from revision r to r+1. @@ -678,6 +698,7 @@ $.Class("PadClient", */ updateAuthors: function (author_info) { var authors = author_info; + console.log("[updateAuthors]: ", authors); for (var authorid in authors) { if (authorid in this.authors) { // just dispose of existing ones instead of trying to update existing @@ -689,6 +710,34 @@ $.Class("PadClient", author.addStyleRule(this.dynamicCSS); } }, + /** + * Merge a foreign (forward) changeset into our data. This involves rebuilding + * the forward changeset in our apool and building a reverse changeset. + * This is used to move new upstream changesets/revisions into our apool context. + * @param {string} changeset - The foreign changeset to merge + * @param {object} apool - The apool for that changeset + * @returns {object} - A values object with forward and reverse changesets. + */ + mergeForeignChangeset: function (changeset, apool) { + var values = {}; + values.forward = libchangeset.moveOpsToNewPool( + changeset, + (new AttribPool()).fromJsonable(apool), + this.apool + ); + var reverseValue = libchangeset.inverse( + changeset, + this.divs, + this.alines, + this.apool + ); + values.reverse = libchangeset.moveOpsToNewPool( + reverseValue, + (new AttribPool()).fromJsonable(apool), + this.apool + ); + return values; + }, /** * Get a div jquery element for a given attributed text line. * @param {string} text - The text content of the line. diff --git a/src/static/js/revisionslider.js b/src/static/js/revisionslider.js index fd2521c08..84d2a9f4c 100644 --- a/src/static/js/revisionslider.js +++ b/src/static/js/revisionslider.js @@ -98,8 +98,10 @@ $.Class("RevisionSlider", var keepPlaying = function (current_revnum) { if (current_revnum == _this.connection.getHeadRevision()) _this.is_playing = false; - if (!_this.is_playing) + if (!_this.is_playing) { + _this.render(); return; + } setTimeout(function () { _this.goToRevision(current_revnum + 1, keepPlaying); }, RevisionSlider.PLAYBACK_DELAY); @@ -113,6 +115,7 @@ $.Class("RevisionSlider", */ render: function () { this.elements.revision_label.html(html10n.get("timeslider.version", { "version": this.revision_number })); + this.slider.setMax(this.connection.getHeadRevision()); this.slider.setValue(this.revision_number); window.location.hash = "#" + this.revision_number; this.setTimestamp(this.timestamp); diff --git a/src/static/js/timeslider.js b/src/static/js/timeslider.js index cb23f8edc..b0ae00124 100644 --- a/src/static/js/timeslider.js +++ b/src/static/js/timeslider.js @@ -169,6 +169,15 @@ SocketClient("AuthenticatedSocketClient", return this; }, + /** + * Dispatch COLLABROOM messages. + * @param {object} data - The data received from the server. + */ + handle_COLLABROOM: function(data) { + //console.log("[authsocket_client] handle_COLLABROOM: ", data); + this.dispatchMessage(data.type, data); + }, + } ); @@ -186,13 +195,9 @@ AuthenticatedSocketClient("TimesliderClient", this.sendMessage("CLIENT_READY", {}, function() { console.log("CLIENT_READY sent");}); }, - // ------------------------------------------ - // Handling events - handle_CLIENT_VARS: function(data) { - console.log("[timeslider_client] handle_CLIENT_VARS: ", data); - this.clientVars = data; + initialize: function (clientVars) { + this.clientVars = clientVars; var collabClientVars = this.clientVars.collab_client_vars; - this.current_revision = this.head_revision = collabClientVars.rev; this.savedRevisions = this.clientVars.savedRevisions; this.revisionCache = new RevisionCache(this, collabClientVars.rev || 0); @@ -214,11 +219,52 @@ AuthenticatedSocketClient("TimesliderClient", this.ui = new RevisionSlider(this, $("#timeslider-top")); }, - //TODO: handle new revisions, authors etc. - handle_COLLABROOM: function(data) { - console.log("[timeslider_client] handle_COLLABROOM: ", data); + // ------------------------------------------ + // Handling events + handle_CLIENT_VARS: function(data) { + console.log("[timeslider_client] handle_CLIENT_VARS: ", data); + this.initialize(data); }, + /** + * Handle USER_NEWINFO messages, which let us know that a (new) user + * has connected to this pad. + * @param {object} data - the data received from the server. + */ + handle_USER_NEWINFO: function (data) { + console.log("[timeslider_client] handle_USER_NEWINFO: ", data.userInfo); + //TODO: we might not want to add EVERY new user to the users list, + //possibly only active users? + var authors = {}; + authors[data.userInfo.userId] = data.userInfo; + this.padClient.updateAuthors(authors); + this.ui.render(); + }, + + /** + * Handle USER_LEAVE messages, which lets us know that a user has left the + * pad. + * @param {object} data - The data received from the server. + */ + handle_USER_LEAVE: function (data) { + console.log("[timeslider_client] handle_USER_LEAVE ", data.userInfo); + }, + + /** + * Handle NEW_CHANGES messages, which lets us know that a new revision has + * been added to the pad. + * @param {object} data - The data received from the server. + */ + handle_NEW_CHANGES: function (data) { + console.log("[timeslider_client] handle_NEW_CHANGES: ", data); + var changesets = this.padClient.mergeForeignChangeset(data.changeset, data.apool); + //TODO: handle calculation of real timedela based on currenttime + //TODO: deal with author? + this.revisionCache.appendHeadRevision(data.newRev, changesets.forward, changesets.reverse, data.timeDelta); + this.ui.render(); + }, + + /** * Go to the specified revision number. This abstracts the implementation * of the actual goToRevision in the padClient. @@ -249,7 +295,7 @@ AuthenticatedSocketClient("TimesliderClient", * @return {Revision} - the head revision. */ getHeadRevision: function () { - return this.head_revision; + return this.revisionCache.getHeadRevision().revnum; }, } );