diff --git a/doc/api/hooks_client-side.md b/doc/api/hooks_client-side.md index 7f376defa..919859417 100644 --- a/doc/api/hooks_client-side.md +++ b/doc/api/hooks_client-side.md @@ -143,6 +143,20 @@ Things in context: This hook is called on the client side whenever a user joins or changes. This can be used to create notifications or an alternate user list. +## chatNewMessage +Called from: src/static/js/chat.js + +Things in context: + +1. authorName - The user that wrote this message +2. author - The authorID of the user that wrote the message +2. text - the message text +3. sticky (boolean) - if you want the gritter notification bubble to fade out on its own or just sit there +3. timestamp - the timestamp of the chat message +4. timeStr - the timestamp as a formatted string + +This hook is called on the client side whenever a chat message is received from the server. It can be used to create different notifications for chat messages. + ## collectContentPre Called from: src/static/js/contentcollector.js diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index ac856a604..7bb9c5db9 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -60,7 +60,7 @@ exports.doImport = function(req, res, padId) form.parse(req, function(err, fields, files) { //the upload failed, stop at this point if(err || files.file === undefined) { - console.warn("Uploading Error: " + err.stack); + if(err) console.warn("Uploading Error: " + err.stack); callback("uploadFailed"); } //everything ok, continue diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index c39f91da6..944fd98f7 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -94,7 +94,7 @@ exports.expressConfigure = function (hook_name, args, cb) { // If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158. // Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway. if (!(settings.loglevel === "WARN" || settings.loglevel == "ERROR")) - args.app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.INFO, format: ':status, :method :url'})); + args.app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.DEBUG, format: ':status, :method :url -- :response-timems'})); /* Do not let express create the session, so that we can retain a * reference to it for socket.io to use. Also, set the key (cookie diff --git a/src/package.json b/src/package.json index f2150b5d9..8278734f2 100644 --- a/src/package.json +++ b/src/package.json @@ -24,6 +24,7 @@ "uglify-js" : "1.2.5", "formidable" : "1.0.9", "log4js" : "0.5.x", + "nodemailer" : "0.3.x", "jsdom-nocontextifiy" : "0.2.10", "async-stacktrace" : "0.0.2", "npm" : "1.1.x", diff --git a/src/static/css/iframe_editor.css b/src/static/css/iframe_editor.css index 3e19cbbea..1d9b61bea 100644 --- a/src/static/css/iframe_editor.css +++ b/src/static/css/iframe_editor.css @@ -78,6 +78,7 @@ ul.list-indent8 { list-style-type: none; } body { margin: 0; white-space: nowrap; + word-wrap: normal; } #outerdocbody { @@ -93,6 +94,7 @@ body.grayedout { background-color: #eee !important } body.doesWrap { white-space: normal; + word-wrap: break-word; /* fix for issue #1648 - firefox not wrapping long lines (without spaces) correctly */ } #innerdocbody { diff --git a/src/static/css/pad.css b/src/static/css/pad.css index e536b9258..320a47202 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -828,7 +828,44 @@ input[type=checkbox] { padding: 4px 1px } } -@media screen and (max-width: 400px){ +@media all and (max-width: 400px){ + #gritter-notice-wrapper{ + max-height:172px; + overflow:hidden; + width:100% !important; + background-color: #ccc; + bottom:20px; + left:0px; + right:0px; + color:#000; + } + .gritter-close { + display:block !important; + left: auto !important; + right:5px; + } + #gritter-notice-wrapper.bottom-right{ + left:0px !important; + bottom:30px !important; + right:0px !important; + } + .gritter-item p{ + color:black; + font-size:16px; + } + .gritter-title{ + text-shadow: none !important; + color:black; + } + .gritter-item{ + padding:2px 11px 8px 4px; + } + .gritter-item-wrapper{ + margin:0; + } + .gritter-item-wrapper > div{ + background: none; + } #editorcontainer { top: 68px; } diff --git a/src/static/js/chat.js b/src/static/js/chat.js index 83a487dee..38d6f38d3 100644 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -17,6 +17,7 @@ var padutils = require('./pad_utils').padutils; var padcookie = require('./pad_cookie').padcookie; var Tinycon = require('tinycon/tinycon'); +var hooks = require('./pluginfw/hooks'); var chat = (function() { @@ -77,7 +78,7 @@ var chat = (function() $("#chatinput").val(""); }, addMessage: function(msg, increment, isHistoryAdd) - { + { //correct the time msg.time += this._pad.clientTimeOffset; @@ -99,74 +100,68 @@ var chat = (function() var text = padutils.escapeHtmlWithClickableLinks(msg.text, "_blank"); - /* Performs an action if your name is mentioned */ - var myName = $('#myusernameedit').val(); - myName = myName.toLowerCase(); - var chatText = text.toLowerCase(); - var wasMentioned = false; - if (chatText.indexOf(myName) !== -1 && myName != "undefined"){ - wasMentioned = true; + var authorName = msg.userName == null ? _('pad.userlist.unnamed') : padutils.escapeHtml(msg.userName); + + // the hook args + var ctx = { + "authorName" : authorName, + "author" : msg.userId, + "text" : text, + "sticky" : false, + "timestamp" : msg.time, + "timeStr" : timeStr } - /* End of new action */ - var authorName = msg.userName == null ? _('pad.userlist.unnamed') : padutils.escapeHtml(msg.userName); - - var html = "

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

