diff options
author | Mario <mario@mariovavti.com> | 2021-06-17 07:33:46 +0000 |
---|---|---|
committer | Mario <mario@mariovavti.com> | 2021-06-17 07:33:46 +0000 |
commit | fa076efd3bd953863f01bcb474ddb4fc928507e7 (patch) | |
tree | d1a6f9e97ac919f91f7658aa16132565deae014a /view | |
parent | 9b71c090c5c8d051e6997c4a39241bbbd5cb6cee (diff) | |
parent | b55676d08914d58927b5503a1bfa283397cd6d44 (diff) | |
download | volse-hubzilla-fa076efd3bd953863f01bcb474ddb4fc928507e7.tar.gz volse-hubzilla-fa076efd3bd953863f01bcb474ddb4fc928507e7.tar.bz2 volse-hubzilla-fa076efd3bd953863f01bcb474ddb4fc928507e7.zip |
Merge branch 'dm' into 'dev'
New landing page HQ with separate views for direct messages, public/limited messages and starred messages if the feature is enabled
See merge request hubzilla/core!1969
Diffstat (limited to 'view')
-rw-r--r-- | view/css/conversation.css | 3 | ||||
-rw-r--r-- | view/css/mod_dm.css | 3 | ||||
-rw-r--r-- | view/css/widgets.css | 7 | ||||
-rw-r--r-- | view/js/autocomplete.js | 15 | ||||
-rw-r--r-- | view/js/main.js | 439 | ||||
-rw-r--r-- | view/js/mod_hq.js | 26 | ||||
-rw-r--r-- | view/pdl/mod_hq.pdl | 8 | ||||
-rw-r--r-- | view/tpl/head.tpl | 1 | ||||
-rw-r--r-- | view/tpl/hq_controls.tpl | 13 | ||||
-rw-r--r-- | view/tpl/messages_widget.tpl | 123 | ||||
-rw-r--r-- | view/tpl/notes.tpl | 12 | ||||
-rw-r--r-- | view/tpl/notifications_widget.tpl | 455 |
12 files changed, 632 insertions, 473 deletions
diff --git a/view/css/conversation.css b/view/css/conversation.css index 43bc96e57..dbb930fc7 100644 --- a/view/css/conversation.css +++ b/view/css/conversation.css @@ -34,6 +34,8 @@ #jot-pagetitle-wrap input, #jot-customjotheaders-wrap { padding: 0.5rem; + outline: none; + } #jot-text-wrap { @@ -55,6 +57,7 @@ padding: 0.5rem; width: 100%; display: inherit; + outline: none; } #profile-jot-text.jot-expanded { diff --git a/view/css/mod_dm.css b/view/css/mod_dm.css new file mode 100644 index 000000000..dde242d4e --- /dev/null +++ b/view/css/mod_dm.css @@ -0,0 +1,3 @@ +#jot-popup { + display: none; +} diff --git a/view/css/widgets.css b/view/css/widgets.css index 30e7e6972..a677bb457 100644 --- a/view/css/widgets.css +++ b/view/css/widgets.css @@ -38,15 +38,16 @@ li:hover .widget-nav-pills-icons { margin-top: 10px; } -/* notes */ +/* notes */ #note-text { border: 1px solid rgba(0,0,0,.125); padding: 5px; width: 100%; - resize: none; + resize: vertical; min-height: 250px; - overflow: hidden; + overflow: auto; + outline: none; } /* saved searches */ diff --git a/view/js/autocomplete.js b/view/js/autocomplete.js index c45c47518..f20c45982 100644 --- a/view/js/autocomplete.js +++ b/view/js/autocomplete.js @@ -162,8 +162,8 @@ function string2bb(element) { if (typeof extra_channels === 'undefined') extra_channels = false; // Autocomplete contacts - contacts = { - match: /(^|\s)(@\!*)([^ \n]{3,})$/, + channels = { + match: /(^(?=[^\!]{2})|\s)(@)([^ \n]{3,})$/, index: 3, cache: true, search: function(term, callback) { contact_search(term, callback, backend_url, 'c', extra_channels, spinelement=false); }, @@ -171,6 +171,15 @@ function string2bb(element) { template: contact_format }; + contacts = { + match: /(^|\s)(@\!)([^ \n]{3,})$/, + index: 3, + cache: true, + search: function(term, callback) { contact_search(term, callback, backend_url, 'm', extra_channels, spinelement=false); }, + replace: editor_replace, + template: contact_format + }; + // Autocomplete hashtags tags = { match: /(^|\s)(\#)([^ \n]{2,})$/, @@ -202,7 +211,7 @@ function string2bb(element) { maxCount: 100 } }); - textcomplete.register([contacts,smilies,tags]); + textcomplete.register([channels,contacts,smilies,tags]); }); }; })( jQuery ); diff --git a/view/js/main.js b/view/js/main.js index b1cba33af..a3f238a45 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -26,13 +26,6 @@ var followUpPageLoad = false; var window_needs_alert = true; var expanded_items = []; -var sse_bs_active = false; -var sse_offset = 0; -var sse_type; -var sse_partial_result = false; -var sse_rmids = []; -var sse_fallback_interval; - var page_cache = {}; // take care of tab/window reloads on channel change @@ -93,7 +86,7 @@ $(document).ready(function() { if (tao.zin.syslc == '') { $('.zinlcx').append(tao.zin.axim); $.ajax({ - type: 'POST', url: 'lang', + type: 'POST', url: 'lang', data: { zinlc: '??' } }).done( function(re) { tao.zin.re = JSON.parse(re); @@ -117,7 +110,7 @@ $(document).ready(function() { tao.zin.me = e.target.id.substr(5); $('#right_aside_wrapper').append(tao.zin.axim); $.ajax({ - type: 'POST', url: 'lang', + type: 'POST', url: 'lang', data: { zinlc: tao.zin.me } }).done( function(re) { tao.zin.re = JSON.parse(re); @@ -161,110 +154,59 @@ $(document).ready(function() { jQuery.timeago.settings.allowFuture = true; - if(sse_enabled) { - if(typeof(window.SharedWorker) === 'undefined') { - // notifications with multiple tabs open will not work very well in this scenario - var evtSource = new EventSource('/sse'); - - evtSource.addEventListener('notifications', function(e) { - var obj = JSON.parse(e.data); - sse_handleNotifications(obj, false, false); - }, false); + $(document).on('click', '.notification, .message', function(e) { + let b64mid = $(this).data('b64mid'); + let notify_id = $(this).data('notify_id'); + let path = $(this)[0].pathname.split('/')[1]; + let stateObj = { b64mid: b64mid }; + let singlethread_modules = ['display', 'hq', 'dm']; + let redirect_modules = ['display', 'notify']; - document.addEventListener('visibilitychange', function() { - if (!document.hidden) { - sse_offset = 0; - sse_bs_init(); - } - }, false); + if(! b64mid && ! notify_id) + return; + if(redirect_modules.indexOf(path) !== -1) { + path = 'hq'; } - else { - var myWorker = new SharedWorker('/view/js/sse_worker.js', localUser); - myWorker.port.onmessage = function(e) { - obj = e.data; - console.log(obj); - sse_handleNotifications(obj, false, false); - } - - myWorker.onerror = function(e) { - myWorker.port.close(); - } + if(notify_id != null) { + $.ajax({ + type: 'post', + url: 'notify', + data: { + 'notify_id' : notify_id + }, + async: ((module !== path) ? false : true) + }); + } - myWorker.port.start(); + if (module !== path) { + e.preventDefault(); + window.location.href = path + '/' + b64mid; } - } - else { - if (!document.hidden) - sse_fallback_interval = setInterval(sse_fallback, updateInterval); + else { - document.addEventListener('visibilitychange', function() { - if (document.hidden) { - clearInterval(sse_fallback_interval); - } - else { - sse_offset = 0; - sse_bs_init(); - sse_fallback_interval = setInterval(sse_fallback, updateInterval); + if (singlethread_modules.indexOf(module) !== -1) { + history.pushState(stateObj, '', module + '/' + b64mid); + $('.message').removeClass('active'); + $('[data-b64mid="' + b64mid + '"].message').addClass('active'); } - }, false); - } - - $('.notification-link').on('click', { replace: true, followup: false }, sse_bs_notifications); - - $('.notification-filter').on('keypress', function(e) { - if(e.which == 13) { // enter - this.blur(); - sse_offset = 0; - $("#nav-" + sse_type + "-menu").html(''); - $("#nav-" + sse_type + "-loading").show(); - - var cn_val = $('#cn-' + sse_type + '-input').length ? $('#cn-' + sse_type + '-input').val().toString().toLowerCase() : ''; + if (b64mid) { - $.get('/sse_bs/' + sse_type + '/' + sse_offset + '?nquery=' + encodeURIComponent(cn_val), function(obj) { - console.log('sse: bootstraping ' + sse_type); - console.log(obj); + e.preventDefault(); - sse_bs_active = false; - sse_partial_result = true; - sse_offset = obj[sse_type].offset; - if(sse_offset < 0) - $("#nav-" + sse_type + "-loading").hide(); - - sse_handleNotifications(obj, true, false); - - }); + if(! page_load) { + prepareLiveUpdate(b64mid, notify_id); + } + } } }); - $('.notifications-textinput-clear').on('click', function(e) { - if(! sse_partial_result) - return; - - $("#nav-" + sse_type + "-menu").html(''); - $("#nav-" + sse_type + "-loading").show(); - $.get('/sse_bs/' + sse_type, function(obj) { - console.log('sse: bootstraping ' + sse_type); - console.log(obj); - - sse_bs_active = false; - sse_partial_result = false; - sse_offset = obj[sse_type].offset; - if(sse_offset < 0) - $("#nav-" + sse_type + "-loading").hide(); - - sse_handleNotifications(obj, true, false); - - }); - }); - - $('.notification-content').on('scroll', function() { - if(this.scrollTop > this.scrollHeight - this.clientHeight - (this.scrollHeight/7)) { - sse_bs_notifications(sse_type, false, true); - } - }); + window.onpopstate = function(e) { + if(e.state !== null && e.state.b64mid !== bParam_mid) + prepareLiveUpdate(e.state.b64mid, ''); + }; //mod_mail only $(".mail-conv-detail .autotime").timeago(); @@ -967,6 +909,20 @@ function updateInit() { } } +function prepareLiveUpdate(b64mid, notify_id) { + $(document).scrollTop(0); + $('.thread-wrapper').remove(); + bParam_mid = b64mid; + mode = 'replace'; + page_load = true; + if (module == 'hq') { + liveUpdate(notify_id); + } + if (module == 'display'|| module == 'dm') { + liveUpdate(); + } +} + function liveUpdate(notify_id) { if(typeof profile_uid === 'undefined') profile_uid = false; /* Should probably be unified with channelId defined in head.tpl */ @@ -1052,7 +1008,7 @@ function liveUpdate(notify_id) { if(typeof notify_id !== 'undefined' && notify_id !== 'undefined') { $.post( - "hq", + "notify", { "notify_id" : notify_id } @@ -1760,288 +1716,6 @@ function zid(s) { return s; } -function sse_bs_init() { - if(sessionStorage.getItem('notification_open') !== null || typeof sse_type !== 'undefined' ) { - if(typeof sse_type === 'undefined') - sse_type = sessionStorage.getItem('notification_open'); - - $("#nav-" + sse_type + "-sub").addClass('show'); - sse_bs_notifications(sse_type, true, false); - } - else { - sse_bs_counts(); - } -} - -function sse_bs_counts() { - if(sse_bs_active) - return; - - sse_bs_active = true; - - $.ajax({ - type: 'post', - url: '/sse_bs', - data: { sse_rmids } - }).done( function(obj) { - console.log(obj); - sse_bs_active = false; - sse_rmids = []; - sse_handleNotifications(obj, true, false); - }); -} - -function sse_bs_notifications(e, replace, followup) { - - if(sse_bs_active) - return; - - - var manual = false; - - if(typeof replace === 'undefined') - replace = e.data.replace; - - if(typeof followup === 'undefined') - followup = e.data.followup; - - if(typeof e === 'string') { - sse_type = e; - } - else { - manual = true; - sse_offset = 0; - sse_type = e.target.dataset.sse_type; - } - - if(typeof sse_type === 'undefined') - return; - - if(followup || !manual || !($('#nav-' + sse_type + '-sub').hasClass('collapse') && $('#nav-' + sse_type + '-sub').hasClass('show'))) { - - if(sse_offset >= 0) { - $("#nav-" + sse_type + "-loading").show(); - } - - sessionStorage.setItem('notification_open', sse_type); - if(sse_offset !== -1 || replace) { - - var cn_val = (($('#cn-' + sse_type + '-input').length && sse_partial_result) ? $('#cn-' + sse_type + '-input').val().toString().toLowerCase() : ''); - - $("#nav-" + sse_type + "-loading").show(); - - sse_bs_active = true; - - $.ajax({ - type: 'post', - url: '/sse_bs/' + sse_type + '/' + sse_offset, - nquery: encodeURIComponent(cn_val), - data: { sse_rmids } - }).done(function(obj) { - console.log('sse: bootstraping ' + sse_type); - console.log(obj); - sse_bs_active = false; - sse_rmids = []; - $("#nav-" + sse_type + "-loading").hide(); - sse_offset = obj[sse_type].offset; - sse_handleNotifications(obj, replace, followup); - }); - } - else - $("#nav-" + sse_type + "-loading").hide(); - - } - else { - sessionStorage.removeItem('notification_open'); - } -} - -function sse_handleNotifications(obj, replace, followup) { - - var primary_notifications = ['dm', 'home', 'intros', 'register', 'notify', 'files']; - var secondary_notifications = ['network', 'forums', 'all_events', 'pubs']; - var all_notifications = primary_notifications.concat(secondary_notifications); - - all_notifications.forEach(function(type, index) { - if(typeof obj[type] === typeof undefined) - return true; - - if(obj[type].count) { - $('.' + type + '-button').fadeIn(); - if(replace || followup) - $('.' + type + '-update').html(Number(obj[type].count)); - else - $('.' + type + '-update').html(Number(obj[type].count) + Number($('.' + type + '-update').html())); - } - else { - $('.' + type + '-update').html('0'); - $('.' + type + '-button').fadeOut(function() { - sse_setNotificationsStatus(); - }); - } - if(obj[type].notifications.length) - sse_handleNotificationsItems(type, obj[type].notifications, replace, followup); - }); - - sse_setNotificationsStatus(); - - // notice and info - $.jGrowl.defaults.closerTemplate = '<div>[ ' + aStr.closeAll + ']</div>'; - - if(obj.notice) { - $(obj.notice.notifications).each(function() { - $.jGrowl(this, { sticky: true, theme: 'notice' }); - }); - } - - if(obj.info) { - $(obj.info.notifications).each(function(){ - $.jGrowl(this, { sticky: false, theme: 'info', life: 10000 }); - }); - } - - // load more notifications if visible notifications count becomes low - if(sse_type && sse_offset != -1 && $('#nav-' + sse_type + '-menu').children().length <= 20) { - sse_offset = 0; - sse_bs_notifications(sse_type, false, true); - } - - -} - -function sse_handleNotificationsItems(notifyType, data, replace, followup) { - - var notifications_tpl = ((notifyType == 'forums') ? decodeURIComponent($("#nav-notifications-forums-template[rel=template]").html().replace('data-src', 'src')) : decodeURIComponent($("#nav-notifications-template[rel=template]").html().replace('data-src', 'src'))); - var notify_menu = $("#nav-" + notifyType + "-menu"); - var notify_loading = $("#nav-" + notifyType + "-loading"); - var notify_count = $("." + notifyType + "-update"); - - if(replace && !followup) { - notify_menu.html(''); - notify_loading.hide(); - } - - $(data).each(function() { - - // do not add a notification if it is already present - if($('#nav-' + notifyType + '-menu .notification[data-b64mid=\'' + this.b64mid + '\']').length) - return true; - - html = notifications_tpl.format(this.notify_link,this.photo,this.name,this.addr,this.message,this.when,this.hclass,this.b64mid,this.notify_id,this.thread_top,this.unseen,this.private_forum, encodeURIComponent(this.mids), this.body); - notify_menu.append(html); - }); - - if(!replace && !followup) { - $("#nav-" + notifyType + "-menu .notification").sort(function(a,b) { - a = new Date(a.dataset.when); - b = new Date(b.dataset.when); - return a > b ? -1 : a < b ? 1 : 0; - }).appendTo('#nav-' + notifyType + '-menu'); - } - - $(document.body).trigger("sticky_kit:recalc"); - $("#nav-" + notifyType + "-menu .notifications-autotime").timeago(); - - if($('#tt-' + notifyType + '-only').hasClass('active')) - $('#nav-' + notifyType + '-menu [data-thread_top=false]').addClass('tt-filter-active'); - - if($('#cn-' + notifyType + '-input').length) { - var filter = $('#cn-' + notifyType + '-input').val().toString().toLowerCase(); - if(filter) { - filter = filter.indexOf('%') == 0 ? filter.substring(1) : filter; - - $('#nav-' + notifyType + '-menu .notification').each(function(i, el) { - var cn = $(el).data('contact_name').toString().toLowerCase(); - var ca = $(el).data('contact_addr').toString().toLowerCase(); - if(cn.indexOf(filter) === -1 && ca.indexOf(filter) === -1) - $(el).addClass('cn-filter-active'); - else - $(el).removeClass('cn-filter-active'); - }); - } - } -} - -function sse_updateNotifications(type, mid) { - - if(type === 'pubs') - return true; - - if(type === 'notify' && (mid !== bParam_mid || sse_type !== 'notify')) - return true; -/* - var count = Number($('.' + type + '-update').html()); - - count--; - - if(count < 1) { - $('.' + type + '-update').html(count); - $('.' + type + '-button').fadeOut(function() { - sse_setNotificationsStatus(); - }); - } - else { - $('.' + type + '-update').html(count); - } -*/ - - $('#nav-' + type + '-menu .notification[data-b64mid=\'' + mid + '\']').fadeOut(function() { - this.remove(); - }); - -} - -function sse_setNotificationsStatus() { - var primary_notifications = ['dm', 'home', 'intros', 'register', 'notify', 'files']; - var secondary_notifications = ['network', 'forums', 'all_events', 'pubs']; - var all_notifications = primary_notifications.concat(secondary_notifications); - - var primary_available = false; - var any_available = false; - - all_notifications.forEach(function(type, index) { - if($('.' + type + '-button').css('display') == 'block') { - any_available = true; - if(primary_notifications.indexOf(type) > -1) - primary_available = true; - } - }); - - if(primary_available) { - $('.notifications-btn-icon').removeClass('fa-exclamation-circle'); - $('.notifications-btn-icon').addClass('fa-exclamation-triangle'); - } - else { - $('.notifications-btn-icon').removeClass('fa-exclamation-triangle'); - $('.notifications-btn-icon').addClass('fa-exclamation-circle'); - } - - if(any_available) { - $('.notifications-btn').css('opacity', 1); - $('#no_notifications').hide(); - $('#notifications').show(); - } - else { - $('.notifications-btn').css('opacity', 0.5); - $('#navbar-collapse-1').removeClass('show'); - $('#no_notifications').show(); - $('#notifications').hide(); - } - -} - -function sse_fallback() { - $.get('/sse', function(obj) { - if(! obj) - return; - - console.log('sse fallback'); - console.log(obj); - - sse_handleNotifications(obj, false, false); - }); -} - function makeid(length) { var result = ''; var characters = 'abcdef0123456789'; @@ -2051,3 +1725,4 @@ function makeid(length) { } return result; } + diff --git a/view/js/mod_hq.js b/view/js/mod_hq.js index b321382bd..ddcde4fcd 100644 --- a/view/js/mod_hq.js +++ b/view/js/mod_hq.js @@ -1,10 +1,20 @@ -$(document).on('click', '#jot-toggle', function(e) { - e.preventDefault(); - e.stopPropagation(); - - $(this).toggleClass('active'); - $(window).scrollTop(0); - $('#jot-popup').toggle(); - $('#profile-jot-text').focus(); +$(document).ready(function() { + + $(document).on('click', '#jot-toggle', function(e) { + e.preventDefault(); + e.stopPropagation(); + $(window).scrollTop(0); + $('#jot-popup').toggle(); + $('#profile-jot-text').focus(); + + }); + + $(document).on('click', '#notes-toggle', function(e) { + e.preventDefault(); + e.stopPropagation(); + $(window).scrollTop(0); + $('#personal-notes').toggleClass('d-none'); + $('#note-text').focus(); + }); }); diff --git a/view/pdl/mod_hq.pdl b/view/pdl/mod_hq.pdl index 1bcdb2c65..348b6c525 100644 --- a/view/pdl/mod_hq.pdl +++ b/view/pdl/mod_hq.pdl @@ -1,6 +1,14 @@ [region=aside] +[widget=messages][/widget] [widget=hq_controls][/widget] [/region] +[region=content] +[widget=notes] + [var=hidden]1[/var] + [var=app]1[/var] +[/widget] +$content +[/region] [region=right_aside] [widget=notifications][/widget] [widget=newmember][/widget] diff --git a/view/tpl/head.tpl b/view/tpl/head.tpl index ecb30afd3..bf61a7ee4 100644 --- a/view/tpl/head.tpl +++ b/view/tpl/head.tpl @@ -17,6 +17,7 @@ var channelId = {{if $channel_id}}{{$channel_id}}{{else}}false{{/if}};{{* Used in e.g. autocomplete *}} var preloadImages = {{$preload_images}}; var auto_save_draft = {{$auto_save_draft}}; + {{if $module}}var module = '{{$module}}';{{/if}} </script> diff --git a/view/tpl/hq_controls.tpl b/view/tpl/hq_controls.tpl index d7f6d436f..f3860a949 100644 --- a/view/tpl/hq_controls.tpl +++ b/view/tpl/hq_controls.tpl @@ -1,8 +1,7 @@ -<div class="widget"> - <h3>{{$title}}</h3> - <ul class="nav nav-pills flex-column"> - {{foreach $menu as $m}} - <li class="nav-item"><a href="{{$m.href}}" id="{{$m.id}}" class="nav-link{{if $m.class}} {{$m.class}}{{/if}}">{{$m.label}}</a></li> - {{/foreach}} - </ul> +<div class="d-grid gap-2 mb-3"> + {{foreach $entries as $e}} + <button id="{{$e.id}}" class="{{$e.class}} rounded-circle" type="{{$e.type}}" title="{{$e.label}}"{{if $extra}} {{$extra}}{{/if}}> + {{if $e.icon}}<i class="fa fa-{{$e.icon}}"></i>{{/if}} + </button> + {{/foreach}} </div> diff --git a/view/tpl/messages_widget.tpl b/view/tpl/messages_widget.tpl new file mode 100644 index 000000000..7ba02e78e --- /dev/null +++ b/view/tpl/messages_widget.tpl @@ -0,0 +1,123 @@ +<ul class="nav nav-tabs nav-fill"> + <li class="nav-item"> + <a class="nav-link active messages-type" href="#" title="{{$strings.messages_title}}" data-messages_type=""> + <i class="fa fa-fw fa-comment-o"></i> + </a> + </li> + <li class="nav-item"> + <a class="nav-link messages-type" href="#" title="{{$strings.direct_messages_title}}" data-messages_type="direct"> + <i class="fa fa-fw fa-envelope-o"></i> + </a> + </li> + {{if $feature_star}} + <li class="nav-item"> + <a class="nav-link messages-type" href="#" title="{{$strings.starred_messages_title}}" data-messages_type="starred"> + <i class="fa fa-fw fa-star"></i> + </a> + </li> + {{/if}} +</ul> +<div id="messages-widget" class="border border-top-0 overflow-auto mb-3" style="height: 70vh;"> + <div id="messages-template" rel="template" class="d-none"> + <a href="{6}" class="list-group-item list-group-item-action message" data-b64mid="{0}"> + <div class="d-flex w-100 justify-content-between"> + <div class="mb-1 text-truncate" title="{5}"> + {7} + <strong>{4}</strong> + </div> + <small class="messages-timeago text-nowrap" title="{1}"></small> + </div> + <div class="mb-1"> + <div class="text-break">{2}</div> + </div> + <small>{3}</small> + </a> + </div> + <div id="dm-container" class="list-group list-group-flush" data-offset="10"> + {{foreach $entries as $e}} + <a href="{{$e.href}}" class="list-group-item list-group-item-action message" data-b64mid="{{$e.b64mid}}"> + <div class="d-flex w-100 justify-content-between"> + <div class="mb-1 text-truncate" title="{{$e.author_addr}}"> + {{$e.icon}} + <strong>{{$e.author_name}}</strong> + </div> + <small class="messages-timeago text-nowrap" title="{{$e.created}}"></small> + </div> + <div class="mb-1"> + <div class="text-break">{{$e.summary}}</div> + </div> + <small>{{$e.info}}</small> + </a> + {{/foreach}} + <div id="messages-loading" class="list-group-item" style="display: none;"> + {{$strings.loading}}<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span> + </div> + </div> +</div> +<script> + var messages_offset = {{$offset}}; + var get_messages_page_active = false; + var messages_type; + + $('#messages-widget').on('scroll', function() { + if(this.scrollTop > this.scrollHeight - this.clientHeight - (this.scrollHeight/7)) { + get_messages_page('hq'); + } + }); + + $(document).on('click', '.messages-type', function(e) { + e.preventDefault(); + $('.messages-type').removeClass('active'); + $(this).addClass('active'); + messages_offset = 0; + messages_type = $(this).data('messages_type'); + $('#dm-container .message').remove(); + get_messages_page(); + }); + + $('.messages-timeago').timeago(); + $('.message[data-b64mid=\'' + bParam_mid + '\']').addClass('active'); + + function get_messages_page() { + if (get_messages_page_active) + return; + + if (messages_offset === -1) + return; + + get_messages_page_active = true; + $('#messages-loading').show(); + $.ajax({ + type: 'post', + url: 'hq', + data: { + offset: messages_offset, + type: messages_type + } + }).done(function(obj) { + get_messages_page_active = false; + messages_offset = obj.offset; + console.log(obj); + let html; + let tpl = $('#messages-template[rel=template]').html(); + obj.entries.forEach(function(e) { + html = tpl.format( + e.b64mid, + e.created, + e.summary, + e.info, + e.author_name, + e.author_addr, + e.href, + e.icon + ); + $('#messages-loading').before(html); + }); + $('.message[data-b64mid=\'' + bParam_mid + '\']').addClass('active'); + $('#messages-loading').hide(); + $('.messages-timeago').timeago(); + + }); + } + +</script> diff --git a/view/tpl/notes.tpl b/view/tpl/notes.tpl index 4bee02aa0..0ae0604ef 100644 --- a/view/tpl/notes.tpl +++ b/view/tpl/notes.tpl @@ -1,24 +1,18 @@ {{if $app}} -<div class="generic-content-wrapper"> +<div id="personal-notes" class="generic-content-wrapper{{if $hidden}} d-none{{/if}}"> <div class="section-title-wrapper"> <h2>{{$banner}}</h2> </div> <div class="section-content-wrapper"> {{else}} -<div class="widget"> +<div id="personal-notes" class="widget{{if $hidden}} d-none{{/if}}"> <h3>{{$banner}}</h3> {{/if}} - <textarea name="note_text" id="note-text">{{$text}}</textarea> + <textarea name="note_text" id="note-text" class="{{if $app}}form-control border-0{{/if}}">{{$text}}</textarea> <script> var noteSaveTimer = null; var noteText = $('#note-text'); - $(document).ready(function(e){ - noteText.on('change keyup keydown paste cut', function () { - noteText.height(0).height(noteText[0].scrollHeight); - }).change(); - }); - $(document).on('focusout',"#note-text",function(e){ if(noteSaveTimer) clearTimeout(noteSaveTimer); diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl index 1092bc155..0d922e416 100644 --- a/view/tpl/notifications_widget.tpl +++ b/view/tpl/notifications_widget.tpl @@ -1,9 +1,17 @@ -{{if $notifications}} <script> - var notifications_parent; + var sse_bs_active = false; + var sse_offset = 0; + var sse_type; + var sse_partial_result = false; + var sse_rmids = []; + var sse_fallback_interval; $(document).ready(function() { - notifications_parent = $('#notifications_wrapper')[0].parentElement.id; + let notifications_parent; + if ($('#notifications_wrapper').length) { + notifications_parent = $('#notifications_wrapper')[0].parentElement.id; + } + $('.notifications-btn').click(function() { if($('#notifications_wrapper').hasClass('fs')) { $('#notifications_wrapper').prependTo('#' + notifications_parent); @@ -23,60 +31,118 @@ } }); - window.onpopstate = function(e) { - if(e.state !== null && e.state.b64mid !== bParam_mid) - getData(e.state.b64mid, ''); - }; - }); + $(document).on('click', '.notification', function() { + if($('#notifications_wrapper').hasClass('fs')) { + $('#notifications_wrapper').prependTo('#' + notifications_parent).removeClass('fs'); + } + }); - {{if $module == 'display' || $module == 'hq' || $startpage == 'hq'}} - $(document).on('click', '.notification', function(e) { - var b64mid = $(this).data('b64mid'); - var notify_id = $(this).data('notify_id'); - var path = $(this)[0].pathname.substr(1,7); - var stateObj = { b64mid: b64mid }; + if(sse_enabled) { + if(typeof(window.SharedWorker) === 'undefined') { + // notifications with multiple tabs open will not work very well in this scenario + var evtSource = new EventSource('/sse'); - if(! b64mid && ! notify_id) - return; + evtSource.addEventListener('notifications', function(e) { + var obj = JSON.parse(e.data); + sse_handleNotifications(obj, false, false); + }, false); - {{if $module != 'hq' && $startpage == 'hq'}} - e.preventDefault(); - if(notify_id != null) { - $.post( - "hq", - { - "notify_id" : notify_id + document.addEventListener('visibilitychange', function() { + if (!document.hidden) { + sse_offset = 0; + sse_bs_init(); } - ); + }, false); + } - window.location.href = 'hq/' + b64mid; - return; - {{else}} - {{if $module == 'display'}} - history.pushState(stateObj, '', 'display/' + b64mid); - {{/if}} - - {{if $module == 'hq'}} - history.pushState(stateObj, '', 'hq/' + b64mid); - {{/if}} - - {{if $module == 'hq'}} - if(b64mid) { - {{else}} - if(path === 'display' && b64mid) { - {{/if}} - e.preventDefault(); - - if(! page_load) { - getData(b64mid, notify_id); + else { + var myWorker = new SharedWorker('/view/js/sse_worker.js', localUser); + + myWorker.port.onmessage = function(e) { + obj = e.data; + console.log(obj); + sse_handleNotifications(obj, false, false); + } + + myWorker.onerror = function(e) { + myWorker.port.close(); + } + + myWorker.port.start(); + } + } + else { + if (!document.hidden) + sse_fallback_interval = setInterval(sse_fallback, updateInterval); + + document.addEventListener('visibilitychange', function() { + if (document.hidden) { + clearInterval(sse_fallback_interval); } + else { + sse_offset = 0; + sse_bs_init(); + sse_fallback_interval = setInterval(sse_fallback, updateInterval); + } + + }, false); + } + + $('.notification-link').on('click', { replace: true, followup: false }, sse_bs_notifications); + + $('.notification-filter').on('keypress', function(e) { + if(e.which == 13) { // enter + this.blur(); + sse_offset = 0; + $("#nav-" + sse_type + "-menu").html(''); + $("#nav-" + sse_type + "-loading").show(); + + var cn_val = $('#cn-' + sse_type + '-input').length ? $('#cn-' + sse_type + '-input').val().toString().toLowerCase() : ''; + + $.get('/sse_bs/' + sse_type + '/' + sse_offset + '?nquery=' + encodeURIComponent(cn_val), function(obj) { + console.log('sse: bootstraping ' + sse_type); + console.log(obj); + + sse_bs_active = false; + sse_partial_result = true; + sse_offset = obj[sse_type].offset; + if(sse_offset < 0) + $("#nav-" + sse_type + "-loading").hide(); + + sse_handleNotifications(obj, true, false); + + }); + } + }); + + $('.notifications-textinput-clear').on('click', function(e) { + if(! sse_partial_result) + return; + + $("#nav-" + sse_type + "-menu").html(''); + $("#nav-" + sse_type + "-loading").show(); + $.get('/sse_bs/' + sse_type, function(obj) { + console.log('sse: bootstraping ' + sse_type); + console.log(obj); + + sse_bs_active = false; + sse_partial_result = false; + sse_offset = obj[sse_type].offset; + if(sse_offset < 0) + $("#nav-" + sse_type + "-loading").hide(); + + sse_handleNotifications(obj, true, false); + + }); + }); - if($('#notifications_wrapper').hasClass('fs')) - $('#notifications_wrapper').prependTo('#' + notifications_parent).removeClass('fs'); + $('.notification-content').on('scroll', function() { + if(this.scrollTop > this.scrollHeight - this.clientHeight - (this.scrollHeight/7)) { + sse_bs_notifications(sse_type, false, true); } - {{/if}} + }); + }); - {{/if}} {{foreach $notifications as $notification}} {{if $notification.filter}} @@ -91,12 +157,14 @@ } }); + $(document).on('click', '#cn-{{$notification.type}}-input-clear', function(e) { $('#cn-{{$notification.type}}-input').val(''); $('#cn-{{$notification.type}}-only').removeClass('active sticky-top'); $("#nav-{{$notification.type}}-menu .notification").removeClass('cn-filter-active'); $('#cn-{{$notification.type}}-input-clear').addClass('d-none'); }); + $(document).on('input', '#cn-{{$notification.type}}-input', function(e) { var val = $('#cn-{{$notification.type}}-input').val().toString().toLowerCase(); if(val) { @@ -122,18 +190,284 @@ {{/if}} {{/foreach}} - function getData(b64mid, notify_id) { - $(document).scrollTop(0); - $('.thread-wrapper').remove(); - bParam_mid = b64mid; - mode = 'replace'; - page_load = true; - {{if $module == 'hq'}} - liveUpdate(notify_id); - {{/if}} - {{if $module == 'display'}} - liveUpdate(); - {{/if}} + function sse_bs_init() { + if(sessionStorage.getItem('notification_open') !== null || typeof sse_type !== 'undefined' ) { + if(typeof sse_type === 'undefined') + sse_type = sessionStorage.getItem('notification_open'); + + $("#nav-" + sse_type + "-sub").addClass('show'); + sse_bs_notifications(sse_type, true, false); + } + else { + sse_bs_counts(); + } + } + + function sse_bs_counts() { + if(sse_bs_active) + return; + + sse_bs_active = true; + + $.ajax({ + type: 'post', + url: '/sse_bs', + data: { sse_rmids } + }).done( function(obj) { + console.log(obj); + sse_bs_active = false; + sse_rmids = []; + sse_handleNotifications(obj, true, false); + }); + } + + function sse_bs_notifications(e, replace, followup) { + + if(sse_bs_active) + return; + + var manual = false; + + if(typeof replace === 'undefined') + replace = e.data.replace; + + if(typeof followup === 'undefined') + followup = e.data.followup; + + if(typeof e === 'string') { + sse_type = e; + } + else { + manual = true; + sse_offset = 0; + sse_type = e.target.dataset.sse_type; + } + + if(typeof sse_type === 'undefined') + return; + + if(followup || !manual || !($('#nav-' + sse_type + '-sub').hasClass('collapse') && $('#nav-' + sse_type + '-sub').hasClass('show'))) { + + if(sse_offset >= 0) { + $("#nav-" + sse_type + "-loading").show(); + } + + sessionStorage.setItem('notification_open', sse_type); + if(sse_offset !== -1 || replace) { + + var cn_val = (($('#cn-' + sse_type + '-input').length && sse_partial_result) ? $('#cn-' + sse_type + '-input').val().toString().toLowerCase() : ''); + + $("#nav-" + sse_type + "-loading").show(); + + sse_bs_active = true; + + $.ajax({ + type: 'post', + url: '/sse_bs/' + sse_type + '/' + sse_offset, + nquery: encodeURIComponent(cn_val), + data: { sse_rmids } + }).done(function(obj) { + console.log('sse: bootstraping ' + sse_type); + console.log(obj); + sse_bs_active = false; + sse_rmids = []; + $("#nav-" + sse_type + "-loading").hide(); + sse_offset = obj[sse_type].offset; + sse_handleNotifications(obj, replace, followup); + }); + } + else + $("#nav-" + sse_type + "-loading").hide(); + + } + else { + sessionStorage.removeItem('notification_open'); + } + } + + function sse_handleNotifications(obj, replace, followup) { + + var primary_notifications = ['dm', 'home', 'intros', 'register', 'notify', 'files']; + var secondary_notifications = ['network', 'forums', 'all_events', 'pubs']; + var all_notifications = primary_notifications.concat(secondary_notifications); + + all_notifications.forEach(function(type, index) { + if(typeof obj[type] === typeof undefined) + return true; + + if(obj[type].count) { + $('.' + type + '-button').fadeIn(); + if(replace || followup) + $('.' + type + '-update').html(Number(obj[type].count)); + else + $('.' + type + '-update').html(Number(obj[type].count) + Number($('.' + type + '-update').html())); + } + else { + $('.' + type + '-update').html('0'); + $('.' + type + '-button').fadeOut(function() { + sse_setNotificationsStatus(); + }); + } + if(obj[type].notifications.length) + sse_handleNotificationsItems(type, obj[type].notifications, replace, followup); + }); + + sse_setNotificationsStatus(); + + // notice and info + $.jGrowl.defaults.closerTemplate = '<div>[ ' + aStr.closeAll + ']</div>'; + + if(obj.notice) { + $(obj.notice.notifications).each(function() { + $.jGrowl(this, { sticky: true, theme: 'notice' }); + }); + } + + if(obj.info) { + $(obj.info.notifications).each(function(){ + $.jGrowl(this, { sticky: false, theme: 'info', life: 10000 }); + }); + } + + // load more notifications if visible notifications count becomes low + if(sse_type && sse_offset != -1 && $('#nav-' + sse_type + '-menu').children().length < 15) { + sse_offset = 0; + sse_bs_notifications(sse_type, false, true); + } + + + } + + function sse_handleNotificationsItems(notifyType, data, replace, followup) { + + var notifications_tpl = ((notifyType == 'forums') ? decodeURIComponent($("#nav-notifications-forums-template[rel=template]").html().replace('data-src', 'src')) : decodeURIComponent($("#nav-notifications-template[rel=template]").html().replace('data-src', 'src'))); + var notify_menu = $("#nav-" + notifyType + "-menu"); + var notify_loading = $("#nav-" + notifyType + "-loading"); + var notify_count = $("." + notifyType + "-update"); + + if(replace && !followup) { + notify_menu.html(''); + notify_loading.hide(); + } + + $(data).each(function() { + + // do not add a notification if it is already present + if($('#nav-' + notifyType + '-menu .notification[data-b64mid=\'' + this.b64mid + '\']').length) + return true; + + html = notifications_tpl.format(this.notify_link,this.photo,this.name,this.addr,this.message,this.when,this.hclass,this.b64mid,this.notify_id,this.thread_top,this.unseen,this.private_forum, encodeURIComponent(this.mids), this.body); + notify_menu.append(html); + }); + + if(!replace && !followup) { + $("#nav-" + notifyType + "-menu .notification").sort(function(a,b) { + a = new Date(a.dataset.when); + b = new Date(b.dataset.when); + return a > b ? -1 : a < b ? 1 : 0; + }).appendTo('#nav-' + notifyType + '-menu'); + } + + $("#nav-" + notifyType + "-menu .notifications-autotime").timeago(); + + if($('#tt-' + notifyType + '-only').hasClass('active')) + $('#nav-' + notifyType + '-menu [data-thread_top=false]').addClass('tt-filter-active'); + + if($('#cn-' + notifyType + '-input').length) { + var filter = $('#cn-' + notifyType + '-input').val().toString().toLowerCase(); + if(filter) { + filter = filter.indexOf('%') == 0 ? filter.substring(1) : filter; + + $('#nav-' + notifyType + '-menu .notification').each(function(i, el) { + var cn = $(el).data('contact_name').toString().toLowerCase(); + var ca = $(el).data('contact_addr').toString().toLowerCase(); + if(cn.indexOf(filter) === -1 && ca.indexOf(filter) === -1) + $(el).addClass('cn-filter-active'); + else + $(el).removeClass('cn-filter-active'); + }); + } + } + } + + function sse_updateNotifications(type, mid) { + + if(type === 'pubs') + return true; + + if(type === 'notify' && (mid !== bParam_mid || sse_type !== 'notify')) + return true; + /* + var count = Number($('.' + type + '-update').html()); + + count--; + + if(count < 1) { + $('.' + type + '-update').html(count); + $('.' + type + '-button').fadeOut(function() { + sse_setNotificationsStatus(); + }); + } + else { + $('.' + type + '-update').html(count); + } + */ + + $('#nav-' + type + '-menu .notification[data-b64mid=\'' + mid + '\']').fadeOut(function() { + this.remove(); + }); + + } + + function sse_setNotificationsStatus() { + var primary_notifications = ['dm', 'home', 'intros', 'register', 'notify', 'files']; + var secondary_notifications = ['network', 'forums', 'all_events', 'pubs']; + var all_notifications = primary_notifications.concat(secondary_notifications); + + var primary_available = false; + var any_available = false; + + all_notifications.forEach(function(type, index) { + if($('.' + type + '-button').css('display') == 'block') { + any_available = true; + if(primary_notifications.indexOf(type) > -1) + primary_available = true; + } + }); + + if(primary_available) { + $('.notifications-btn-icon').removeClass('fa-exclamation-circle'); + $('.notifications-btn-icon').addClass('fa-exclamation-triangle'); + } + else { + $('.notifications-btn-icon').removeClass('fa-exclamation-triangle'); + $('.notifications-btn-icon').addClass('fa-exclamation-circle'); + } + + if(any_available) { + $('.notifications-btn').css('opacity', 1); + $('#no_notifications').hide(); + $('#notifications').show(); + } + else { + $('.notifications-btn').css('opacity', 0.5); + $('#navbar-collapse-1').removeClass('show'); + $('#no_notifications').show(); + $('#notifications').hide(); + } + + } + + function sse_fallback() { + $.get('/sse', function(obj) { + if(! obj) + return; + + console.log('sse fallback'); + console.log(obj); + + sse_handleNotifications(obj, false, false); + }); } </script> @@ -199,4 +533,3 @@ {{/foreach}} </div> </div> -{{/if}} |