From 9484b92ae236888fc72a181adf3248816b52b7f0 Mon Sep 17 00:00:00 2001 From: mluto Date: Sun, 6 Jan 2013 14:55:33 +0100 Subject: [PATCH 1/8] fixed and unified indenting, added comments in handleClientReady --- src/node/handler/PadMessageHandler.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index a0bccfc51..ef70d604e 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -782,15 +782,15 @@ function handleClientReady(client, message) var padIds; async.series([ - // Get ro/rw id:s - function (callback) { + //Get ro/rw id:s + function (callback) + { readOnlyManager.getIds(message.padId, function(err, value) { if(ERR(err, callback)) return; padIds = value; callback(); }); }, - //check permissions function(callback) { @@ -816,7 +816,7 @@ function handleClientReady(client, message) } }); }, - //get all authordata of this new user + //get all authordata of this new user, and load the pad-object from the database function(callback) { async.parallel([ @@ -840,6 +840,7 @@ function handleClientReady(client, message) callback(); }); }, + //get pad function(callback) { padManager.getPad(padIds.padId, function(err, value) @@ -851,7 +852,7 @@ function handleClientReady(client, message) } ], callback); }, - //these db requests all need the pad object + //these db requests all need the pad object (timestamp of latest revission, author data, chat messages) function(callback) { var authors = pad.getAllAuthors(); @@ -894,6 +895,7 @@ function handleClientReady(client, message) ], callback); }, + //glue the clientVars together, send them and tell the other clients that a new one is there function(callback) { //Check that the client is still here. It might have disconnected between callbacks. @@ -980,11 +982,10 @@ function handleClientReady(client, message) }, "abiwordAvailable": settings.abiwordAvailable(), "plugins": { - "plugins": plugins.plugins, - "parts": plugins.parts, - }, - "initialChangesets": [] // FIXME: REMOVE THIS SHIT - + "plugins": plugins.plugins, + "parts": plugins.parts, + }, + "initialChangesets": [] // FIXME: REMOVE THIS SHIT } //Add a username to the clientVars if one avaiable From 5592c4b0feb42082ab50e1c90753c28e5cd79334 Mon Sep 17 00:00:00 2001 From: mluto Date: Sun, 6 Jan 2013 16:11:48 +0100 Subject: [PATCH 2/8] client loads messages using the new client loads messages using new method, getChatMessages restructured and renamed to getLastChatMessages, added GET_CHAT_MESSAGES, getChatMessages restructured and renamed to getLastChatMessages --- src/node/db/Pad.js | 26 ++------ src/node/handler/PadMessageHandler.js | 87 +++++++++++++++++++++++---- src/static/js/chat.js | 23 +++---- src/static/js/collab_client.js | 14 ++++- src/static/js/pad.js | 5 ++ 5 files changed, 108 insertions(+), 47 deletions(-) diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index dba791fd2..0914c175b 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -281,27 +281,7 @@ Pad.prototype.getChatMessage = function getChatMessage(entryNum, callback) { }); }; -Pad.prototype.getLastChatMessages = function getLastChatMessages(count, callback) { - //return an empty array if there are no chat messages - if(this.chatHead == -1) - { - callback(null, []); - return; - } - - var _this = this; - - //works only if we decrement the amount, for some reason - count--; - - //set the startpoint - var start = this.chatHead-count; - if(start < 0) - start = 0; - - //set the endpoint - var end = this.chatHead; - +Pad.prototype.getChatMessages = function getChatMessages(start, end, callback) { //collect the numbers of chat entries and in which order we need them var neededEntries = []; var order = 0; @@ -310,7 +290,9 @@ Pad.prototype.getLastChatMessages = function getLastChatMessages(count, callback neededEntries.push({entryNum:i, order: order}); order++; } - + + var _this = this; + //get all entries out of the database var entries = []; async.forEach(neededEntries, function(entryObject, callback) diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index ef70d604e..00eb234e4 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -205,6 +205,8 @@ exports.handleMessage = function(client, message) handleUserInfoUpdate(client, message); } else if (message.data.type == "CHAT_MESSAGE") { handleChatMessage(client, message); + } else if (message.data.type == "GET_CHAT_MESSAGES") { + handleGetChatMessages(client, message); } else if (message.data.type == "SAVE_REVISION") { handleSaveRevisionMessage(client, message); } else if (message.data.type == "CLIENT_MESSAGE" && @@ -362,6 +364,74 @@ function handleChatMessage(client, message) }); } +/** + * Handles the clients requets for more chat-messages + * @param client the client that send this message + * @param message the message from the client + */ +function handleGetChatMessages(client, message) +{ + if(message.data.start == null) + { + messageLogger.warn("Dropped message, GetChatMessages Message has no start!"); + return; + } + if(message.data.end == null) + { + messageLogger.warn("Dropped message, GetChatMessages Message has no start!"); + return; + } + + var start = message.data.start; + var end = message.data.end; + var count = start - count; + + if(count < 0 && count > 100) + { + messageLogger.warn("Dropped message, GetChatMessages Message, client requested invalid amout of messages!"); + return; + } + + var padId = sessioninfos[client.id].padId; + var pad; + + async.series([ + //get the pad + function(callback) + { + padManager.getPad(padId, function(err, _pad) + { + if(ERR(err, callback)) return; + pad = _pad; + callback(); + }); + }, + function(callback) + { + pad.getChatMessages(start, end, function(err, chatMessages) + { + if(ERR(err, callback)) return; + + var infoMsg = { + type: "COLLABROOM", + data: { + type: "CHAT_MESSAGES", + messages: chatMessages + } + }; + + // send the messages back to the client + for(var i in pad2sessions[padId]) + { + if(pad2sessions[padId][i] == client.id) + { + socketio.sockets.sockets[pad2sessions[padId][i]].json.send(infoMsg); + break; + } + } + }); + }]); +} /** * Handles a handleSuggestUserName, that means a user have suggest a userName for a other user @@ -778,7 +848,6 @@ function handleClientReady(client, message) var pad; var historicalAuthorData = {}; var currentTime; - var chatMessages; var padIds; async.series([ @@ -852,7 +921,7 @@ function handleClientReady(client, message) } ], callback); }, - //these db requests all need the pad object (timestamp of latest revission, author data, chat messages) + //these db requests all need the pad object (timestamp of latest revission, author data) function(callback) { var authors = pad.getAllAuthors(); @@ -881,16 +950,6 @@ function handleClientReady(client, message) callback(); }); }, callback); - }, - //get the latest chat messages - function(callback) - { - pad.getLastChatMessages(100, function(err, _chatMessages) - { - if(ERR(err, callback)) return; - chatMessages = _chatMessages; - callback(); - }); } ], callback); @@ -968,7 +1027,9 @@ function handleClientReady(client, message) "padId": message.padId, "initialTitle": "Pad: " + message.padId, "opts": {}, - "chatHistory": chatMessages, + // tell the client the number of the latest chat-message, which will be + // used to request the latest 100 chat-messages later (GET_CHAT_MESSAGES) + "chatHead": pad.chatHead, "numConnectedUsers": pad2sessions[padIds.padId].length, "isProPad": false, "readOnlyId": padIds.readOnlyPadId, diff --git a/src/static/js/chat.js b/src/static/js/chat.js index 79224e80c..19c4cba80 100644 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -28,6 +28,7 @@ var Tinycon = require('tinycon/tinycon'); var chat = (function() { var isStuck = false; + var gotInitialMessages = false; var chatMentions = 0; var self = { show: function () @@ -76,7 +77,7 @@ var chat = (function() this._pad.collabClient.sendMessage({"type": "CHAT_MESSAGE", "text": text}); $("#chatinput").val(""); }, - addMessage: function(msg, increment) + addMessage: function(msg, increment, isHistoryAdd) { //correct the time msg.time += this._pad.clientTimeOffset; @@ -112,7 +113,10 @@ var chat = (function() var authorName = msg.userName == null ? _('pad.userlist.unnamed') : padutils.escapeHtml(msg.userName); var html = "

" + authorName + ":" + timeStr + " " + text + "

"; - $("#chattext").append(html); + if(isHistoryAdd) + $("#chattext").prepend(html); + else + $("#chattext").append(html); //should we increment the counter?? if(increment) @@ -125,7 +129,7 @@ var chat = (function() $("#chatcounter").text(count); // chat throb stuff -- Just make it throw for twice as long - if(wasMentioned && !alreadyFocused) + if(wasMentioned && !alreadyFocused && !isHistoryAdd) { // If the user was mentioned show for twice as long and flash the browser window $('#chatthrob').html(""+authorName+"" + ": " + text).show().delay(4000).hide(400); chatMentions++; @@ -141,8 +145,8 @@ var chat = (function() chatMentions = 0; Tinycon.setBubble(0); }); - self.scrollDown(); - + if(!isHistoryAdd) + self.scrollDown(); }, init: function(pad) { @@ -157,12 +161,9 @@ var chat = (function() } }); - var that = this; - $.each(clientVars.chatHistory, function(i, o){ - that.addMessage(o, false); - }) - - $("#chatcounter").text(clientVars.chatHistory.length); + // initial messages are loaded in pad.js' _afterHandshake + + $("#chatcounter").text(0); } } diff --git a/src/static/js/collab_client.js b/src/static/js/collab_client.js index b700fc490..29c404828 100644 --- a/src/static/js/collab_client.js +++ b/src/static/js/collab_client.js @@ -400,7 +400,19 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) } else if (msg.type == "CHAT_MESSAGE") { - chat.addMessage(msg, true); + chat.addMessage(msg, true, false); + } + else if (msg.type == "CHAT_MESSAGES") + { + for(var i = msg.messages.length - 1; i >= 0; i--) + { + chat.addMessage(msg.messages[i], true, true); + } + if(!chat.gotInitalMessages) + { + chat.scrollDown(); + chat.gotInitalMessages = true; + } } else if (msg.type == "SERVER_MESSAGE") { diff --git a/src/static/js/pad.js b/src/static/js/pad.js index a02d7abbc..56a1dad7c 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -555,6 +555,11 @@ var pad = { pad.collabClient.setOnChannelStateChange(pad.handleChannelStateChange); pad.collabClient.setOnInternalAction(pad.handleCollabAction); + // load initial chat-messages + var chatHead = clientVars.chatHead; + var start = Math.max(chatHead - 100, 0); + pad.collabClient.sendMessage({"type": "GET_CHAT_MESSAGES", "start": start, "end": chatHead}); + function postAceInit() { padeditbar.init(); From 5f81daed0ae9b8e147d00724516b5002dc77f289 Mon Sep 17 00:00:00 2001 From: mluto Date: Mon, 7 Jan 2013 17:36:03 +0100 Subject: [PATCH 3/8] Added link to load more chat-messages using new GET_CHAT_MESSAGES --- src/locales/de.json | 1 + src/locales/en.json | 2 +- src/static/css/pad.css | 5 +++++ src/static/js/chat.js | 16 +++++++++++++++- src/static/js/collab_client.js | 5 ++++- src/static/js/pad.js | 13 ++++++++++--- src/templates/pad.html | 2 +- 7 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/locales/de.json b/src/locales/de.json index 5ede40f08..1bdbdaf3d 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -81,6 +81,7 @@ "pad.share.emebdcode": "In Webseite einbetten", "pad.chat": "Chat", "pad.chat.title": "Den Chat dieses Pads \u00f6ffnen", + "pad.chat.loadmessages": "Weitere Nachrichten laden", "timeslider.pageTitle": "{{appTitle}} Pad-Versionsgeschichte", "timeslider.toolbar.returnbutton": "Zur\u00fcck zum Pad", "timeslider.toolbar.authors": "Autoren:", diff --git a/src/locales/en.json b/src/locales/en.json index c3ab8c583..37e07a154 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1 +1 @@ -{"index.newPad":"New Pad","index.createOpenPad":"or create/open a Pad with the name:","pad.toolbar.bold.title":"Bold (Ctrl-B)","pad.toolbar.italic.title":"Italic (Ctrl-I)","pad.toolbar.underline.title":"Underline (Ctrl-U)","pad.toolbar.strikethrough.title":"Strikethrough","pad.toolbar.ol.title":"Ordered list","pad.toolbar.ul.title":"Unordered List","pad.toolbar.indent.title":"Indent","pad.toolbar.unindent.title":"Outdent","pad.toolbar.undo.title":"Undo (Ctrl-Z)","pad.toolbar.redo.title":"Redo (Ctrl-Y)","pad.toolbar.clearAuthorship.title":"Clear Authorship Colors","pad.toolbar.import_export.title":"Import/Export from/to different file formats","pad.toolbar.timeslider.title":"Timeslider","pad.toolbar.savedRevision.title":"Saved Revisions","pad.toolbar.settings.title":"Settings","pad.toolbar.embed.title":"Embed this pad","pad.toolbar.showusers.title":"Show the users on this pad","pad.colorpicker.save":"Save","pad.colorpicker.cancel":"Cancel","pad.loading":"Loading...","pad.passwordRequired":"You need a password to access this pad","pad.permissionDenied":"You do not have permission to access this pad","pad.wrongPassword":"Your password was wrong","pad.settings.padSettings":"Pad Settings","pad.settings.myView":"My View","pad.settings.stickychat":"Chat always on screen","pad.settings.colorcheck":"Authorship colors","pad.settings.linenocheck":"Line numbers","pad.settings.fontType":"Font type:","pad.settings.fontType.normal":"Normal","pad.settings.fontType.monospaced":"Monospace","pad.settings.globalView":"Global View","pad.settings.language":"Language:","pad.importExport.import_export":"Import/Export","pad.importExport.import":"Upload any text file or document","pad.importExport.importSuccessful":"Successful!","pad.importExport.export":"Export current pad as:","pad.importExport.exporthtml":"HTML","pad.importExport.exportplain":"Plain text","pad.importExport.exportword":"Microsoft Word","pad.importExport.exportpdf":"PDF","pad.importExport.exportopen":"ODF (Open Document Format)","pad.importExport.exportdokuwiki":"DokuWiki","pad.importExport.abiword.innerHTML":"You only can import from plain text or html formats. For more advanced import features please install abiword.","pad.modals.connected":"Connected.","pad.modals.reconnecting":"Reconnecting to your pad..","pad.modals.forcereconnect":"Force reconnect","pad.modals.userdup":"Opened in another window","pad.modals.userdup.explanation":"This pad seems to be opened in more than one browser window on this computer.","pad.modals.userdup.advice":"Reconnect to use this window instead.","pad.modals.unauth":"Not authorized","pad.modals.unauth.explanation":"Your permissions have changed while viewing this page. Try to reconnect.","pad.modals.looping":"Disconnected.","pad.modals.looping.explanation":"There are communication problems with the synchronization server.","pad.modals.looping.cause":"Perhaps you connected through an incompatible firewall or proxy.","pad.modals.initsocketfail":"Server is unreachable.","pad.modals.initsocketfail.explanation":"Couldn't connect to the synchronization server.","pad.modals.initsocketfail.cause":"This is probably due to a problem with your browser or your internet connection.","pad.modals.slowcommit":"Disconnected.","pad.modals.slowcommit.explanation":"The server is not responding.","pad.modals.slowcommit.cause":"This could be due to problems with network connectivity.","pad.modals.deleted":"Deleted.","pad.modals.deleted.explanation":"This pad has been removed.","pad.modals.disconnected":"You have been disconnected.","pad.modals.disconnected.explanation":"The connection to the server was lost","pad.modals.disconnected.cause":"The server may be unavailable. Please notify us if this continues to happen.","pad.share":"Share this pad","pad.share.readonly":"Read only","pad.share.link":"Link","pad.share.emebdcode":"Embed URL","pad.chat":"Chat","pad.chat.title":"Open the chat for this pad.","timeslider.pageTitle":"{{appTitle}} Timeslider","timeslider.toolbar.returnbutton":"Return to pad","timeslider.toolbar.authors":"Authors:","timeslider.toolbar.authorsList":"No Authors","timeslider.toolbar.exportlink.title":"Export","timeslider.exportCurrent":"Export current version as:","timeslider.version":"Version {{version}}","timeslider.saved":"Saved {{month}} {{day}}, {{year}}","timeslider.dateformat":"{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}","timeslider.month.january":"January","timeslider.month.february":"February","timeslider.month.march":"March","timeslider.month.april":"April","timeslider.month.may":"May","timeslider.month.june":"June","timeslider.month.july":"July","timeslider.month.august":"August","timeslider.month.september":"September","timeslider.month.october":"October","timeslider.month.november":"November","timeslider.month.december":"December","pad.savedrevs.marked":"This revision is now marked as a saved revision","pad.userlist.entername":"Enter your name","pad.userlist.unnamed":"unnamed","pad.userlist.guest":"Guest","pad.userlist.deny":"Deny","pad.userlist.approve":"Approve","pad.editbar.clearcolors":"Clear authorship colors on entire document?","pad.impexp.importbutton":"Import Now","pad.impexp.importing":"Importing...","pad.impexp.confirmimport":"Importing a file will overwrite the current text of the pad. Are you sure you want to proceed?","pad.impexp.convertFailed":"We were not able to import this file. Please use a different document format or copy paste manually","pad.impexp.uploadFailed":"The upload failed, please try again","pad.impexp.importfailed":"Import failed","pad.impexp.copypaste":"Please copy paste","pad.impexp.exportdisabled":"Exporting as {{type}} format is disabled. Please contact your system administrator for details."} \ No newline at end of file +{"index.newPad":"New Pad","index.createOpenPad":"or create/open a Pad with the name:","pad.toolbar.bold.title":"Bold (Ctrl-B)","pad.toolbar.italic.title":"Italic (Ctrl-I)","pad.toolbar.underline.title":"Underline (Ctrl-U)","pad.toolbar.strikethrough.title":"Strikethrough","pad.toolbar.ol.title":"Ordered list","pad.toolbar.ul.title":"Unordered List","pad.toolbar.indent.title":"Indent","pad.toolbar.unindent.title":"Outdent","pad.toolbar.undo.title":"Undo (Ctrl-Z)","pad.toolbar.redo.title":"Redo (Ctrl-Y)","pad.toolbar.clearAuthorship.title":"Clear Authorship Colors","pad.toolbar.import_export.title":"Import/Export from/to different file formats","pad.toolbar.timeslider.title":"Timeslider","pad.toolbar.savedRevision.title":"Saved Revisions","pad.toolbar.settings.title":"Settings","pad.toolbar.embed.title":"Embed this pad","pad.toolbar.showusers.title":"Show the users on this pad","pad.colorpicker.save":"Save","pad.colorpicker.cancel":"Cancel","pad.loading":"Loading...","pad.passwordRequired":"You need a password to access this pad","pad.permissionDenied":"You do not have permission to access this pad","pad.wrongPassword":"Your password was wrong","pad.settings.padSettings":"Pad Settings","pad.settings.myView":"My View","pad.settings.stickychat":"Chat always on screen","pad.settings.colorcheck":"Authorship colors","pad.settings.linenocheck":"Line numbers","pad.settings.fontType":"Font type:","pad.settings.fontType.normal":"Normal","pad.settings.fontType.monospaced":"Monospace","pad.settings.globalView":"Global View","pad.settings.language":"Language:","pad.importExport.import_export":"Import/Export","pad.importExport.import":"Upload any text file or document","pad.importExport.importSuccessful":"Successful!","pad.importExport.export":"Export current pad as:","pad.importExport.exporthtml":"HTML","pad.importExport.exportplain":"Plain text","pad.importExport.exportword":"Microsoft Word","pad.importExport.exportpdf":"PDF","pad.importExport.exportopen":"ODF (Open Document Format)","pad.importExport.exportdokuwiki":"DokuWiki","pad.importExport.abiword.innerHTML":"You only can import from plain text or html formats. For more advanced import features please install abiword.","pad.modals.connected":"Connected.","pad.modals.reconnecting":"Reconnecting to your pad..","pad.modals.forcereconnect":"Force reconnect","pad.modals.userdup":"Opened in another window","pad.modals.userdup.explanation":"This pad seems to be opened in more than one browser window on this computer.","pad.modals.userdup.advice":"Reconnect to use this window instead.","pad.modals.unauth":"Not authorized","pad.modals.unauth.explanation":"Your permissions have changed while viewing this page. Try to reconnect.","pad.modals.looping":"Disconnected.","pad.modals.looping.explanation":"There are communication problems with the synchronization server.","pad.modals.looping.cause":"Perhaps you connected through an incompatible firewall or proxy.","pad.modals.initsocketfail":"Server is unreachable.","pad.modals.initsocketfail.explanation":"Couldn't connect to the synchronization server.","pad.modals.initsocketfail.cause":"This is probably due to a problem with your browser or your internet connection.","pad.modals.slowcommit":"Disconnected.","pad.modals.slowcommit.explanation":"The server is not responding.","pad.modals.slowcommit.cause":"This could be due to problems with network connectivity.","pad.modals.deleted":"Deleted.","pad.modals.deleted.explanation":"This pad has been removed.","pad.modals.disconnected":"You have been disconnected.","pad.modals.disconnected.explanation":"The connection to the server was lost","pad.modals.disconnected.cause":"The server may be unavailable. Please notify us if this continues to happen.","pad.share":"Share this pad","pad.share.readonly":"Read only","pad.share.link":"Link","pad.share.emebdcode":"Embed URL","pad.chat":"Chat","pad.chat.title":"Open the chat for this pad.","pad.chat.loadmessages": "Load more messages","timeslider.pageTitle":"{{appTitle}} Timeslider","timeslider.toolbar.returnbutton":"Return to pad","timeslider.toolbar.authors":"Authors:","timeslider.toolbar.authorsList":"No Authors","timeslider.toolbar.exportlink.title":"Export","timeslider.exportCurrent":"Export current version as:","timeslider.version":"Version {{version}}","timeslider.saved":"Saved {{month}} {{day}}, {{year}}","timeslider.dateformat":"{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}","timeslider.month.january":"January","timeslider.month.february":"February","timeslider.month.march":"March","timeslider.month.april":"April","timeslider.month.may":"May","timeslider.month.june":"June","timeslider.month.july":"July","timeslider.month.august":"August","timeslider.month.september":"September","timeslider.month.october":"October","timeslider.month.november":"November","timeslider.month.december":"December","pad.savedrevs.marked":"This revision is now marked as a saved revision","pad.userlist.entername":"Enter your name","pad.userlist.unnamed":"unnamed","pad.userlist.guest":"Guest","pad.userlist.deny":"Deny","pad.userlist.approve":"Approve","pad.editbar.clearcolors":"Clear authorship colors on entire document?","pad.impexp.importbutton":"Import Now","pad.impexp.importing":"Importing...","pad.impexp.confirmimport":"Importing a file will overwrite the current text of the pad. Are you sure you want to proceed?","pad.impexp.convertFailed":"We were not able to import this file. Please use a different document format or copy paste manually","pad.impexp.uploadFailed":"The upload failed, please try again","pad.impexp.importfailed":"Import failed","pad.impexp.copypaste":"Please copy paste","pad.impexp.exportdisabled":"Exporting as {{type}} format is disabled. Please contact your system administrator for details."} \ No newline at end of file diff --git a/src/static/css/pad.css b/src/static/css/pad.css index bb8da99b6..a36a7ff9c 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -488,6 +488,11 @@ table#otheruserstable { -ms-overflow-x: hidden; overflow-x: hidden; } +#chatloadmessages +{ + color: blue; + text-decoration: underline; +} #chatinputbox { padding: 3px 2px; position: absolute; diff --git a/src/static/js/chat.js b/src/static/js/chat.js index 19c4cba80..2136c56c1 100644 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -29,6 +29,7 @@ var chat = (function() { var isStuck = false; var gotInitialMessages = false; + var historyPointer = 0; var chatMentions = 0; var self = { show: function () @@ -114,7 +115,7 @@ var chat = (function() var html = "

" + authorName + ":" + timeStr + " " + text + "

"; if(isHistoryAdd) - $("#chattext").prepend(html); + $(html).insertAfter('#chatloadmessages'); else $("#chattext").append(html); @@ -164,6 +165,19 @@ var chat = (function() // initial messages are loaded in pad.js' _afterHandshake $("#chatcounter").text(0); + $("#chatloadmessages").click(function() + { + var start = Math.max(self.historyPointer - 100, 0); + var end = self.historyPointer; + + if(start == end) // nothing to load + return; + if(start == 0) // reached the top + $("#chatloadmessages").css("display", "none"); + + pad.collabClient.sendMessage({"type": "GET_CHAT_MESSAGES", "start": start, "end": end}); + self.historyPointer = start; + }); } } diff --git a/src/static/js/collab_client.js b/src/static/js/collab_client.js index 29c404828..902301d50 100644 --- a/src/static/js/collab_client.js +++ b/src/static/js/collab_client.js @@ -411,7 +411,10 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) if(!chat.gotInitalMessages) { chat.scrollDown(); - chat.gotInitalMessages = true; + chat.gotInitalMessages = true; + chat.historyPointer = clientVars.chatHead - msg.messages.length; + if(chat.historyPointer == -1) // there are less than 100 messages + $("#chatloadmessages").css("display", "none"); } } else if (msg.type == "SERVER_MESSAGE") diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 56a1dad7c..57aa2834e 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -556,9 +556,16 @@ var pad = { pad.collabClient.setOnInternalAction(pad.handleCollabAction); // load initial chat-messages - var chatHead = clientVars.chatHead; - var start = Math.max(chatHead - 100, 0); - pad.collabClient.sendMessage({"type": "GET_CHAT_MESSAGES", "start": start, "end": chatHead}); + if(clientVars.chatHead != -1) + { + var chatHead = clientVars.chatHead; + var start = Math.max(chatHead - 100, 0); + pad.collabClient.sendMessage({"type": "GET_CHAT_MESSAGES", "start": start, "end": chatHead}); + } + else // there are no messages + { + $("#chatloadmessages").css("display", "none"); + } function postAceInit() { diff --git a/src/templates/pad.html b/src/templates/pad.html index a9313a1be..780ceaaa0 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -368,7 +368,7 @@
-
+
From 825b258d995f3c1512af20124d9c72768014ef09 Mon Sep 17 00:00:00 2001 From: mluto Date: Mon, 7 Jan 2013 17:43:03 +0100 Subject: [PATCH 4/8] only load 20 messages when pressing the load-link, fixed whitespace --- src/static/js/chat.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/static/js/chat.js b/src/static/js/chat.js index 2136c56c1..edd6c500a 100644 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -167,9 +167,9 @@ var chat = (function() $("#chatcounter").text(0); $("#chatloadmessages").click(function() { - var start = Math.max(self.historyPointer - 100, 0); - var end = self.historyPointer; - + var start = Math.max(self.historyPointer - 20, 0); + var end = self.historyPointer; + if(start == end) // nothing to load return; if(start == 0) // reached the top From bc05f9eb0adf5d9f674159106644f64d363e62e1 Mon Sep 17 00:00:00 2001 From: mluto Date: Mon, 7 Jan 2013 19:15:55 +0100 Subject: [PATCH 5/8] converted load-more-link to button, added loading-gif, fixed typo --- src/node/handler/PadMessageHandler.js | 2 +- src/static/css/pad.css | 17 ++++++++++++++--- src/static/js/chat.js | 9 +++++---- src/static/js/collab_client.js | 11 +++++++++-- src/static/js/pad.js | 2 +- src/templates/pad.html | 5 ++++- 6 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index 00eb234e4..a013f2203 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -365,7 +365,7 @@ function handleChatMessage(client, message) } /** - * Handles the clients requets for more chat-messages + * Handles the clients request for more chat-messages * @param client the client that send this message * @param message the message from the client */ diff --git a/src/static/css/pad.css b/src/static/css/pad.css index a36a7ff9c..bbbadbc18 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -488,10 +488,21 @@ table#otheruserstable { -ms-overflow-x: hidden; overflow-x: hidden; } -#chatloadmessages +.chatloadmessages { - color: blue; - text-decoration: underline; + margin-bottom: 5px; + margin-top: 5px; + margin-left: auto; + margin-right: auto; + display: block; +} +#chatloadmessagesbutton +{ + line-height: 1.8em; +} +#chatloadmessagesball +{ + display: none; } #chatinputbox { padding: 3px 2px; diff --git a/src/static/js/chat.js b/src/static/js/chat.js index edd6c500a..01adc34e8 100644 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -115,7 +115,7 @@ var chat = (function() var html = "

" + authorName + ":" + timeStr + " " + text + "

"; if(isHistoryAdd) - $(html).insertAfter('#chatloadmessages'); + $(html).insertAfter('#chatloadmessagesbutton'); else $("#chattext").append(html); @@ -165,15 +165,16 @@ var chat = (function() // initial messages are loaded in pad.js' _afterHandshake $("#chatcounter").text(0); - $("#chatloadmessages").click(function() + $("#chatloadmessagesbutton").click(function() { var start = Math.max(self.historyPointer - 20, 0); var end = self.historyPointer; if(start == end) // nothing to load return; - if(start == 0) // reached the top - $("#chatloadmessages").css("display", "none"); + + $("#chatloadmessagesbutton").css("display", "none"); + $("#chatloadmessagesball").css("display", "block"); pad.collabClient.sendMessage({"type": "GET_CHAT_MESSAGES", "start": start, "end": end}); self.historyPointer = start; diff --git a/src/static/js/collab_client.js b/src/static/js/collab_client.js index 902301d50..7df0b7114 100644 --- a/src/static/js/collab_client.js +++ b/src/static/js/collab_client.js @@ -413,9 +413,16 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) chat.scrollDown(); chat.gotInitalMessages = true; chat.historyPointer = clientVars.chatHead - msg.messages.length; - if(chat.historyPointer == -1) // there are less than 100 messages - $("#chatloadmessages").css("display", "none"); } + + // messages are loaded, so hide the loading-ball + $("#chatloadmessagesball").css("display", "none"); + + // there are less than 100 messages or we reached the top + if(chat.historyPointer <= 0) + $("#chatloadmessagesbutton").css("display", "none"); + else // there are still more messages, re-show the load-button + $("#chatloadmessagesbutton").css("display", "block"); } else if (msg.type == "SERVER_MESSAGE") { diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 57aa2834e..64d8b42b8 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -564,7 +564,7 @@ var pad = { } else // there are no messages { - $("#chatloadmessages").css("display", "none"); + $("#chatloadmessagesbutton").css("display", "none"); } function postAceInit() diff --git a/src/templates/pad.html b/src/templates/pad.html index 780ceaaa0..cbfdc5276 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -368,7 +368,10 @@
-
+
+ loading.. + +
From 176719b331c3b6880afc3c258a9a0865ee4af2c6 Mon Sep 17 00:00:00 2001 From: mluto Date: Sun, 13 Jan 2013 10:39:13 +0100 Subject: [PATCH 6/8] Added tests --- tests/frontend/specs/chat_load_messages.js | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tests/frontend/specs/chat_load_messages.js diff --git a/tests/frontend/specs/chat_load_messages.js b/tests/frontend/specs/chat_load_messages.js new file mode 100644 index 000000000..710064139 --- /dev/null +++ b/tests/frontend/specs/chat_load_messages.js @@ -0,0 +1,70 @@ +describe("chat-load-messages", function(){ + it("create pad", function(done) { + helper.newPad(done); + }); + + it("add a lot of messages", function(done) { + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + var chatButton = chrome$("#chaticon"); + chatButton.click(); + var chatInput = chrome$("#chatinput"); + var chatText = chrome$("#chattext"); + + var messages = 140; + for(var i=1; i <= messages; i++) { + var num = ''+i; + if(num.length == 1) + num = '00'+num; + if(num.length == 2) + num = '0'+num; + chatInput.sendkeys('msg' + num); + chatInput.sendkeys('{enter}'); + } + setTimeout(function() { + expect(chatText.children("p").length).to.be(messages); + $('#iframe-container iframe')[0].contentWindow.location.reload(); + done(); + }, 500); + }); + + it("check initial message count", function(done) { + setTimeout(function() { + var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; + var chatButton = chrome$("#chaticon"); + chatButton.click(); + var chatText = chrome$("#chattext"); + + expect(chatText.children("p").length).to.be(101); + done(); + }, 500); + }); + + it("load more messages", function(done) { + var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; + var chatButton = chrome$("#chaticon"); + chatButton.click(); + var chatText = chrome$("#chattext"); + var loadMsgBtn = chrome$("#chatloadmessagesbutton"); + + loadMsgBtn.click(); + setTimeout(function() { + expect(chatText.children("p").length).to.be(122); + done(); + }, 500); + }); + + it("btn vanishes", function(done) { + var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; + var chatButton = chrome$("#chaticon"); + chatButton.click(); + var chatText = chrome$("#chattext"); + var loadMsgBtn = chrome$("#chatloadmessagesbutton"); + + loadMsgBtn.click(); + setTimeout(function() { + expect(loadMsgBtn.css('display')).to.be('none'); + done(); + }, 200); + }); +}); From c3dd433c990acbfb37a639b658dbb4d849d1620b Mon Sep 17 00:00:00 2001 From: mluto Date: Sun, 13 Jan 2013 11:03:52 +0100 Subject: [PATCH 7/8] Fixed test-names, use waitFor instead of setTimeout --- tests/frontend/specs/chat_load_messages.js | 51 +++++++++++----------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/tests/frontend/specs/chat_load_messages.js b/tests/frontend/specs/chat_load_messages.js index 710064139..6d702b9bf 100644 --- a/tests/frontend/specs/chat_load_messages.js +++ b/tests/frontend/specs/chat_load_messages.js @@ -1,9 +1,9 @@ describe("chat-load-messages", function(){ - it("create pad", function(done) { + it("creates a pad", function(done) { helper.newPad(done); }); - it("add a lot of messages", function(done) { + it("adds a lot of messages", function(done) { var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; var chatButton = chrome$("#chaticon"); @@ -21,26 +21,29 @@ describe("chat-load-messages", function(){ chatInput.sendkeys('msg' + num); chatInput.sendkeys('{enter}'); } - setTimeout(function() { - expect(chatText.children("p").length).to.be(messages); + helper.waitFor(function(){ + return chatText.children("p").length == messages; + }).done(function(){ $('#iframe-container iframe')[0].contentWindow.location.reload(); done(); - }, 500); + }); }); - it("check initial message count", function(done) { - setTimeout(function() { - var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; - var chatButton = chrome$("#chaticon"); - chatButton.click(); - var chatText = chrome$("#chattext"); - - expect(chatText.children("p").length).to.be(101); - done(); - }, 500); + it("checks initial message count", function(done) { + helper.waitFor(function(){ + // wait for the frame to load + var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; + if(!chrome$) // page not fully loaded + return false; + + var chatButton = chrome$("#chaticon"); + chatButton.click(); + var chatText = chrome$("#chattext"); + return chatText.children("p").length == 101; + }).done(done); }); - it("load more messages", function(done) { + it("loads more messages", function(done) { var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; var chatButton = chrome$("#chaticon"); chatButton.click(); @@ -48,13 +51,12 @@ describe("chat-load-messages", function(){ var loadMsgBtn = chrome$("#chatloadmessagesbutton"); loadMsgBtn.click(); - setTimeout(function() { - expect(chatText.children("p").length).to.be(122); - done(); - }, 500); + helper.waitFor(function(){ + return chatText.children("p").length == 122; + }).done(done); }); - it("btn vanishes", function(done) { + it("checks for button vanishing", function(done) { var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; var chatButton = chrome$("#chaticon"); chatButton.click(); @@ -62,9 +64,8 @@ describe("chat-load-messages", function(){ var loadMsgBtn = chrome$("#chatloadmessagesbutton"); loadMsgBtn.click(); - setTimeout(function() { - expect(loadMsgBtn.css('display')).to.be('none'); - done(); - }, 200); + helper.waitFor(function(){ + return loadMsgBtn.css('display') == 'none'; + }).done(done); }); }); From 21b99ccd53623439739929cc389e7330c66e7ede Mon Sep 17 00:00:00 2001 From: mluto Date: Sun, 13 Jan 2013 11:29:28 +0100 Subject: [PATCH 8/8] use always() instead of done() and call expect() in there, fixed whitespace --- tests/frontend/specs/chat_load_messages.js | 44 ++++++++++++++-------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/tests/frontend/specs/chat_load_messages.js b/tests/frontend/specs/chat_load_messages.js index 6d702b9bf..8dc98691e 100644 --- a/tests/frontend/specs/chat_load_messages.js +++ b/tests/frontend/specs/chat_load_messages.js @@ -23,27 +23,34 @@ describe("chat-load-messages", function(){ } helper.waitFor(function(){ return chatText.children("p").length == messages; - }).done(function(){ + }).always(function(){ + expect(chatText.children("p").length).to.be(messages); $('#iframe-container iframe')[0].contentWindow.location.reload(); done(); }); }); it("checks initial message count", function(done) { + var chatText; + var expectedCount = 101; helper.waitFor(function(){ - // wait for the frame to load - var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; - if(!chrome$) // page not fully loaded - return false; - - var chatButton = chrome$("#chaticon"); - chatButton.click(); - var chatText = chrome$("#chattext"); - return chatText.children("p").length == 101; - }).done(done); + // wait for the frame to load + var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; + if(!chrome$) // page not fully loaded + return false; + + var chatButton = chrome$("#chaticon"); + chatButton.click(); + chatText = chrome$("#chattext"); + return chatText.children("p").length == expectedCount; + }).always(function(){ + expect(chatText.children("p").length).to.be(expectedCount); + done(); + }); }); it("loads more messages", function(done) { + var expectedCount = 122; var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; var chatButton = chrome$("#chaticon"); chatButton.click(); @@ -52,11 +59,15 @@ describe("chat-load-messages", function(){ loadMsgBtn.click(); helper.waitFor(function(){ - return chatText.children("p").length == 122; - }).done(done); + return chatText.children("p").length == expectedCount; + }).always(function(){ + expect(chatText.children("p").length).to.be(expectedCount); + done(); + }); }); it("checks for button vanishing", function(done) { + var expectedDisplay = 'none'; var chrome$ = $('#iframe-container iframe')[0].contentWindow.$; var chatButton = chrome$("#chaticon"); chatButton.click(); @@ -65,7 +76,10 @@ describe("chat-load-messages", function(){ loadMsgBtn.click(); helper.waitFor(function(){ - return loadMsgBtn.css('display') == 'none'; - }).done(done); + return loadMsgBtn.css('display') == expectedDisplay; + }).always(function(){ + expect(loadMsgBtn.css('display')).to.be(expectedDisplay); + done(); + }); }); });