diff options
author | John McLear <john@mclear.co.uk> | 2013-01-13 10:31:45 -0800 |
---|---|---|
committer | John McLear <john@mclear.co.uk> | 2013-01-13 10:31:45 -0800 |
commit | 33e0ec209779ed04960718782ac32f122ad42726 (patch) | |
tree | 90852901d26379fef7bf3d4a05160bfe47906cb6 | |
parent | 6104987a4bae71f23fc237ac1651af195ce323b8 (diff) | |
parent | 21b99ccd53623439739929cc389e7330c66e7ede (diff) | |
download | etherpad-lite-33e0ec209779ed04960718782ac32f122ad42726.zip |
Merge pull request #1334 from mluto/load-more-chat-messages
Load more than 100 chat messages using a 'load more'-link
-rw-r--r-- | src/locales/de.json | 1 | ||||
-rw-r--r-- | src/locales/en.json | 2 | ||||
-rw-r--r-- | src/node/db/Pad.js | 26 | ||||
-rw-r--r-- | src/node/handler/PadMessageHandler.js | 106 | ||||
-rw-r--r-- | src/static/css/pad.css | 16 | ||||
-rw-r--r-- | src/static/js/chat.js | 36 | ||||
-rw-r--r-- | src/static/js/collab_client.js | 24 | ||||
-rw-r--r-- | src/static/js/pad.js | 12 | ||||
-rw-r--r-- | src/templates/pad.html | 5 | ||||
-rw-r--r-- | tests/frontend/specs/chat_load_messages.js | 85 |
10 files changed, 256 insertions, 57 deletions
diff --git a/src/locales/de.json b/src/locales/de.json index 5ede40f0..1bdbdaf3 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 c3ab8c58..37e07a15 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 <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">install abiword</a>.","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 <a href=\"https://github.com/ether/etherpad-lite/wiki/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">install abiword</a>.","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/node/db/Pad.js b/src/node/db/Pad.js index dba791fd..0914c175 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 a0bccfc5..a013f220 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 request 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,19 +848,18 @@ function handleClientReady(client, message) var pad; var historicalAuthorData = {}; var currentTime; - var chatMessages; 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 +885,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 +909,7 @@ function handleClientReady(client, message) callback(); }); }, + //get pad function(callback) { padManager.getPad(padIds.padId, function(err, value) @@ -851,7 +921,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) function(callback) { var authors = pad.getAllAuthors(); @@ -880,20 +950,11 @@ 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); }, + //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. @@ -966,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, @@ -980,11 +1043,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 diff --git a/src/static/css/pad.css b/src/static/css/pad.css index bb8da99b..bbbadbc1 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -488,6 +488,22 @@ table#otheruserstable { -ms-overflow-x: hidden; overflow-x: hidden; } +.chatloadmessages +{ + 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; position: absolute; diff --git a/src/static/js/chat.js b/src/static/js/chat.js index 79224e80..01adc34e 100644 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -28,6 +28,8 @@ var Tinycon = require('tinycon/tinycon'); var chat = (function() { var isStuck = false; + var gotInitialMessages = false; + var historyPointer = 0; var chatMentions = 0; var self = { show: function () @@ -76,7 +78,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 +114,10 @@ var chat = (function() var authorName = msg.userName == null ? _('pad.userlist.unnamed') : padutils.escapeHtml(msg.userName); var html = "<p class='" + authorClass + "'><b>" + authorName + ":</b><span class='time " + authorClass + "'>" + timeStr + "</span> " + text + "</p>"; - $("#chattext").append(html); + if(isHistoryAdd) + $(html).insertAfter('#chatloadmessagesbutton'); + else + $("#chattext").append(html); //should we increment the counter?? if(increment) @@ -125,7 +130,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("<b>"+authorName+"</b>" + ": " + text).show().delay(4000).hide(400); chatMentions++; @@ -141,8 +146,8 @@ var chat = (function() chatMentions = 0; Tinycon.setBubble(0); }); - self.scrollDown(); - + if(!isHistoryAdd) + self.scrollDown(); }, init: function(pad) { @@ -157,12 +162,23 @@ var chat = (function() } }); - var that = this; - $.each(clientVars.chatHistory, function(i, o){ - that.addMessage(o, false); - }) + // initial messages are loaded in pad.js' _afterHandshake + + $("#chatcounter").text(0); + $("#chatloadmessagesbutton").click(function() + { + var start = Math.max(self.historyPointer - 20, 0); + var end = self.historyPointer; + + if(start == end) // nothing to load + return; + + $("#chatloadmessagesbutton").css("display", "none"); + $("#chatloadmessagesball").css("display", "block"); - $("#chatcounter").text(clientVars.chatHistory.length); + 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 b700fc49..7df0b711 100644 --- a/src/static/js/collab_client.js +++ b/src/static/js/collab_client.js @@ -400,7 +400,29 @@ 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; + chat.historyPointer = clientVars.chatHead - msg.messages.length; + } + + // 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 a02d7abb..64d8b42b 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -555,6 +555,18 @@ var pad = { pad.collabClient.setOnChannelStateChange(pad.handleChannelStateChange); pad.collabClient.setOnInternalAction(pad.handleCollabAction); + // load initial chat-messages + 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 + { + $("#chatloadmessagesbutton").css("display", "none"); + } + function postAceInit() { padeditbar.init(); diff --git a/src/templates/pad.html b/src/templates/pad.html index 92f6c1ae..a4de8ed8 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -368,7 +368,10 @@ <div id="chatbox"> <div id="titlebar"><span id ="titlelabel" data-l10n-id="pad.chat"></span><a id="titlecross" onClick="chat.hide();return false;">- </a></div> - <div id="chattext" class="authorColors"></div> + <div id="chattext" class="authorColors"> + <img alt="loading.." id="chatloadmessagesball" class="chatloadmessages" src="../static/img/loading.gif" align="top"> + <button id="chatloadmessagesbutton" class="chatloadmessages" data-l10n-id="pad.chat.loadmessages"></button> + </div> <div id="chatinputbox"> <form> <input id="chatinput" type="text" maxlength="999"> diff --git a/tests/frontend/specs/chat_load_messages.js b/tests/frontend/specs/chat_load_messages.js new file mode 100644 index 00000000..8dc98691 --- /dev/null +++ b/tests/frontend/specs/chat_load_messages.js @@ -0,0 +1,85 @@ +describe("chat-load-messages", function(){ + it("creates a pad", function(done) { + helper.newPad(done); + }); + + it("adds 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}'); + } + helper.waitFor(function(){ + return chatText.children("p").length == messages; + }).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(); + 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(); + var chatText = chrome$("#chattext"); + var loadMsgBtn = chrome$("#chatloadmessagesbutton"); + + loadMsgBtn.click(); + helper.waitFor(function(){ + 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(); + var chatText = chrome$("#chattext"); + var loadMsgBtn = chrome$("#chatloadmessagesbutton"); + + loadMsgBtn.click(); + helper.waitFor(function(){ + return loadMsgBtn.css('display') == expectedDisplay; + }).always(function(){ + expect(loadMsgBtn.css('display')).to.be(expectedDisplay); + done(); + }); + }); +}); |