"; - if(isHistoryAdd) - $(html).insertAfter('#chatloadmessagesbutton'); - else - $("#chattext").append(html); - - //should we increment the counter?? - if(increment && !isHistoryAdd) - { - var count = Number($("#chatcounter").text()); - count++; - - // is the users focus already in the chatbox? - var alreadyFocused = $("#chatinput").is(":focus"); - - // does the user already have the chatbox open? - var chatOpen = $("#chatbox").is(":visible"); + // is the users focus already in the chatbox? + var alreadyFocused = $("#chatinput").is(":focus"); - $("#chatcounter").text(count); - // chat throb stuff -- Just make it throw for twice as long - if(wasMentioned && !alreadyFocused && !isHistoryAdd && !chatOpen) - { // If the user was mentioned show for twice as long and flash the browser window - $.gritter.add({ - // (string | mandatory) the heading of the notification - title: authorName, - // (string | mandatory) the text inside the notification - text: text, - // (bool | optional) if you want it to fade out on its own or just sit there - sticky: true, - // (int | optional) the time you want it to be alive for before fading out - time: '2000' - }); + // does the user already have the chatbox open? + var chatOpen = $("#chatbox").is(":visible"); - chatMentions++; - Tinycon.setBubble(chatMentions); - } + // does this message contain this user's name? (is the curretn user mentioned?) + var myName = $('#myusernameedit').val(); + var wasMentioned = (text.toLowerCase().indexOf(myName.toLowerCase()) !== -1 && myName != "undefined"); + + if(wasMentioned && !alreadyFocused && !isHistoryAdd && !chatOpen) + { // If the user was mentioned show for twice as long and flash the browser window + chatMentions++; + Tinycon.setBubble(chatMentions); + ctx.sticky = true; + } + + // Call chat message hook + hooks.aCallAll("chatNewMessage", ctx, function() { + + var html = "

" + authorName + ":" + ctx.timeStr + " " + ctx.text + "

"; + if(isHistoryAdd) + $(html).insertAfter('#chatloadmessagesbutton'); else + $("#chattext").append(html); + + //should we increment the counter?? + if(increment && !isHistoryAdd) { - if(!chatOpen){ + // Update the counter of unread messages + var count = Number($("#chatcounter").text()); + count++; + $("#chatcounter").text(count); + + if(!chatOpen) { $.gritter.add({ // (string | mandatory) the heading of the notification - title: authorName, + title: ctx.authorName, // (string | mandatory) the text inside the notification - text: text, - + text: ctx.text, // (bool | optional) if you want it to fade out on its own or just sit there - sticky: false, + sticky: ctx.sticky, // (int | optional) the time you want it to be alive for before fading out time: '4000' }); - Tinycon.setBubble(count); - } } - } - // Clear the chat mentions when the user clicks on the chat input box + }); + + // Clear the chat mentions when the user clicks on the chat input box $('#chatinput').click(function(){ chatMentions = 0; Tinycon.setBubble(0); diff --git a/src/static/js/gritter.js b/src/static/js/gritter.js index c32cc758e..9778707ef 100644 --- a/src/static/js/gritter.js +++ b/src/static/js/gritter.js @@ -21,8 +21,6 @@ $.gritter.options = { position: '', class_name: '', // could be set to 'gritter-light' to use white notifications - fade_in_speed: 'medium', // how fast notifications fade in - fade_out_speed: 1000, // how fast the notices fade out time: 6000 // hang on the screen for... } diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 60a435572..e75d09b2d 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -365,8 +365,7 @@ function handshake() $.extend($.gritter.options, { position: 'bottom-right', // defaults to 'top-right' but can be 'bottom-left', 'bottom-right', 'top-left', 'top-right' (added in 1.7.1) - fade_in_speed: 'medium', // how fast notifications fade in (string or int) - fade_out_speed: 2000, // how fast the notices fade out + fade: false, // dont fade, too jerky on mobile time: 6000 // hang on the screen for... });