aboutsummaryrefslogtreecommitdiffstats
path: root/view
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2019-11-11 21:30:38 +0100
committerMax Kostikov <max@kostikov.co>2019-11-11 21:30:38 +0100
commitb033597ada02ef045bc9fbdb2237f81935b73e47 (patch)
treeecc8af0a821436c576e01627ee3c76c6c8ba254d /view
parent89342ca9fbf329d5e84839c51f26db19bdd4ac8c (diff)
downloadvolse-hubzilla-b033597ada02ef045bc9fbdb2237f81935b73e47.tar.gz
volse-hubzilla-b033597ada02ef045bc9fbdb2237f81935b73e47.tar.bz2
volse-hubzilla-b033597ada02ef045bc9fbdb2237f81935b73e47.zip
sse notifications
Diffstat (limited to 'view')
-rw-r--r--view/css/widgets.css5
-rw-r--r--view/de-de/hstrings.php2
-rw-r--r--view/js/main.js531
-rwxr-xr-xview/js/sse_worker.js14
-rw-r--r--view/php/theme_init.php1
-rw-r--r--view/tpl/activity_filter_widget.tpl2
-rwxr-xr-xview/tpl/conv_item.tpl4
-rwxr-xr-xview/tpl/conv_list.tpl2
-rwxr-xr-xview/tpl/js_strings.tpl2
-rw-r--r--view/tpl/notifications_widget.tpl28
10 files changed, 535 insertions, 56 deletions
diff --git a/view/css/widgets.css b/view/css/widgets.css
index 995647d1c..ca7267189 100644
--- a/view/css/widgets.css
+++ b/view/css/widgets.css
@@ -181,7 +181,6 @@ a.wikilist {
.notifications-textinput {
padding: .75rem 0.85rem;
- position: relative;
}
.notifications-textinput input {
@@ -233,3 +232,7 @@ a.wikilist {
margin-top: 25px;
opacity: 0.8;
}
+
+#cid-filter-wrapper {
+ position: relative;
+}
diff --git a/view/de-de/hstrings.php b/view/de-de/hstrings.php
index 5e16040e2..2f411a1d1 100644
--- a/view/de-de/hstrings.php
+++ b/view/de-de/hstrings.php
@@ -77,7 +77,7 @@ App::$strings["Search"] = "Suche";
App::$strings["Search site @name, !forum, #tag, ?docs, content"] = "Hub durchsuchen: @Name, !Forum, #Schlagwort, ?Dokumentation, Inhalt";
App::$strings["Admin"] = "Administration";
App::$strings["Site Setup and Configuration"] = "Seiten-Einrichtung und -Konfiguration";
-App::$strings["Loading"] = "Lädt...";
+App::$strings["Loading"] = "Lädt";
App::$strings["@name, !forum, #tag, ?doc, content"] = "@Name, !Forum, #Schlagwort, ?Dokumentation, Inhalt";
App::$strings["Please wait..."] = "Bitte warten...";
App::$strings["Add Apps"] = "Apps hinzufügen";
diff --git a/view/js/main.js b/view/js/main.js
index f3b8151b0..f15636a35 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -24,7 +24,31 @@ var contentHeightDiff = 0;
var liveRecurse = 0;
var savedTitle = '';
var initialLoad = true;
+var window_needs_alert = true;
+
+var sse_bs_active = false;
+var sse_offset = 0;
+var sse_type;
+var sse_partial_result = false;
+
+// take care of tab/window reloads on channel change
+if(localStorage.getItem('uid') !== localUser.toString()) {
+ localStorage.setItem('uid', localUser.toString());
+}
+window.onstorage = function(e) {
+ if(e.key === 'uid' && parseInt(e.newValue) !== localUser) {
+ if(window_needs_alert) {
+ window_needs_alert = false;
+ localStorage.clear();
+ sessionStorage.clear();
+ alert("Your identity has changed. Page reload required!");
+ window.location.reload();
+ return;
+ }
+ }
+}
+/*
// Clear the session and local storage if we switch channel or log out
var cache_uid = '';
if(sessionStorage.getItem('uid') !== null) {
@@ -35,6 +59,7 @@ if(cache_uid !== localUser.toString()) {
localStorage.clear();
sessionStorage.setItem('uid', localUser.toString());
}
+*/
$.ajaxSetup({cache: false});
@@ -55,28 +80,114 @@ $(document).ready(function() {
}
});
- var tf = new Function('n', 's', 'var k = s.split("/")['+aStr['plural_func']+']; return (k ? k : s);');
-
- jQuery.timeago.settings.strings = {
- prefixAgo : aStr['t01'],
- prefixFromNow : aStr['t02'],
- suffixAgo : aStr['t03'],
- suffixFromNow : aStr['t04'],
- seconds : aStr['t05'],
- minute : aStr['t06'],
- minutes : function(value){return tf(value, aStr['t07']);},
- hour : aStr['t08'],
- hours : function(value){return tf(value, aStr['t09']);},
- day : aStr['t10'],
- days : function(value){return tf(value, aStr['t11']);},
- month : aStr['t12'],
- months : function(value){return tf(value, aStr['t13']);},
- year : aStr['t14'],
- years : function(value){return tf(value, aStr['t15']);},
- wordSeparator : aStr['t16'],
- numbers : aStr['t17'],
- };
+ var tf = new Function('n', 's', 'var k = s.split("/")['+aStr['plural_func']+']; return (k ? k : s);');
+
+ jQuery.timeago.settings.strings = {
+ prefixAgo : aStr['t01'],
+ prefixFromNow : aStr['t02'],
+ suffixAgo : aStr['t03'],
+ suffixFromNow : aStr['t04'],
+ seconds : aStr['t05'],
+ minute : aStr['t06'],
+ minutes : function(value){return tf(value, aStr['t07']);},
+ hour : aStr['t08'],
+ hours : function(value){return tf(value, aStr['t09']);},
+ day : aStr['t10'],
+ days : function(value){return tf(value, aStr['t11']);},
+ month : aStr['t12'],
+ months : function(value){return tf(value, aStr['t13']);},
+ year : aStr['t14'],
+ years : function(value){return tf(value, aStr['t15']);},
+ wordSeparator : aStr['t16'],
+ numbers : aStr['t17'],
+ };
+
+
+ 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.addEventListener('visibilitychange', function() {
+ if (!document.hidden) {
+ sse_offset = 0;
+ sse_bs_init();
+ }
+ }, false);
+
+ }
+ 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();
+ }
+
+ sse_bs_init();
+
+ $('.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_handleNotifications(obj, true, false);
+ sse_bs_active = false;
+ sse_partial_result = true;
+ sse_offset = obj[sse_type].offset;
+ if(sse_offset < 0)
+ $("#nav-" + sse_type + "-loading").hide();
+
+ });
+ }
+ });
+
+ $('.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_handleNotifications(obj, true, false);
+ sse_bs_active = false;
+ sse_partial_result = false;
+ sse_offset = obj[sse_type].offset;
+ if(sse_offset < 0)
+ $("#nav-" + sse_type + "-loading").hide();
+
+ });
+ });
+ $('.notification-content').on('scroll', function() {
+ if(this.scrollTop > this.scrollHeight - this.clientHeight - (this.scrollHeight/7)) {
+ if(!sse_bs_active)
+ sse_bs_notifications(sse_type, false, true);
+ }
+ });
//mod_mail only
$(".mail-conv-detail .autotime").timeago();
@@ -85,6 +196,7 @@ $(document).ready(function() {
updateInit();
+/*
$('a.notification-link').click(function(e){
var notifyType = $(this).data('type');
@@ -102,6 +214,7 @@ $(document).ready(function() {
$('#nav-' + notifyType + '-sub').addClass('show');
loadNotificationItems(notifyType);
}
+*/
// Allow folks to stop the ajax page updates with the pause/break key
$(document).keydown(function(event) {
@@ -462,6 +575,7 @@ function markItemRead(itemId) {
$('.unseen-wall-indicator-'+itemId).hide();
}
+/*
function notificationsUpdate(cached_data) {
var pingCmd = 'ping' + ((localUser != 0) ? '?f=&uid=' + localUser : '');
@@ -545,7 +659,7 @@ function handleNotifications(data) {
$.each(data, function(index, item) {
//do not process those
- var arr = ['notice', 'info', 'invalid'];
+ var arr = ['notice', 'info', 'invalid', 'network', 'home', 'notify', 'intros'];
if(arr.indexOf(index) !== -1)
return;
@@ -565,10 +679,11 @@ function handleNotificationsItems(notifyType, data) {
notify_menu.html('');
- $(data).each(function() {
+ $(data.reverse()).each(function() {
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);
- notify_menu.append(html);
+ notify_menu.prepend(html);
});
+ $(".notifications-autotime").timeago();
datasrc2src('#notifications .notification img[data-src]');
@@ -578,6 +693,7 @@ function handleNotificationsItems(notifyType, data) {
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();
@@ -589,6 +705,7 @@ function handleNotificationsItems(notifyType, data) {
}
}
}
+*/
function contextualHelp() {
var container = $("#contextual-help-content");
@@ -718,13 +835,10 @@ function updateConvItems(mode,data) {
}
}
-
-
// trigger the autotime function on all newly created content
-
$("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago();
$("> .shared_header .autotime",this).timeago();
-
+
if((mode === 'append' || mode === 'replace') && (loadingPage)) {
loadingPage = false;
}
@@ -744,6 +858,42 @@ function updateConvItems(mode,data) {
}
});
+
+ // take care of the notifications count updates
+ $('.thread-wrapper', data).each(function() {
+
+ var nmid = $(this).data('b64mid');
+
+ if($('.notification[data-b64mid=\'' + nmid + '\']').length) {
+ $('.notification[data-b64mid=\'' + nmid + '\']').each(function() {
+ var n = this.parentElement.id.split('-');
+
+ if(n[1] === 'pubs')
+ return true;
+
+ if(n[1] === 'notify' && (nmid !== bParam_mid || sse_type !== 'notify'))
+ return true;
+
+ var count = Number($('.' + n[1] + '-update').html());
+
+ if(count > 0)
+ count = count - 1;
+
+ if(count < 1) {
+ $('.' + n[1] + '-button').fadeOut();
+ $('.' + n[1] + '-update').html(count);
+ }
+ else
+ $('.' + n[1] + '-update').html(count);
+
+ $('#nav-' + n[1] + '-menu .notification[data-b64mid=\'' + nmid + '\']').fadeOut();
+
+ });
+ }
+
+ });
+
+
// reset rotators and cursors we may have set before reaching this place
$('.like-rotator').hide();
@@ -802,18 +952,15 @@ function updateConvItems(mode,data) {
function scrollToItem() {
// auto-scroll to a particular comment in a thread (designated by mid) when in single-thread mode
- // use the same method to generate the submid as we use in ThreadItem,
- // base64_encode + replace(['+','='],['','']);
if(justifiedGalleryActive)
return;
var submid = ((bParam_mid.length) ? bParam_mid : 'abcdefg');
var encoded = ((submid.substr(0,4) == 'b64.') ? true : false);
- var submid_encoded = ((encoded) ? submid.substr(4) : window.btoa(submid));
+ var submid_encoded = ((encoded) ? submid : window.btoa(submid));
- submid_encoded = submid_encoded.replace(/[\+\=]/g,'');
- if($('.item_' + submid_encoded).length && !$('.item_' + submid_encoded).hasClass('toplevel_item')) {
+ if($('.thread-wrapper[data-b64mid=\'' + submid_encoded + '\']').length && !$('.thread-wrapper[data-b64mid=\'' + submid_encoded + '\']').hasClass('toplevel_item')) {
if($('.collapsed-comments').length) {
var scrolltoid = $('.collapsed-comments').attr('id').substring(19);
$('#collapsed-comments-' + scrolltoid + ' .autotime').timeago();
@@ -821,8 +968,8 @@ function scrollToItem() {
$('#hide-comments-' + scrolltoid).html(aStr.showfewer);
$('#hide-comments-total-' + scrolltoid).hide();
}
- $('html, body').animate({ scrollTop: $('.item_' + submid_encoded).offset().top - $('nav').outerHeight(true) }, 'slow');
- $('.item_' + submid_encoded).addClass('item-highlight');
+ $('html, body').animate({ scrollTop: $('.thread-wrapper[data-b64mid=\'' + submid_encoded + '\']').offset().top - $('nav').outerHeight(true) }, 'slow');
+ $('.thread-wrapper[data-b64mid=\'' + submid_encoded + '\']').addClass('item-highlight');
}
}
@@ -885,6 +1032,7 @@ function updateInit() {
// if($('#live-cards').length) { src = 'cards'; }
// if($('#live-articles').length) { src = 'articles'; }
+/*
if (initialLoad && (sessionStorage.getItem('notifications_cache') !== null)) {
var cached_data = JSON.parse(sessionStorage.getItem('notifications_cache'));
notificationsUpdate(cached_data);
@@ -898,9 +1046,10 @@ function updateInit() {
}
}
+*/
if(! src) {
- notificationsUpdate();
+ // notificationsUpdate();
}
else {
liveUpdate();
@@ -1039,7 +1188,7 @@ function liveUpdate(notify_id) {
})
.done(function() {
- notificationsUpdate();
+ // notificationsUpdate();
});
}
@@ -1088,7 +1237,9 @@ function justifyPhotosAjax(id) {
$('#' + id).justifiedGallery('norewind').on('jg.complete', function(e){ justifiedGalleryActive = false; });
}
+/*
function loadNotificationItems(notifyType) {
+
var pingExCmd = 'ping/' + notifyType + ((localUser != 0) ? '?f=&uid=' + localUser : '');
var clicked = $('[data-type=\'' + notifyType + '\']').data('clicked');
@@ -1119,6 +1270,7 @@ function loadNotificationItems(notifyType) {
}
});
}
+*/
// Since our ajax calls are asynchronous, we will give a few
// seconds for the first ajax call (setting like/dislike), then
@@ -1169,7 +1321,7 @@ function doscroll(parent, hidden) {
}
}
back.remove();
- var id = $('[data-mid="' + parent + '"]');
+ var id = $('[data-b64mid="' + parent + '"]');
$('html, body').animate({scrollTop:(id.offset().top) - 50}, 'slow');
$('<a href="javascript:doscrollback(' + pos + ');" id="back-to-reply" class="float-right" title="' + aStr['to_reply'] + '"><i class="fa fa-angle-double-down">&nbsp;&nbsp;&nbsp;</i></a>').insertBefore('#wall-item-info-' + id.attr('id').replace(/\D/g,''));
}
@@ -1653,3 +1805,306 @@ 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 {
+ $.get('/sse_bs',function(obj) {
+ console.log(obj);
+ sse_handleNotifications(obj, true, false);
+ });
+ }
+}
+
+function sse_bs_notifications(e, replace, followup) {
+
+ sse_bs_active = true;
+ 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() : '');
+
+ $.get('/sse_bs/' + sse_type + '/' + sse_offset + '?nquery=' + encodeURIComponent(cn_val), function(obj) {
+ console.log('sse: bootstraping ' + sse_type);
+ console.log(obj);
+ sse_handleNotifications(obj, replace, followup);
+ sse_bs_active = false;
+ sse_offset = obj[sse_type].offset;
+ if(sse_offset < 0)
+ $("#nav-" + sse_type + "-loading").hide();
+
+ });
+ }
+ else
+ $("#nav-" + sse_type + "-loading").hide();
+
+ }
+ else {
+ sessionStorage.removeItem('notification_open');
+ }
+}
+
+
+
+function sse_handleNotifications(obj, replace, followup) {
+
+ if(
+ (obj.network && obj.network.count) ||
+ (obj.home && obj.home.count) ||
+ (obj.intros && obj.intros.count) ||
+ (obj.register && obj.register.count) ||
+ (obj.mail && obj.mail.count) ||
+ (obj.all_events && obj.all_events.count) ||
+ (obj.notify && obj.notify.count) ||
+ (obj.files && obj.files.count) ||
+ (obj.pubs && obj.pubs.count) ||
+ (obj.forums && obj.forums.count)
+ ) {
+ $('.notifications-btn').css('opacity', 1);
+ $('#no_notifications').hide();
+ }
+ else {
+ $('.notifications-btn').css('opacity', 0.5);
+ $('#navbar-collapse-1').removeClass('show');
+ $('#no_notifications').show();
+ }
+
+ if(
+ (obj.home && obj.home.count) ||
+ (obj.intros && obj.intros.count) ||
+ (obj.register && obj.register.count) ||
+ (obj.mail && obj.mail.count) ||
+ (obj.notify && obj.notify.count) ||
+ (obj.files && obj.files.count)
+ ) {
+ $('.notifications-btn-icon').removeClass('fa-exclamation-circle');
+ $('.notifications-btn-icon').addClass('fa-exclamation-triangle');
+ }
+ if(
+ !(obj.home && obj.home.count) &&
+ !(obj.intros && obj.intros.count) &&
+ !(obj.register && obj.register.count) &&
+ !(obj.mail && obj.mail.count) &&
+ !(obj.notify && obj.notify.count) &&
+ !(obj.files && obj.files.count)
+ ) {
+ $('.notifications-btn-icon').removeClass('fa-exclamation-triangle');
+ $('.notifications-btn-icon').addClass('fa-exclamation-circle');
+ }
+ if(obj.all_events_today && obj.all_events_today.count) {
+ $('.all_events-update').removeClass('badge-secondary');
+ $('.all_events-update').addClass('badge-danger');
+ }
+ else {
+ $('.all_events-update').removeClass('badge-danger');
+ $('.all_events-update').addClass('badge-secondary');
+ }
+
+ // network
+ if(obj.network && obj.network.count) {
+ $('.network-button').fadeIn();
+ if(replace || followup)
+ $('.network-update').html(Number(obj.network.count));
+ else
+ $('.network-update').html(Number(obj.network.count) + Number($('.network-update').html()));
+ }
+ if(obj.network && obj.network.notifications.length)
+ sse_handleNotificationsItems('network', obj.network.notifications, replace, followup);
+
+ // home
+ if(obj.home && obj.home.count) {
+ $('.home-button').fadeIn();
+ if(replace || followup)
+ $('.home-update').html(Number(obj.home.count));
+ else
+ $('.home-update').html(Number(obj.home.count) + Number($('.home-update').html()));
+ }
+ if(obj.home && obj.home.notifications.length)
+ sse_handleNotificationsItems('home', obj.home.notifications, replace, followup);
+
+ // notify
+ if(obj.notify && obj.notify.count) {
+ $('.notify-button').fadeIn();
+ if(replace || followup)
+ $('.notify-update').html(Number(obj.notify.count));
+ else
+ $('.notify-update').html(Number(obj.notify.count) + Number($('.notify-update').html()));
+
+ }
+ if(obj.notify && obj.notify.notifications.length)
+ sse_handleNotificationsItems('notify', obj.notify.notifications, replace, false);
+
+ // intros
+ if(obj.intros && obj.intros.count) {
+ $('.intros-button').fadeIn();
+ if(replace || followup)
+ $('.intros-update').html(Number(obj.intros.count));
+ else
+ $('.intros-update').html(Number(obj.intros.count) + Number($('.intros-update').html()));
+ }
+ if(obj.intros && obj.intros.notifications.length)
+ sse_handleNotificationsItems('intros', obj.intros.notifications, replace, false);
+
+ // forums
+ if(obj.forums && obj.forums.count) {
+ $('.forums-button').fadeIn();
+ if(replace || followup)
+ $('.forums-update').html(Number(obj.forums.count));
+ else
+ $('.forums-update').html(Number(obj.forums.count) + Number($('.forums-update').html()));
+ }
+ if(obj.forums && obj.forums.notifications.length)
+ sse_handleNotificationsItems('forums', obj.forums.notifications, replace, false);
+
+ // pubs
+ if(obj.pubs && obj.pubs.count) {
+ $('.pubs-button').fadeIn();
+ if(replace || followup)
+ $('.pubs-update').html(Number(obj.pubs.count));
+ else
+ $('.pubs-update').html(Number(obj.pubs.count) + Number($('.pubs-update').html()));
+ }
+ if(obj.pubs && obj.pubs.notifications.length)
+ sse_handleNotificationsItems('pubs', obj.pubs.notifications, replace, followup);
+
+ // files
+ if(obj.files && obj.files.count) {
+ $('.files-button').fadeIn();
+ if(replace || followup)
+ $('.files-update').html(Number(obj.files.count));
+ else
+ $('.files-update').html(Number(obj.files.count) + Number($('.files-update').html()));
+ }
+ if(obj.files && obj.files.notifications.length)
+ sse_handleNotificationsItems('files', obj.files.notifications, replace, false);
+
+ // mail
+ if(obj.mail && obj.mail.count) {
+ $('.mail-button').fadeIn();
+ if(replace || followup)
+ $('.mail-update').html(Number(obj.mail.count));
+ else
+ $('.mail-update').html(Number(obj.mail.count) + Number($('.mail-update').html()));
+ }
+ if(obj.mail && obj.mail.notifications.length)
+ sse_handleNotificationsItems('mail', obj.mail.notifications, replace, false);
+
+ // all_events
+ if(obj.all_events && obj.all_events.count) {
+ $('.all_events-button').fadeIn();
+ if(replace || followup)
+ $('.all_events-update').html(Number(obj.all_events.count));
+ else
+ $('.all_events-update').html(Number(obj.all_events.count) + Number($('.all_events-update').html()));
+ }
+ if(obj.all_events && obj.all_events.notifications.length)
+ sse_handleNotificationsItems('all_events', obj.all_events.notifications, replace, false);
+
+ // register
+ if(obj.register && obj.register.count) {
+ $('.register-button').fadeIn();
+ if(replace || followup)
+ $('.register-update').html(Number(obj.register.count));
+ else
+ $('.register-update').html(Number(obj.register.count) + Number($('.register-update').html()));
+ }
+ if(obj.register && obj.register.notifications.length)
+ sse_handleNotificationsItems('register', obj.register.notifications, replace, false);
+
+ // 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 });
+ });
+ }
+
+}
+
+function sse_handleNotificationsItems(notifyType, data, replace, followup) {
+ console.log('replace: ' + replace);
+ console.log('followup: ' + followup);
+ var notifications_tpl = ((notifyType == 'forums') ? unescape($("#nav-notifications-forums-template[rel=template]").html()) : unescape($("#nav-notifications-template[rel=template]").html()));
+ 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() {
+ 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);
+ notify_menu.append(html);
+ });
+
+ if(!replace && !followup) {
+ console.log('sorting');
+ $("#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('d-none');
+
+ 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('d-none');
+ else
+ $(el).removeClass('d-none');
+ });
+ }
+ }
+}
+
diff --git a/view/js/sse_worker.js b/view/js/sse_worker.js
new file mode 100755
index 000000000..78e4aa51b
--- /dev/null
+++ b/view/js/sse_worker.js
@@ -0,0 +1,14 @@
+var evtSource = new EventSource('/sse');
+
+onconnect = function(e) {
+
+ var port = e.ports[0];
+
+ port.start();
+
+ evtSource.addEventListener('notifications', function(e) {
+ var obj = JSON.parse(e.data);
+ port.postMessage(obj);
+ }, false);
+
+}
diff --git a/view/php/theme_init.php b/view/php/theme_init.php
index d683a3b58..d47325b77 100644
--- a/view/php/theme_init.php
+++ b/view/php/theme_init.php
@@ -37,6 +37,7 @@ head_add_js('/library/colorbox/jquery.colorbox-min.js');
head_add_js('/library/jquery.AreYouSure/jquery.are-you-sure.js');
head_add_js('/library/tableofcontents/jquery.toc.js');
head_add_js('/vendor/desandro/imagesloaded/imagesloaded.pkgd.min.js');
+
/**
* Those who require this feature will know what to do with it.
* Those who don't, won't.
diff --git a/view/tpl/activity_filter_widget.tpl b/view/tpl/activity_filter_widget.tpl
index 7d10100ba..779786828 100644
--- a/view/tpl/activity_filter_widget.tpl
+++ b/view/tpl/activity_filter_widget.tpl
@@ -9,7 +9,7 @@
</h3>
{{$content}}
{{if $name}}
- <div class="notifications-textinput">
+ <div id="cid-filter-wrapper" class="notifications-textinput">
<form method="get" action="{{$name.url}}" role="search">
<div class="text-muted notifications-textinput-filter"><i class="fa fa-fw fa-filter"></i></div>
<input id="cid" type="hidden" value="" name="cid" />
diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl
index 186551e2d..f639683b8 100755
--- a/view/tpl/conv_item.tpl
+++ b/view/tpl/conv_item.tpl
@@ -4,9 +4,9 @@
</div>
<div id="collapsed-comments-{{$item.id}}" class="collapsed-comments" style="display: none;">
{{/if}}
- <div id="thread-wrapper-{{$item.id}}" class="thread-wrapper{{if $item.toplevel}} {{$item.toplevel}} generic-content-wrapper h-entry {{else}} u-comment h-cite {{/if}} item_{{$item.submid}}">
+ <div id="thread-wrapper-{{$item.id}}" class="thread-wrapper{{if $item.toplevel}} {{$item.toplevel}} generic-content-wrapper h-entry {{else}} u-comment h-cite{{/if}}" data-b64mid="{{$item.mid}}">
<a name="item_{{$item.id}}" ></a>
- <div class="wall-item-outside-wrapper{{if $item.is_comment}} comment{{/if}}{{if $item.previewing}} preview{{/if}}" data-mid="{{$item.mid}}" id="wall-item-outside-wrapper-{{$item.id}}" >
+ <div class="wall-item-outside-wrapper{{if $item.is_comment}} comment{{/if}}{{if $item.previewing}} preview{{/if}}" id="wall-item-outside-wrapper-{{$item.id}}" >
<div class="clearfix wall-item-content-wrapper{{if $item.is_comment}} comment{{/if}}" id="wall-item-content-wrapper-{{$item.id}}">
{{if $item.photo}}
<div class="wall-photo-item" id="wall-photo-item-{{$item.id}}">
diff --git a/view/tpl/conv_list.tpl b/view/tpl/conv_list.tpl
index 8c5b47bf3..b244311bb 100755
--- a/view/tpl/conv_list.tpl
+++ b/view/tpl/conv_list.tpl
@@ -4,7 +4,7 @@
</div>
<div id="collapsed-comments-{{$item.id}}" class="collapsed-comments" style="display: none;">
{{/if}}
- <div id="thread-wrapper-{{$item.id}}" class="thread-wrapper{{if $item.toplevel}} {{$item.toplevel}} generic-content-wrapper h-entry {{else}} u-comment h-cite {{/if}} item_{{$item.submid}}">
+ <div id="thread-wrapper-{{$item.id}}" class="thread-wrapper{{if $item.toplevel}} {{$item.toplevel}} generic-content-wrapper h-entry {{else}} u-comment h-cite {{/if}}" data-b64mid="{{$item.mid}}">
<a name="item_{{$item.id}}" ></a>
<div class="wall-item-outside-wrapper{{if $item.is_comment}} comment{{/if}}{{if $item.previewing}} preview{{/if}}" id="wall-item-outside-wrapper-{{$item.id}}" >
<div class="clearfix wall-item-content-wrapper{{if $item.is_comment}} comment{{/if}}" id="wall-item-content-wrapper-{{$item.id}}">
diff --git a/view/tpl/js_strings.tpl b/view/tpl/js_strings.tpl
index 0a9cf9519..440676dee 100755
--- a/view/tpl/js_strings.tpl
+++ b/view/tpl/js_strings.tpl
@@ -35,7 +35,7 @@
'name_ok2' : "{{$name_ok2}}",
'to_reply' : "{{$to_reply}}",
- 'plural_func' : "{{$plural_func}}",
+ 'plural_func' : "{{$plural_func}}",
't01' : "{{$t01}}",
't02' : "{{$t02}}",
diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl
index bc7f80906..057d5b491 100644
--- a/view/tpl/notifications_widget.tpl
+++ b/view/tpl/notifications_widget.tpl
@@ -85,7 +85,7 @@
$('#nav-{{$notification.type}}-menu [data-thread_top=false]').toggle();
$(this).toggleClass('active sticky-top');
});
- $(document).on('click ', '#cn-{{$notification.type}}-input-clear', function(e) {
+ $(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('d-none');
@@ -93,8 +93,8 @@
});
$(document).on('input', '#cn-{{$notification.type}}-input', function(e) {
var val = $('#cn-{{$notification.type}}-input').val().toString().toLowerCase();
-
if(val) {
+ val = val.indexOf('%') == 0 ? val.substring(1) : val;
$('#cn-{{$notification.type}}-only').addClass('active sticky-top');
$('#cn-{{$notification.type}}-input-clear').removeClass('d-none');
}
@@ -135,16 +135,17 @@
{{$no_notifications}}<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span>
</div>
<div id="nav-notifications-template" rel="template">
- <a class="list-group-item clearfix notification {6}" href="{0}" title="{3}" data-b64mid="{7}" data-notify_id="{8}" data-thread_top="{9}" data-contact_name="{2}" data-contact_addr="{3}">
- <img class="menu-img-3" data-src="{1}">
+ <a class="list-group-item clearfix notification {6}" href="{0}" title="{3}" data-b64mid="{7}" data-notify_id="{8}" data-thread_top="{9}" data-contact_name="{2}" data-contact_addr="{3}" data-when="{5}">
+ <img class="menu-img-3" src="{1}">
<span class="contactname">{2}</span>
- <span class="dropdown-sub-text">{4}<br>{5}</span>
+ <span class="dropdown-sub-text">{4}</span><br>
+ <span class="dropdown-sub-text notifications-autotime" title="{5}">{5}</span>
</a>
</div>
<div id="nav-notifications-forums-template" rel="template">
<a class="list-group-item clearfix notification notification-forum" href="{0}" title="{4} - {3}" data-b64mid="{7}" data-notify_id="{8}" data-thread_top="{9}" data-contact_name="{2}" data-contact_addr="{3}">
- <span class="float-right badge badge-{{$notification.severity}}">{10}</span>
- <img class="menu-img-1" data-src="{1}">
+ <span class="float-right badge badge-secondary">{10}</span>
+ <img class="menu-img-1" src="{1}">
<span class="">{2}</span>
<i class="fa fa-{11} text-muted"></i>
</a>
@@ -152,11 +153,14 @@
<div id="notifications" class="navbar-nav">
{{foreach $notifications as $notification}}
<div class="collapse {{$notification.type}}-button">
- <a class="list-group-item notification-link" href="#" title="{{$notification.title}}" data-target="#nav-{{$notification.type}}-sub" data-toggle="collapse" data-type="{{$notification.type}}">
+ <a id="notification-link-{{$notification.type}}" class="collapsed list-group-item notification-link" href="#" title="{{$notification.title}}" data-target="#nav-{{$notification.type}}-sub" data-toggle="collapse" data-sse_type="{{$notification.type}}">
<i class="fa fa-fw fa-{{$notification.icon}}"></i> {{$notification.label}}
<span class="float-right badge badge-{{$notification.severity}} {{$notification.type}}-update"></span>
+ <div id="notifications-spinner-{{$notification.type}}" class="float-right spinner-wrapper">
+ <div class="spinner s"></div>
+ </div>
</a>
- <div id="nav-{{$notification.type}}-sub" class="collapse notification-content" data-parent="#notifications" data-type="{{$notification.type}}">
+ <div id="nav-{{$notification.type}}-sub" class="collapse notification-content" data-parent="#notifications" data-sse_type="{{$notification.type}}">
{{if $notification.viewall}}
<a class="list-group-item text-dark" id="nav-{{$notification.type}}-see-all" href="{{$notification.viewall.url}}">
<i class="fa fa-fw fa-external-link"></i> {{$notification.viewall.label}}
@@ -176,14 +180,16 @@
{{if $notification.filter.name_label}}
<div class="list-group-item clearfix notifications-textinput" id="cn-{{$notification.type}}-only">
<div class="text-muted notifications-textinput-filter"><i class="fa fa-fw fa-filter"></i></div>
- <input id="cn-{{$notification.type}}-input" type="text" class="form-control form-control-sm" placeholder="{{$notification.filter.name_label}}">
+ <input id="cn-{{$notification.type}}-input" type="text" class="notification-filter form-control form-control-sm" placeholder="{{$notification.filter.name_label}}">
<div id="cn-{{$notification.type}}-input-clear" class="text-muted notifications-textinput-clear d-none"><i class="fa fa-times"></i></div>
</div>
{{/if}}
{{/if}}
- <div id="nav-{{$notification.type}}-menu" class="">
+ <div id="nav-{{$notification.type}}-menu"></div>
+ <div id="nav-{{$notification.type}}-loading" style="display: none;">
{{$loading}}<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span>
</div>
+
</div>
</div>
{{/foreach}}