From 96de38a1f06193d674f8fe89cb1852e0e4abb4cf Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 22 Oct 2020 11:33:25 +0000 Subject: adapt notifications and mark item seen handling to play well with client side page caching --- Zotlabs/Module/Channel.php | 40 +++------------------- Zotlabs/Module/Display.php | 14 -------- Zotlabs/Module/Hq.php | 17 ---------- Zotlabs/Module/Network.php | 33 ------------------ Zotlabs/Module/Pubstream.php | 1 - Zotlabs/Module/Sse_bs.php | 39 ++++++++++++++++++--- boot.php | 2 +- view/js/main.js | 81 +++++++++++++++++++++++++++++--------------- 8 files changed, 93 insertions(+), 134 deletions(-) diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 9c8cddab3..307be048a 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -442,44 +442,12 @@ class Channel extends Controller { } - $update_unseen = ''; - - if($page_mode === 'list') { - - /** - * in "list mode", only mark the parent item and any like activities as "seen". - * We won't distinguish between comment likes and post likes. The important thing - * is that the number of unseen comments will be accurate. The SQL to separate the - * comment likes could also get somewhat hairy. - */ - - if($parents_str) { - $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; - $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; - } - } - else { - if($parents_str) { - $update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )"; - } - } - - if($is_owner && $update_unseen) { - $x = [ 'channel_id' => local_channel(), 'update' => 'unset' ]; - call_hooks('update_unseen',$x); - if($x['update'] === 'unset' || intval($x['update'])) { - $r = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 and item_wall = 1 AND uid = %d $update_unseen", - intval(local_channel()) - ); - } - } - // Add pinned content if(! x($_REQUEST,'mid') && ! $search) { - $pinned = new \Zotlabs\Widget\Pinned; - $r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]); - $o .= $r['html']; - } + $pinned = new \Zotlabs\Widget\Pinned; + $r = $pinned->widget(intval(App::$profile['profile_uid']), [ITEM_TYPE_POST]); + $o .= $r['html']; + } $mode = (($search) ? 'search' : 'channel'); diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index f45f37001..3d61d7018 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -47,7 +47,6 @@ class Display extends \Zotlabs\Web\Controller { } $observer_is_owner = false; - $updateable = false; if(local_channel() && (! $update)) { @@ -274,9 +273,6 @@ class Display extends \Zotlabs\Web\Controller { intval(local_channel()), dbesc($target_item['parent_mid']) ); - if($r) { - $updateable = true; - } } if(! $r) { @@ -318,9 +314,6 @@ class Display extends \Zotlabs\Web\Controller { intval(local_channel()), dbesc($target_item['parent_mid']) ); - if($r) { - $updateable = true; - } } if($r === null) { @@ -432,13 +425,6 @@ class Display extends \Zotlabs\Web\Controller { killme(); } - - if($updateable) { - $x = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 AND uid = %d and parent = %d ", - intval(local_channel()), - intval($r[0]['item_id']) - ); - } $o .= '
'; diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index 5b331f4c1..e2678c07f 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -199,8 +199,6 @@ class Hq extends \Zotlabs\Web\Controller { ]); } - $updateable = false; - if($load && $target_item) { $r = null; @@ -213,10 +211,6 @@ class Hq extends \Zotlabs\Web\Controller { dbesc($target_item['parent_mid']) ); - if($r) { - $updateable = true; - } - if(!$r) { $sys_item = true; @@ -243,10 +237,6 @@ class Hq extends \Zotlabs\Web\Controller { dbesc($target_item['parent_mid']) ); - if($r) { - $updateable = true; - } - if(!$r) { $sys_item = true; @@ -283,13 +273,6 @@ class Hq extends \Zotlabs\Web\Controller { $o .= conversation($items, 'hq', $update, 'client'); - if($updateable) { - $x = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d AND parent = %d ", - intval(local_channel()), - intval($r[0]['item_id']) - ); - } - $o .= '
'; return $o; diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index df60fb9a3..bbacbb21e 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -493,7 +493,6 @@ class Network extends \Zotlabs\Web\Controller { $page_mode = 'client'; $parents_str = ''; - $update_unseen = ''; $simple_update = (($update) ? " and item_unseen = 1 " : ''); @@ -532,9 +531,6 @@ class Network extends \Zotlabs\Web\Controller { ); $parents_str = ids_to_querystr($items,'item_id'); - if($parents_str) { - $update_unseen = " AND id IN ( " . dbesc($parents_str) . " )"; - } require_once('include/items.php'); @@ -598,35 +594,6 @@ class Network extends \Zotlabs\Web\Controller { $items = array(); } - if($page_mode === 'list') { - - /** - * in "list mode", only mark the parent item and any like activities as "seen". - * We won't distinguish between comment likes and post likes. The important thing - * is that the number of unseen comments will be accurate. The SQL to separate the - * comment likes could also get somewhat hairy. - */ - - if($parents_str) { - $update_unseen = " AND ( id IN ( " . dbesc($parents_str) . " )"; - $update_unseen .= " OR ( parent IN ( " . dbesc($parents_str) . " ) AND verb in ( '" . dbesc(ACTIVITY_LIKE) . "','" . dbesc(ACTIVITY_DISLIKE) . "' ))) "; - } - } - else { - if($parents_str) { - $update_unseen = " AND parent IN ( " . dbesc($parents_str) . " )"; - } - } - } - - if($update_unseen) { - $x = [ 'channel_id' => local_channel(), 'update' => 'unset' ]; - call_hooks('update_unseen',$x); - if($x['update'] === 'unset' || intval($x['update'])) { - $r = q("UPDATE item SET item_unseen = 0 WHERE item_unseen = 1 AND uid = %d $update_unseen ", - intval(local_channel()) - ); - } } $mode = (($nouveau) ? 'network-new' : 'network'); diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 76a3e0d9e..55c96b23d 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -264,7 +264,6 @@ class Pubstream extends \Zotlabs\Web\Controller { // Then fetch all the children of the parents that are on this page $parents_str = ''; - $update_unseen = ''; if($r) { diff --git a/Zotlabs/Module/Sse_bs.php b/Zotlabs/Module/Sse_bs.php index 0189c4695..e3439e7dd 100644 --- a/Zotlabs/Module/Sse_bs.php +++ b/Zotlabs/Module/Sse_bs.php @@ -36,12 +36,15 @@ class Sse_bs extends Controller { self::$vnotify = get_pconfig(self::$uid, 'system', 'vnotify', -1); self::$evdays = intval(get_pconfig(self::$uid, 'system', 'evdays')); - self::$limit = 30; + self::$limit = 50; self::$offset = 0; self::$xchans = ''; - if(!empty($_GET['nquery']) && $_GET['nquery'] !== '%') { - $nquery = $_GET['nquery']; + if($_REQUEST['sse_rmids']) + self::mark_read($_REQUEST['sse_rmids']); + + if(!empty($_REQUEST['nquery']) && $_REQUEST['nquery'] !== '%') { + $nquery = $_REQUEST['nquery']; $x = q("SELECT xchan_hash FROM xchan WHERE xchan_name LIKE '%s' OR xchan_addr LIKE '%s'", dbesc($nquery . '%'), @@ -108,6 +111,31 @@ class Sse_bs extends Controller { json_return_and_die($result); } + function mark_read($arr) { + + if(! self::$uid) + return; + + $mids = []; + $str = ''; + + foreach($arr as $a) { + $mids[] = '\'' . dbesc(@base64url_decode(substr($a,4))) . '\''; + } + + $str = implode($mids, ','); + + $x = [ 'channel_id' => self::$uid, 'update' => 'unset' ]; + call_hooks('update_unseen',$x); + + if($x['update'] === 'unset' || intval($x['update'])) { + q("UPDATE item SET item_unseen = 0 WHERE uid = %d AND mid in (". $str . ") AND item_unseen = 1", + intval(self::$uid) + ); + } + + } + function bs_network($notifications) { $result['network']['notifications'] = []; @@ -163,9 +191,10 @@ class Sse_bs extends Controller { $r = q("SELECT count(id) as total FROM item WHERE uid = %d and item_unseen = 1 AND item_wall = 0 AND item_private IN (0, 1) + AND obj_type NOT IN ('Document', 'Video', 'Audio', 'Image') + AND author_xchan != '%s' $item_normal - $sql_extra - AND author_xchan != '%s'", + $sql_extra", intval(self::$uid), dbesc(self::$ob_hash) ); diff --git a/boot.php b/boot.php index e77a5260c..9045fe9f4 100755 --- a/boot.php +++ b/boot.php @@ -50,7 +50,7 @@ require_once('include/attach.php'); require_once('include/bbcode.php'); define ( 'PLATFORM_NAME', 'hubzilla' ); -define ( 'STD_VERSION', '5.1.1' ); +define ( 'STD_VERSION', '5.1.2' ); define ( 'ZOT_REVISION', '6.0' ); define ( 'DB_UPDATE_VERSION', 1238 ); diff --git a/view/js/main.js b/view/js/main.js index 041ecdd43..ffb869425 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -30,6 +30,7 @@ var sse_bs_active = false; var sse_offset = 0; var sse_type; var sse_partial_result = false; +var sse_rmids = []; var page_cache = {}; @@ -176,8 +177,7 @@ $(document).ready(function() { $('.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); + sse_bs_notifications(sse_type, false, true); } }); @@ -545,7 +545,7 @@ function markRead(notifType) { function markItemRead(itemId) { $.get('ping?f=&markItemRead='+itemId); - $('.unseen-wall-indicator-'+itemId).hide(); + $('.unseen-wall-indicator-'+itemId).remove(); } function contextualHelp() { @@ -710,6 +710,9 @@ function updateConvItems(mode,data) { var nmids = $(this).data('b64mids'); nmids.forEach(function(nmid, index) { + + sse_rmids.push(nmid); + if($('.notification[data-b64mid=\'' + nmid + '\']').length) { $('.notification[data-b64mid=\'' + nmid + '\']').each(function() { var n = this.parentElement.id.split('-'); @@ -743,12 +746,6 @@ function updateConvItems(mode,data) { }); - // We are actually dealing with counts in sse_updateNotifications() - // for notifications which are already visible. For the case where - // unseen items were loaded but their notifications are not yet visible - // we need to bootstrap counts here to stay in sync with the DB after - // the first page load. - if(followUpPageLoad) sse_bs_counts(); else @@ -1766,14 +1763,31 @@ function sse_bs_init() { } function sse_bs_counts() { - $.get('/sse_bs',function(obj) { + + + 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) { - sse_bs_active = true; + + if(sse_bs_active) + return; + + var manual = false; if(typeof replace === 'undefined') @@ -1807,17 +1821,19 @@ function sse_bs_notifications(e, replace, followup) { $("#nav-" + sse_type + "-loading").show(); - $.get('/sse_bs/' + sse_type + '/' + sse_offset + '?nquery=' + encodeURIComponent(cn_val), function(obj) { + sse_bs_active = true; + + $.ajax({ + type: 'post', + url: '/sse_bs/' + sse_type + '/' + sse_offset, + nquery: encodeURIComponent(cn_val) + }).done(function(obj) { console.log('sse: bootstraping ' + sse_type); console.log(obj); - sse_bs_active = false; - sse_offset = obj[sse_type].offset; - $("#nav-" + sse_type + "-loading").hide(); - + sse_offset = obj[sse_type].offset; sse_handleNotifications(obj, replace, followup); - }); } else @@ -1838,14 +1854,21 @@ function sse_handleNotifications(obj, replace, followup) { var all_notifications = primary_notifications.concat(secondary_notifications); all_notifications.forEach(function(type, index) { - if(obj[type] && obj[type].count) { + 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())); } - if(obj[type] && obj[type].notifications.length) + else { + $('.' + type + '-update').html('0'); + $('.' + type + '-button').fadeOut(); + } + if(obj[type].notifications.length) sse_handleNotificationsItems(type, obj[type].notifications, replace, followup); }); @@ -1866,15 +1889,13 @@ function sse_handleNotifications(obj, replace, followup) { }); } - // load more notifications if visible notifications count becomes < 15 - if(sse_type) { - if($('#nav-' + sse_type + '-menu').children().length < 15) { - if(!sse_bs_active) { - sse_bs_notifications(sse_type, false, true); - } - } + // 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) { @@ -1890,6 +1911,11 @@ function sse_handleNotificationsItems(notifyType, data, replace, followup) { } $(data).each(function() { + + // do not add a notification if it is already present + if($('.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); }); @@ -1932,7 +1958,7 @@ function sse_updateNotifications(type, mid) { if(type === 'notify' && (mid !== bParam_mid || sse_type !== 'notify')) return true; - +/* var count = Number($('.' + type + '-update').html()); count--; @@ -1946,6 +1972,7 @@ function sse_updateNotifications(type, mid) { else { $('.' + type + '-update').html(count); } +*/ $('#nav-' + type + '-menu .notification[data-b64mid=\'' + mid + '\']').fadeOut(function() { this.remove(); -- cgit v1.2.3