PM/Chat Plugin - break it or leave it. V1.4.5 & 2.3-beta



  • Thanks for all the people who send me PM today and allowed me to get the plugin to version 1.0

    The code is obscure and safe and no warranty is provided.

    Features

    • direct access to the last ~15 pm
    • shows if new or how many unread messages in a conversation
    • quick preview of the last replies inline
    • participants avatars in conversation, hover to get name tooltip if needed.

    Known stuff & miscellaneous

    * preview messages does not show date and time - what a shame

    • preview is stealth and will not mark messages as read.

    • developed on desktop was not tested or design for mobile.

    * The plugin does not auto-refresh, if you want to update you have to open the envelope.
    the other notification will show you if you have new message anyway.

    * I started the idea of adding an inline reply in the preview section to provide a chat like interface but this feature is not there yet.

    • run in console and should work if add to an extension(greasemonkey)

    • security: The preview functionality almost got me with xss. I was trying to show a text version only due to visual issues,The conversion allowed html tag to be rendered. I moved back to just rendering the "cooked" version
      and instead added some styling to fix the visual issues. I consider it pretty safe on that aspect, but testing is welcomed.

    * there is a small bug, it may show 1 even if there are no messages need attention blah
    • 1/20/2014: click on @mention in the preview will go to the user page as a new page which will reset the widget

    ###Inline preview of the last replies

    ###code (Version 1.4.5)

    (function(f){f.Styler||(f.Styler=new function(){var c={};this.loadStyle=function(a,h){c.hasOwnProperty(a)?0==c[a].added&&(c[a].content=h,this.appendStyle(a)):(c[a]={content:h,added:!1},this.appendStyle(a))};this.listLoadedStyles=function(){};this.removeStyle=function(a){c.hasOwnProperty(a)&&(c[a].added=!1,f("#Styler_"+a).remove())};this.appendStyle=function(a){c.hasOwnProperty(a)&&(c[a].added=!0,a=f("<style id='Styler_"+a+"'>"+c[a].content+"</style>"),f("body").append(a))}})})(jQuery);
    window.APIHelper=new function(){this.get_last_page=function(f,c){window.Messages_plugin.getCache();var a=window.Messages_plugin.get_topic_data(f),h=a.preview_posts.last_post_number||1,n=void 0===a.preview_posts.last_post_number,k=Math.ceil(h/20);$.getJSON("http://what.thedailywtf.com/t/"+f+".json?page="+k,function(a){var g=Math.ceil(a.posts_count/20),q=20-(20-h%20);g>k?0==q||n?$.getJSON("http://what.thedailywtf.com/t/"+f+".json?page="+g,c):c(a):c(a)})}};
    window.Messages_plugin=function(){function f(a){if(null===g.json_result||null===g.last_fetch_time||1E4<Date.now()-g.last_fetch_time){var b=Discourse.User.current();b&&(b="http://what.thedailywtf.com/topics/private-messages/"+b.username+".json?_="+Date.now(),$.getJSON(b).then(function(b){g.json_result=b;a(b)}),g.last_fetch_time=Date.now())}else a(g.json_result)}function c(a,b){var p=$("<div></div>");_.forEach(a.posters,function(d){var e=_.find(b.users,{id:d.user_id});d=e.username;e=$("<img src='"+
    e.avatar_template.replace("{size}","20")+"'></img>");e.attr("title",d);p.append(e)});return p}function a(a){var b=a.topic_list.topics;n.find("div.loading").hide();g.unseen=0;var p=0<n.find("li").length;_.first(b,15).forEach(function(d){if(l.hasOwnProperty(d.id))return!0;var e="<span style='float:right;margin-top:-2px;padding:3px;border-radius: 3px;'>"+Discourse.Formatter.relativeAge(new Date(d.last_posted_at),{format:"tiny",wrapInSpan:!1})+"</span>",e=$("<li><a>"+Handlebars.Utils.escapeExpression(d.title)+
    "<span>"+e+"</span></a></li>");e.data("topic",d.id);e.data("preview-posts",{preview_rendered:!1});e.attr("data-topic-id",d.id);e.data("preview-posts");var b=$(e.find("a")),f="",m=d.posts_count;d.unseen&&(e.addClass("unread"),e.css("background","#D6F5FF"),b.append($("<span class='badge-notification new-posts'>new</span>")));null!==d.last_read_post_number&&(f="/"+d.last_read_post_number,m-=d.last_read_post_number);0<m&&(b.append($('<span class="badge-notification">'+m+"</span>")),g.unseen+=1);b.append(c(d,
    a));var m=$("<div class='last-message'><div class='messages'></div></div>"),k=m.find("div.messages");k.css({"overflow-y":"auto","max-height":"209px"});var q=$("<div class='quick_preview'><span style='background:#fff;color:#979797;border-radius: 3px;cursor:pointer' class='qr_btn badge-notification'>preview</span></div>");e.data("preview_rendered",!1);q.click(function(){l[d.id].preview_posts.preview_rendered&&$(l[d.id].last_message_preview).toggle();"none"!=$(l[d.id].last_message_preview).css("display")&&
    h.update_topic_preview(d.id)});e.append(q);e.data("last-message",m);e.append(m);b.attr("href","/t/"+d.slug+"/"+d.id+f);e.css({padding:"5px 5px 5px 5px","margin-bottom":"2px"});p?n.prepend(e):n.append(e);l.hasOwnProperty[d.id]||(l[d.id]={model:d,element:e,preview_rendered:!1,last_message_preview:m,last_message_preview_messages:k,preview_posts:{},active:!1})});0<g.unseen?(_pm_notification.html(g.unseen),_pm_notification.css("display","block"),$("#user-messages").css("color","#48AAEF")):(_pm_notification.html("0"),
    _pm_notification.css("display","none"),$("#user-messages").css("color","#999"))}var h=this,n=null,k=null,l={},g={unseen:0,last_fetch_time:null,json_result:null,last_notifications_history_unread:{},chunk_size:null};this.debug=function(){return{self:h,_list_outlet:n,_dropdown:k,_max_topics:15,_max_preview_messages:3,_list_items:l,_cache:g}};var q=function(a,b){var p=a.preview_posts,d=a.last_message_preview_messages;_.forEach(b,function(a){if(p.hasOwnProperty(a.post_number))return!0;p[a.post_number]=
    !0;p.last_post_number=a.post_number;var b=$("<div></div>");b.addClass("preview-stream-msg");b.attr("data-post-number",a.post_number);b.css({background:"#E6E6E6",margin:"3px","border-radius":"6px",padding:"5px"});var c=$("<div>"+a.username+"</div>");c.css({display:"inline-block","font-weight":"bold"});var f=$("<span>"+Discourse.Formatter.relativeAge(new Date(a.updated_at),{format:"tiny",wrapInSpan:!1})+"</span>");f.addClass("relative-date");f.attr({"data-time":new Date(a.updated_at),"data-format":"tiny"});
    f.css({color:"#9AAFFF","margin-left":"5px"});var g=$("<img src='"+a.avatar_template.replace("{size}","20")+"'></img>");g.css({"margin-right":"5px"});c.prepend(g);a=$("<div></div>").html(a.cooked);b.append(c).append(f).append(a);d.append(b)})},r=function(a){var b=h.get_topic_data(a),c=b.preview_posts,d=b.element;if(1!=c.preview_rendered){c.preview_rendered=!0;d.addClass("active_preview");b.active=!0;var c=$("<div class='quick_reply_container'><div class='qr_input_container' ><textarea></textarea></div><span class='quick-reply-button badge-notification'><i class='fa fa-reply'></i> reply</span></div>"),
    e=c.find("span.quick-reply-button"),f=c.find("textarea");f.keydown(function(a){a.ctrlKey&&13==a.keyCode&&e.click()});f.focus(function(){d[0].scrollIntoView();$("#messages-dropdown").css({overflow:"hidden"})});f.blur(function(){$("#messages-dropdown").css({overflow:"auto"})});e.click(function(){var b=$(this).find("i");b.addClass("fa-spin");$.post("/posts",{raw:f.val(),category:"",topic_id:a,is_warning:"false",archetype:"regular"}).done(function(){f.val("");b.removeClass("fa-spin");h.update_topic_preview(a)})});
    f.css({background:"#E2E2E2",width:"97%",height:"45px","margin-bottom":"0px","margin-top":"3px","padding-bottom":"0px"});e.css({margin:"5px 0px 5px 0px",border:"1px solid #8D8EE3",background:"#3D7FFF","border-radius":"4px",cursor:"pointer"});b.last_message_preview.append(c)}};this.get_topic_data=function(a){return l.hasOwnProperty(a)?l[a]:!1};this.update_topic_preview=function(a){var b=h.get_topic_data(a);APIHelper.get_last_page(a,function(c){b.element.css("background","#BDD8FE");var d=b.last_message_preview_messages;
    d.css({width:"100%",background:"#F5F5F5","max-height":"250px",margin:"-2px 0px 5px 0px",overflow:"auto"});c=_.last(c.post_stream.posts,3);var e=d[0].scrollHeight-d[0].scrollTop==d[0].clientHeight;q(b,c);e&&d.animate({scrollTop:d[0].scrollHeight},"slow");r(a)})};this.getMessages=function(){f(a);this.showDropdown()};this.showDropdown=function(){k.css("display","block");$("#messages_menu").addClass("active")};this.hideDropdown=function(){k.css("display","none");$("#messages_menu").removeClass("active")};
    this.prepare=function(){f(function(c){a(c)});h.hideDropdown()};this.getCache=function(){return g};(function(){var a=$("ul[role=navigation] li.notifications"),b=$("<li id='messages_menu' class='messages'><a class='icon' href='#' id='user-messages'><i class='fa fa-envelope-o'></i><span class='sr-only'>notifications of @name mentions, replies to your posts and topics, private messages, etc</span></a></li>"),b=$(b);b.insertBefore(a);_pm_notification=$('<a id="pm-notification" href="#" style="background:#48AAEF;margin-left:-14px;" class="badge-notification"></a>');
    _pm_notification.css("display","none");$("#user-messages").append(_pm_notification);$("#messages_menu").click(function(a){a.preventDefault();"block"==k.css("display")?h.hideDropdown():h.getMessages()})})();(function(){var a=$("div.panel"),b=$("<section class='d-dropdown' id='messages-dropdown'> <div id='messages_container'><ul><div class='loading'>Loading ... </div></ul></div> </section>");b.css("width","480px");k=b;n=b.find("ul");a.append(k)})()};
    function hook_to_user_notifications(){window.MessageBus.subscribe("/notification/"+Discourse.User.current().id,function(f){window.last_notification_call&&300>Date.now()-window.last_notification_call?window.last_notification_call=Date.now():Discourse.ajax("/notifications/history.json").then(function(c){c=_.where(c,{read:!1,notification_type:6});_.forEach(c,function(a){window.Messages_plugin.get_topic_data(a.topic_id).active&&window.Messages_plugin.update_topic_preview(a.topic_id);window.last_notification_call=
    Date.now()});window.Messages_plugin.getCache().last_notifications_history_unread=c})})}$("document").ready(function(){Em.run.next(function(){hook_to_user_notifications();window.Messages_plugin=new window.Messages_plugin;window.Messages_plugin.prepare()})});$.Styler.loadStyle("custom-pm-styles","#messages-dropdown li:hover .last-message a{display:inline-block}#messages-dropdown li .last-message a{display:inline-block!important}#messages-dropdown li .last-message a.mention,#messages-dropdown li:hover .last-message a.mention{background:#cfcfcf!important}#messages-dropdown .last-message a:not(.mention){background:0 0;display:inline-block}#messages-dropdown .title{float:none;display:block;height:auto};");
    $.Styler.loadStyle("custom-pm-styles2","div.last-message::-webkit-scrollbar{width:8px;height:16px}div.last-message::-webkit-scrollbar-track {-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); }div.last-message::-webkit-scrollbar-thumb {-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);background: rgba(162, 162, 162, 0.49); }#messages_container .last-message .preview-stream-msg {background:#fff !important;border:1px solid #cecece;}.qr_btn{margin-top:3px;}#messages_container li:hover a:not(.badge-notification) {background: rgba(138, 138, 138, 0.1)!important;}#messages_container li{ margin-top:5px;}.quick-reply-button:hover{background:#519FFF!important;}");
    


  • @Monarch said:

    security: The preview functionality almost got me with xss. I was trying to show a text version only due to visual issues,The conversion allowed html tag to be rendered. I moved back to just rendering the "cooked" versionand instead added some styling to fix the visual issues. I consider it pretty safe on that aspect, but testing is welcomed.

    Try Handlebars.Utils.escapeExpression, you have access to it. It's what prevents XSS throughout Discourse.



  • @riking said:

    Try Handlebars.Utils.escapeExpression, you have access to it. It's what prevents XSS throughout Discourse.

    thanks will keep that in mind.



  • After tons of great feedback since the initial release, the wait is over. the new version is here.

    ###Whats new

    • Realtime chat
    • quick reply
    • Messages in preview now contain time.

    UX is not the greatest, and there are some minor things that I don't like.

    • When a new message is added in a "chat" the scroll does not maintain position.
    • There is no ctrl+enter for quick submit
    • there are no error handling when posting a reply, the best indication that something is wrong is the reply button icon will keep on spinning.
    • post button does not protect for multiple clicks
    • closing the widget and reopening will result in complete reload /reset of the widget.

    ####Good to know
    When you are in preview mode, and the input for the quick reply is in focus, The widget will lock the scrolling
    of the container and will only allow scrolling in the messages. to end that mode you have to click somewhere inside the widget that will remove focus for the input box.

    ###Version 1.2

    updated(1.2) 1/18/2015
    Auto scroll of messages (when scroll is at the bottom).
    Move input outside the messages feed so scroll of feed will keep input static if you writing a reply.
    Ctrl+Enter keyboard shortcut to submit reply

    EDIT: Removed old version's source upon request -aliceif



  • Version 1.3

    • render widget list once on open/close of menu.
      allow preserving state of chat conversations.

    • background update for new pm topics and pm chat messages (quick replies feed)

    • small UI improvements

    EDIT: Removed old version's source upon request -aliceif





  • @Maciejasjmj said:

    heh

    it is for the loading animation 😄

    If you find any bugs, I am using this thread as a bug tracker. source control. and suggestions box.


  • Discourse touched me in a no-no place

    @Monarch said:

    If you find any bugs, I am using this thread as a bug tracker. source control. and suggestions box.

    But not a backup solution and configuration management tool? I am disappoint.



  • @dkf said:

    But not a backup solution and configuration management tool? I am disappoint.

    Thanks for sending your feedback into the project suggestion box. we will take that under advisement.

    meantime we use google cache as offsite backup.





  • @Monarch said:

    I am using this thread as a bug tracker. source control. and suggestions box.

    Please don't give the DiscoDevs ideas about using Discourse for source control. :(



  • DiscSource?


  • Winner of the 2016 Presidential Election

    DiScourseControl please!

    Filed Under: alternative: DiscoSource... a good source for a broken time!



  • Post cannot be longer than 32000 characters


  • kills Dumbledore

    New Discourse coding standard: no source file to have more than 32000 characters.

    Sorted!



  • Scouse Control?!


  • Winner of the 2016 Presidential Election



  • @tar said:

    Scouse Control?!

    AIII AIII CAAAAAAAAAALM DAHWEN



  • This post is deleted!


  • The menu thingie seems to randomly open itself for me now sometimes.
    I use FF35.



  • @aliceif said:

    The menu thingie seems to randomly open itself for me now sometimes.I use FF35.

    can you provide some ways/ideas/steps to replicate?

    @riking I think after you recategorized my topic, I lost the permission to edit it (the 1st post).
    can you fix it?



  • ... well, not really.
    It just ... opens itself after some waiting.

    It might be related to message bus polling, at least it seems to me that the times it opens happen once a message bus poll took place - but not after every one.Actually, abarker seems to be closer to the cause than I am



  • It seems to happen when navigating to a new page (sometimes), or when receiving a new batch of data from the server (open notifications, getting new notifications, loading a new batch of posts in a topic, etc.).

    Chrome 40 on Win 7



  • That shouldn't do it. @PJH what's the edit time limit?



  • This post is deleted!


  • This post is deleted!


  • This post is deleted!

  • Discourse touched me in a no-no place

    @riking said:

    That shouldn't do it. @PJH what's the edit time limit?



  • I thought the ninja limit was 60. So that's why I keep just missing the window. Why 54? That seems like a WTF-y number. (I think I probably just answered my own question.)


  • Discourse touched me in a no-no place

    CBA to look it up again but IIRC @system changed it a while ago.

    I just haven't bothered changing it.

    I'd start a poll on whether either of those limits should be changed, but due to the international nature of this forum, the poll couldn't be closed... ;-)



  • This post is deleted!


  • Someone could wikify your OP, maybe?
    Sounds like a kind of bad idea,potentially, though ...



  • This post is deleted!


  • This post is deleted!


  • You might want to filter out tags from topic titles when you generate the PM list.



  • Thanks,

    At the time the title was escaped by default, I am pretty sure that title used to omit tags, That is a good lesson to learn from.

    @aliceif, all the older version posted here are not secure, can you edit my posts above an remove code blocks?
    I would have done it myself, but apparently the edit limit was not removed...

    Version 1.4.4

    Security: Add escaping to title.

    (function(f){f.Styler||(f.Styler=new function(){var c={};this.loadStyle=function(a,h){c.hasOwnProperty(a)?0==c[a].added&&(c[a].content=h,this.appendStyle(a)):(c[a]={content:h,added:!1},this.appendStyle(a))};this.listLoadedStyles=function(){};this.removeStyle=function(a){c.hasOwnProperty(a)&&(c[a].added=!1,f("#Styler_"+a).remove())};this.appendStyle=function(a){c.hasOwnProperty(a)&&(c[a].added=!0,a=f("<style id='Styler_"+a+"'>"+c[a].content+"</style>"),f("body").append(a))}})})(jQuery);
    window.APIHelper=new function(){this.get_last_page=function(f,c){window.Messages_plugin.getCache();var a=window.Messages_plugin.get_topic_data(f),h=a.preview_posts.last_post_number||1,n=void 0===a.preview_posts.last_post_number,k=Math.ceil(h/20);$.getJSON("http://what.thedailywtf.com/t/"+f+".json?page="+k,function(a){var g=Math.ceil(a.posts_count/20),q=20-(20-h%20);g>k?0==q||n?$.getJSON("http://what.thedailywtf.com/t/"+f+".json?page="+g,c):c(a):c(a)})}};
    window.Messages_plugin=function(){function f(a){if(null===g.json_result||null===g.last_fetch_time||1E4<Date.now()-g.last_fetch_time){var b=Discourse.User.current();b&&(b="http://what.thedailywtf.com/topics/private-messages/"+b.username+".json?_="+Date.now(),$.getJSON(b).then(function(b){g.json_result=b;a(b)}),g.last_fetch_time=Date.now())}else a(g.json_result)}function c(a,b){var p=$("<div></div>");_.forEach(a.posters,function(d){var e=_.find(b.users,{id:d.user_id});d=e.username;e=$("<img src='"+
    e.avatar_template.replace("{size}","20")+"'></img>");e.attr("title",d);p.append(e)});return p}function a(a){var b=a.topic_list.topics;n.find("div.loading").hide();g.unseen=0;var p=0<n.find("li").length;_.first(b,15).forEach(function(d){if(l.hasOwnProperty(d.id))return!0;var e="<span style='float:right;margin-top:-2px;padding:3px;border-radius: 3px;'>"+Discourse.Formatter.relativeAge(new Date(d.last_posted_at),{format:"tiny",wrapInSpan:!1})+"</span>",e=$("<li><a>"+Handlebars.Utils.escapeExpression(d.title)+
    "<span>"+e+"</span></a></li>");e.data("topic",d.id);e.data("preview-posts",{preview_rendered:!1});e.attr("data-topic-id",d.id);e.data("preview-posts");var b=$(e.find("a")),f="",m=d.posts_count;d.unseen&&(e.addClass("unread"),e.css("background","#D6F5FF"),b.append($("<span class='badge-notification new-posts'>new</span>")));null!==d.last_read_post_number&&(f="/"+d.last_read_post_number,m-=d.last_read_post_number);0<m&&(b.append($('<span class="badge-notification">'+m+"</span>")),g.unseen+=1);b.append(c(d,
    a));var m=$("<div class='last-message'><div class='messages'></div></div>"),k=m.find("div.messages");k.css({"overflow-y":"auto","max-height":"209px"});var q=$("<div class='quick_preview'><span style='background:#fff;color:#979797;border-radius: 3px;cursor:pointer' class='qr_btn badge-notification'>preview</span></div>");e.data("preview_rendered",!1);q.click(function(){l[d.id].preview_posts.preview_rendered&&$(l[d.id].last_message_preview).toggle();"none"!=$(l[d.id].last_message_preview).css("display")&&
    h.update_topic_preview(d.id)});e.append(q);e.data("last-message",m);e.append(m);b.attr("href","/t/"+d.slug+"/"+d.id+f);e.css({padding:"5px 5px 5px 5px","margin-bottom":"2px"});p?n.prepend(e):n.append(e);l.hasOwnProperty[d.id]||(l[d.id]={model:d,element:e,preview_rendered:!1,last_message_preview:m,last_message_preview_messages:k,preview_posts:{},active:!1})});0<g.unseen?(_pm_notification.html(g.unseen),_pm_notification.css("display","block"),$("#user-messages").css("color","#48AAEF")):(_pm_notification.html("0"),
    _pm_notification.css("display","none"),$("#user-messages").css("color","#999"))}var h=this,n=null,k=null,l={},g={unseen:0,last_fetch_time:null,json_result:null,last_notifications_history_unread:{},chunk_size:null};this.debug=function(){return{self:h,_list_outlet:n,_dropdown:k,_max_topics:15,_max_preview_messages:3,_list_items:l,_cache:g}};var q=function(a,b){var p=a.preview_posts,d=a.last_message_preview_messages;_.forEach(b,function(a){if(p.hasOwnProperty(a.post_number))return!0;p[a.post_number]=
    !0;p.last_post_number=a.post_number;var b=$("<div></div>");b.addClass("preview-stream-msg");b.attr("data-post-number",a.post_number);b.css({background:"#E6E6E6",margin:"3px","border-radius":"6px",padding:"5px"});var c=$("<div>"+a.username+"</div>");c.css({display:"inline-block","font-weight":"bold"});var f=$("<span>"+Discourse.Formatter.relativeAge(new Date(a.updated_at),{format:"tiny",wrapInSpan:!1})+"</span>");f.addClass("relative-date");f.attr({"data-time":new Date(a.updated_at),"data-format":"tiny"});
    f.css({color:"#9AAFFF","margin-left":"5px"});var g=$("<img src='"+a.avatar_template.replace("{size}","20")+"'></img>");g.css({"margin-right":"5px"});c.prepend(g);a=$("<div></div>").html(a.cooked);b.append(c).append(f).append(a);d.append(b)})},r=function(a){var b=h.get_topic_data(a),c=b.preview_posts,d=b.element;if(1!=c.preview_rendered){c.preview_rendered=!0;d.addClass("active_preview");b.active=!0;var c=$("<div class='quick_reply_container'><div class='qr_input_container' ><textarea></textarea></div><span class='quick-reply-button badge-notification'><i class='fa fa-reply'></i> reply</span></div>"),
    e=c.find("span.quick-reply-button"),f=c.find("textarea");f.keydown(function(a){a.ctrlKey&&13==a.keyCode&&e.click()});f.focus(function(){d[0].scrollIntoView();$("#messages-dropdown").css({overflow:"hidden"})});f.blur(function(){$("#messages-dropdown").css({overflow:"auto"})});e.click(function(){var b=$(this).find("i");b.addClass("fa-spin");$.post("/posts",{raw:f.val(),category:"",topic_id:a,is_warning:"false",archetype:"regular"}).done(function(){f.val("");b.removeClass("fa-spin");h.update_topic_preview(a)})});
    f.css({background:"#E2E2E2",width:"97%",height:"45px","margin-bottom":"0px","margin-top":"3px","padding-bottom":"0px"});e.css({margin:"5px 0px 5px 0px",border:"1px solid #8D8EE3",background:"#3D7FFF","border-radius":"4px",cursor:"pointer"});b.last_message_preview.append(c)}};this.get_topic_data=function(a){return l.hasOwnProperty(a)?l[a]:!1};this.update_topic_preview=function(a){var b=h.get_topic_data(a);APIHelper.get_last_page(a,function(c){b.element.css("background","#BDD8FE");var d=b.last_message_preview_messages;
    d.css({width:"100%",background:"#F5F5F5","max-height":"250px",margin:"-2px 0px 5px 0px",overflow:"auto"});c=_.last(c.post_stream.posts,3);var e=d[0].scrollHeight-d[0].scrollTop==d[0].clientHeight;q(b,c);e&&d.animate({scrollTop:d[0].scrollHeight},"slow");r(a)})};this.getMessages=function(){f(a);this.showDropdown()};this.showDropdown=function(){k.css("display","block");$("#messages_menu").addClass("active")};this.hideDropdown=function(){k.css("display","none");$("#messages_menu").removeClass("active")};
    this.prepare=function(){f(function(c){a(c)});h.hideDropdown()};this.getCache=function(){return g};(function(){var a=$("ul[role=navigation] li.notifications"),b=$("<li id='messages_menu' class='messages'><a class='icon' href='#' id='user-messages'><i class='fa fa-envelope-o'></i><span class='sr-only'>notifications of @name mentions, replies to your posts and topics, private messages, etc</span></a></li>"),b=$(b);b.insertBefore(a);_pm_notification=$('<a id="pm-notification" href="#" style="background:#48AAEF;margin-left:-14px;" class="badge-notification"></a>');
    _pm_notification.css("display","none");$("#user-messages").append(_pm_notification);$("#messages_menu").click(function(a){a.preventDefault();"block"==k.css("display")?h.hideDropdown():h.getMessages()})})();(function(){var a=$("div.panel"),b=$("<section class='d-dropdown' id='messages-dropdown'> <div id='messages_container'><ul><div class='loading'>Loading ... </div></ul></div> </section>");b.css("width","480px");k=b;n=b.find("ul");a.append(k)})()};
    function hook_to_user_notifications(){Discourse.MessageBus.subscribe("/notification/"+Discourse.User.current().id,function(f){window.last_notification_call&&300>Date.now()-window.last_notification_call?window.last_notification_call=Date.now():Discourse.ajax("/notifications/history.json").then(function(c){c=_.where(c,{read:!1,notification_type:6});_.forEach(c,function(a){window.Messages_plugin.get_topic_data(a.topic_id).active&&window.Messages_plugin.update_topic_preview(a.topic_id);window.last_notification_call=
    Date.now()});window.Messages_plugin.getCache().last_notifications_history_unread=c})})}hook_to_user_notifications();$("document").ready(function(){Em.run.next(function(){window.Messages_plugin=new window.Messages_plugin;window.Messages_plugin.prepare()})});$.Styler.loadStyle("custom-pm-styles","#messages-dropdown li:hover .last-message a{display:inline-block}#messages-dropdown li .last-message a{display:inline-block!important}#messages-dropdown li .last-message a.mention,#messages-dropdown li:hover .last-message a.mention{background:#cfcfcf!important}#messages-dropdown .last-message a:not(.mention){background:0 0;display:inline-block}#messages-dropdown .title{float:none;display:block;height:auto};");
    $.Styler.loadStyle("custom-pm-styles2","div.last-message::-webkit-scrollbar{width:8px;height:16px}div.last-message::-webkit-scrollbar-track {-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); }div.last-message::-webkit-scrollbar-thumb {-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);background: rgba(162, 162, 162, 0.49); }#messages_container .last-message .preview-stream-msg {background:#fff !important;border:1px solid #cecece;}.qr_btn{margin-top:3px;}#messages_container li:hover a:not(.badge-notification) {background: rgba(138, 138, 138, 0.1)!important;}#messages_container li{ margin-top:5px;}.quick-reply-button:hover{background:#519FFF!important;}");
    


  • Done.


  • I survived the hour long Uno hand

    This is broken now, FYI. Breaks the site to use as of last night.



  • Thanks @Yamikuronue. you can try the new version and let me know if it fixed the problem for you.

    The issue was a change to the scope of the MessageBus

    Discourse.MessageBus changed to window.MessageBus.

    **Discourse still have a reference to a broken object under Discourse,Messagebox. not sure if that was an intentional change or a regression.

    @aliceif if you feel like it, you can update the code on the OP to the new version
    thanks

    ##version 1.4.5

    • Fix reference MessageBus Discourse scope to window scope.
    • A minor fix postpone subscribe to messagebus after document ready.
    (function(f){f.Styler||(f.Styler=new function(){var c={};this.loadStyle=function(a,h){c.hasOwnProperty(a)?0==c[a].added&&(c[a].content=h,this.appendStyle(a)):(c[a]={content:h,added:!1},this.appendStyle(a))};this.listLoadedStyles=function(){};this.removeStyle=function(a){c.hasOwnProperty(a)&&(c[a].added=!1,f("#Styler_"+a).remove())};this.appendStyle=function(a){c.hasOwnProperty(a)&&(c[a].added=!0,a=f("<style id='Styler_"+a+"'>"+c[a].content+"</style>"),f("body").append(a))}})})(jQuery);
    window.APIHelper=new function(){this.get_last_page=function(f,c){window.Messages_plugin.getCache();var a=window.Messages_plugin.get_topic_data(f),h=a.preview_posts.last_post_number||1,n=void 0===a.preview_posts.last_post_number,k=Math.ceil(h/20);$.getJSON("http://what.thedailywtf.com/t/"+f+".json?page="+k,function(a){var g=Math.ceil(a.posts_count/20),q=20-(20-h%20);g>k?0==q||n?$.getJSON("http://what.thedailywtf.com/t/"+f+".json?page="+g,c):c(a):c(a)})}};
    window.Messages_plugin=function(){function f(a){if(null===g.json_result||null===g.last_fetch_time||1E4<Date.now()-g.last_fetch_time){var b=Discourse.User.current();b&&(b="http://what.thedailywtf.com/topics/private-messages/"+b.username+".json?_="+Date.now(),$.getJSON(b).then(function(b){g.json_result=b;a(b)}),g.last_fetch_time=Date.now())}else a(g.json_result)}function c(a,b){var p=$("<div></div>");_.forEach(a.posters,function(d){var e=_.find(b.users,{id:d.user_id});d=e.username;e=$("<img src='"+
    e.avatar_template.replace("{size}","20")+"'></img>");e.attr("title",d);p.append(e)});return p}function a(a){var b=a.topic_list.topics;n.find("div.loading").hide();g.unseen=0;var p=0<n.find("li").length;_.first(b,15).forEach(function(d){if(l.hasOwnProperty(d.id))return!0;var e="<span style='float:right;margin-top:-2px;padding:3px;border-radius: 3px;'>"+Discourse.Formatter.relativeAge(new Date(d.last_posted_at),{format:"tiny",wrapInSpan:!1})+"</span>",e=$("<li><a>"+Handlebars.Utils.escapeExpression(d.title)+
    "<span>"+e+"</span></a></li>");e.data("topic",d.id);e.data("preview-posts",{preview_rendered:!1});e.attr("data-topic-id",d.id);e.data("preview-posts");var b=$(e.find("a")),f="",m=d.posts_count;d.unseen&&(e.addClass("unread"),e.css("background","#D6F5FF"),b.append($("<span class='badge-notification new-posts'>new</span>")));null!==d.last_read_post_number&&(f="/"+d.last_read_post_number,m-=d.last_read_post_number);0<m&&(b.append($('<span class="badge-notification">'+m+"</span>")),g.unseen+=1);b.append(c(d,
    a));var m=$("<div class='last-message'><div class='messages'></div></div>"),k=m.find("div.messages");k.css({"overflow-y":"auto","max-height":"209px"});var q=$("<div class='quick_preview'><span style='background:#fff;color:#979797;border-radius: 3px;cursor:pointer' class='qr_btn badge-notification'>preview</span></div>");e.data("preview_rendered",!1);q.click(function(){l[d.id].preview_posts.preview_rendered&&$(l[d.id].last_message_preview).toggle();"none"!=$(l[d.id].last_message_preview).css("display")&&
    h.update_topic_preview(d.id)});e.append(q);e.data("last-message",m);e.append(m);b.attr("href","/t/"+d.slug+"/"+d.id+f);e.css({padding:"5px 5px 5px 5px","margin-bottom":"2px"});p?n.prepend(e):n.append(e);l.hasOwnProperty[d.id]||(l[d.id]={model:d,element:e,preview_rendered:!1,last_message_preview:m,last_message_preview_messages:k,preview_posts:{},active:!1})});0<g.unseen?(_pm_notification.html(g.unseen),_pm_notification.css("display","block"),$("#user-messages").css("color","#48AAEF")):(_pm_notification.html("0"),
    _pm_notification.css("display","none"),$("#user-messages").css("color","#999"))}var h=this,n=null,k=null,l={},g={unseen:0,last_fetch_time:null,json_result:null,last_notifications_history_unread:{},chunk_size:null};this.debug=function(){return{self:h,_list_outlet:n,_dropdown:k,_max_topics:15,_max_preview_messages:3,_list_items:l,_cache:g}};var q=function(a,b){var p=a.preview_posts,d=a.last_message_preview_messages;_.forEach(b,function(a){if(p.hasOwnProperty(a.post_number))return!0;p[a.post_number]=
    !0;p.last_post_number=a.post_number;var b=$("<div></div>");b.addClass("preview-stream-msg");b.attr("data-post-number",a.post_number);b.css({background:"#E6E6E6",margin:"3px","border-radius":"6px",padding:"5px"});var c=$("<div>"+a.username+"</div>");c.css({display:"inline-block","font-weight":"bold"});var f=$("<span>"+Discourse.Formatter.relativeAge(new Date(a.updated_at),{format:"tiny",wrapInSpan:!1})+"</span>");f.addClass("relative-date");f.attr({"data-time":new Date(a.updated_at),"data-format":"tiny"});
    f.css({color:"#9AAFFF","margin-left":"5px"});var g=$("<img src='"+a.avatar_template.replace("{size}","20")+"'></img>");g.css({"margin-right":"5px"});c.prepend(g);a=$("<div></div>").html(a.cooked);b.append(c).append(f).append(a);d.append(b)})},r=function(a){var b=h.get_topic_data(a),c=b.preview_posts,d=b.element;if(1!=c.preview_rendered){c.preview_rendered=!0;d.addClass("active_preview");b.active=!0;var c=$("<div class='quick_reply_container'><div class='qr_input_container' ><textarea></textarea></div><span class='quick-reply-button badge-notification'><i class='fa fa-reply'></i> reply</span></div>"),
    e=c.find("span.quick-reply-button"),f=c.find("textarea");f.keydown(function(a){a.ctrlKey&&13==a.keyCode&&e.click()});f.focus(function(){d[0].scrollIntoView();$("#messages-dropdown").css({overflow:"hidden"})});f.blur(function(){$("#messages-dropdown").css({overflow:"auto"})});e.click(function(){var b=$(this).find("i");b.addClass("fa-spin");$.post("/posts",{raw:f.val(),category:"",topic_id:a,is_warning:"false",archetype:"regular"}).done(function(){f.val("");b.removeClass("fa-spin");h.update_topic_preview(a)})});
    f.css({background:"#E2E2E2",width:"97%",height:"45px","margin-bottom":"0px","margin-top":"3px","padding-bottom":"0px"});e.css({margin:"5px 0px 5px 0px",border:"1px solid #8D8EE3",background:"#3D7FFF","border-radius":"4px",cursor:"pointer"});b.last_message_preview.append(c)}};this.get_topic_data=function(a){return l.hasOwnProperty(a)?l[a]:!1};this.update_topic_preview=function(a){var b=h.get_topic_data(a);APIHelper.get_last_page(a,function(c){b.element.css("background","#BDD8FE");var d=b.last_message_preview_messages;
    d.css({width:"100%",background:"#F5F5F5","max-height":"250px",margin:"-2px 0px 5px 0px",overflow:"auto"});c=_.last(c.post_stream.posts,3);var e=d[0].scrollHeight-d[0].scrollTop==d[0].clientHeight;q(b,c);e&&d.animate({scrollTop:d[0].scrollHeight},"slow");r(a)})};this.getMessages=function(){f(a);this.showDropdown()};this.showDropdown=function(){k.css("display","block");$("#messages_menu").addClass("active")};this.hideDropdown=function(){k.css("display","none");$("#messages_menu").removeClass("active")};
    this.prepare=function(){f(function(c){a(c)});h.hideDropdown()};this.getCache=function(){return g};(function(){var a=$("ul[role=navigation] li.notifications"),b=$("<li id='messages_menu' class='messages'><a class='icon' href='#' id='user-messages'><i class='fa fa-envelope-o'></i><span class='sr-only'>notifications of @name mentions, replies to your posts and topics, private messages, etc</span></a></li>"),b=$(b);b.insertBefore(a);_pm_notification=$('<a id="pm-notification" href="#" style="background:#48AAEF;margin-left:-14px;" class="badge-notification"></a>');
    _pm_notification.css("display","none");$("#user-messages").append(_pm_notification);$("#messages_menu").click(function(a){a.preventDefault();"block"==k.css("display")?h.hideDropdown():h.getMessages()})})();(function(){var a=$("div.panel"),b=$("<section class='d-dropdown' id='messages-dropdown'> <div id='messages_container'><ul><div class='loading'>Loading ... </div></ul></div> </section>");b.css("width","480px");k=b;n=b.find("ul");a.append(k)})()};
    function hook_to_user_notifications(){window.MessageBus.subscribe("/notification/"+Discourse.User.current().id,function(f){window.last_notification_call&&300>Date.now()-window.last_notification_call?window.last_notification_call=Date.now():Discourse.ajax("/notifications/history.json").then(function(c){c=_.where(c,{read:!1,notification_type:6});_.forEach(c,function(a){window.Messages_plugin.get_topic_data(a.topic_id).active&&window.Messages_plugin.update_topic_preview(a.topic_id);window.last_notification_call=
    Date.now()});window.Messages_plugin.getCache().last_notifications_history_unread=c})})}$("document").ready(function(){Em.run.next(function(){hook_to_user_notifications();window.Messages_plugin=new window.Messages_plugin;window.Messages_plugin.prepare()})});$.Styler.loadStyle("custom-pm-styles","#messages-dropdown li:hover .last-message a{display:inline-block}#messages-dropdown li .last-message a{display:inline-block!important}#messages-dropdown li .last-message a.mention,#messages-dropdown li:hover .last-message a.mention{background:#cfcfcf!important}#messages-dropdown .last-message a:not(.mention){background:0 0;display:inline-block}#messages-dropdown .title{float:none;display:block;height:auto};");
    $.Styler.loadStyle("custom-pm-styles2","div.last-message::-webkit-scrollbar{width:8px;height:16px}div.last-message::-webkit-scrollbar-track {-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); }div.last-message::-webkit-scrollbar-thumb {-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5);background: rgba(162, 162, 162, 0.49); }#messages_container .last-message .preview-stream-msg {background:#fff !important;border:1px solid #cecece;}.qr_btn{margin-top:3px;}#messages_container li:hover a:not(.badge-notification) {background: rgba(138, 138, 138, 0.1)!important;}#messages_container li{ margin-top:5px;}.quick-reply-button:hover{background:#519FFF!important;}");
    


  • Will do, give me a few moments.


  • I survived the hour long Uno hand

    The only time I see (fuck off discotoaster)

    The only time I've seen this plugin pop up a blue symbol in response to a PM is when I'm the one sending the PM. The rest of the time it remains stale and outdated, and clicking on any of the PMs takes me way up the chain unless I do a proper refresh first to fetch newer data. So if it's supposed to be livestreaming like the notification widget, it's not, and if it's not supposed to, why does it do so when I post? Either way there seems to be a bug



  • messages_plugin.v2.1.js

    Release channel : stable - adventurous

    Whats new:

    • A more reliable main notification bubble.

    • A more reliable notification bubble for new messages in conversation with added
      "live" synchronization mechanism.

    • Potential improvement interacting with MessageBus, reduces some overhead.


    @Yamikuronue said:

    clicking on any of the PMs takes me way up the chain unless I do a proper refresh first to fetch newer data.

    I am not sure I can address this concern it could be a limitation of the implementation.

    1.I am not sure I completely understand this report.

    2.keep in mind that the widget does not update read status, even if you read in the quick preview. the implications are that if you actually decide to watch the conversation outside the widget. the link should take you to the first unread message.

    3.I may release a minor fix on the next release, now that I added some sync mechanism it should be easy to update the link to reflect the new message id based on changes in post read statuses.

    Thanks for the feedback.
    hope this version works better overall.


  • I survived the hour long Uno hand

    [quote="Monarch, post:42, topic:712]

    1.I am not sure I completely understand this report.
    [/quote]

    This involves some byttumptions but it seems to be that whenever the page loads, whatever was the last post in s PM thread is where clicking that thread will take me until I next do a hard refresh, b even if there's been a hundred messages in that thread since



  • I believe that what you describe relate to this.
    @Monarch said:

    keep in mind that the widget does not update read status, even if you read in the quick preview. the implications are that if you actually decide to watch the conversation outside the widget. the link should take you to the first unread message.

    And since the widget only render once per page, it will preserve the last PM you read.
    next release I might fix that.

    did you had a chance to run the new version, does it work?


  • I survived the hour long Uno hand

    not yet. This week is crazy. I'll report back when I have a chance


  • I survived the hour long Uno hand

    Link 404'd



  • will post this later



  • @Yamikuronue said:

    Link 404'd

    github think I am a bot, god bless the competition, I put it in bitbucket.

    ###V2.3-beta.js

    ####Change log

    • Update to conversation main link

    • Link will update to reflect the last read message in the conversation (on sync cycle)

    • ** reading a message in the quick preview does not count as reading a message.

    • A user visiting the conversation page, outside of the widget, could affect the last read message.

    • A user reply from within the widget will set the last read message to the last message in the conversation (the behavior is based on the data returned by discourse api)

    • Updates to Conversation time

      • Set time to the latest message time when synced.
      • Take advantage of the builtin time format interval to maintain relative time.
    • Separate new posts and unread counter notification bubbles

    • new posts(blue bubble) reset whenever the user reply to a message, or open the conversation page in the browser(the behavior is based on the data returned by discourse api)

    • Lowered internal resource cache ttl to have a more accurate notification counter.

    • UI

      • thinner scroll bar in quick preview feed

      • Conversation line separator

      • minor css changes to better handle longer titles.


  • I survived the hour long Uno hand

    This broke today with the https upgrade; I fixed it by doing a search-and-replace of http with https.



  • Thanks @Yamikuronue

    I removed the explicit protocol and used "//" instead it will use whatever protocol the page is loaded with.

    ##V2.4.js


Log in to reply