From 78c9f752af8db5db290a57224fa1d0239a36a34d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 16 Nov 2017 11:11:06 +0100 Subject: [PATCH 01/17] provide ability to pin apps to navbar from /apps. this removes the ability to have per custom navbar pinned apps - this can be added later if desired --- Zotlabs/Lib/Apps.php | 41 ++++++++++++++++++++++---------- Zotlabs/Module/Appman.php | 6 ++++- Zotlabs/Widget/Appcategories.php | 1 + include/nav.php | 14 +++++++---- view/tpl/app.tpl | 9 +++---- 5 files changed, 49 insertions(+), 22 deletions(-) diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index f13fbe362..bd271e860 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -401,11 +401,15 @@ class Apps { '$undelete' => ((local_channel() && $installed && $mode == 'edit') ? t('Undelete') : ''), '$deleted' => $papp['deleted'], '$feature' => (($papp['embed']) ? false : true), + '$pin' => (($papp['embed']) ? false : true), '$featured' => ((strpos($papp['categories'], 'nav_featured_app') === false) ? false : true), + '$pinned' => ((strpos($papp['categories'], 'nav_pinned_app') === false) ? false : true), '$navapps' => (($mode == 'nav') ? true : false), '$order' => (($mode == 'nav-order') ? true : false), '$add' => t('Add to app-tray'), - '$remove' => t('Remove from app-tray') + '$remove' => t('Remove from app-tray'), + '$add_nav' => t('Add to navbar'), + '$remove_nav' => t('Remove from navbar') )); } @@ -498,25 +502,27 @@ class Apps { } } - static public function app_feature($uid,$app) { + static public function app_feature($uid,$app,$term) { $r = q("select id from app where app_id = '%s' and app_channel = %d limit 1", dbesc($app['guid']), intval($uid) ); - $x = q("select * from term where otype = %d and oid = %d and term = 'nav_featured_app' limit 1", + $x = q("select * from term where otype = %d and oid = %d and term = '%s' limit 1", intval(TERM_OBJ_APP), - intval($r[0]['id']) + intval($r[0]['id']), + dbesc($term) ); if($x) { - q("delete from term where otype = %d and oid = %d and term = 'nav_featured_app'", + q("delete from term where otype = %d and oid = %d and term = '%s'", intval(TERM_OBJ_APP), - intval($x[0]['oid']) + intval($x[0]['oid']), + dbesc($term) ); } else { - store_item_tag($uid,$r[0]['id'],TERM_OBJ_APP,TERM_CATEGORY,'nav_featured_app',escape_tags(z_root() . '/apps/?f=&cat=nav_featured_app')); + store_item_tag($uid, $r[0]['id'], TERM_OBJ_APP, TERM_CATEGORY, $term, escape_tags(z_root() . '/apps/?f=&cat=' . $term)); } } @@ -531,16 +537,27 @@ class Apps { } - static public function app_list($uid, $deleted = false, $cat = '') { + static public function app_list($uid, $deleted = false, $cats = []) { if($deleted) $sql_extra = ""; else $sql_extra = " and app_deleted = 0 "; - if($cat) { - $r = q("select oid from term where otype = %d and term = '%s'", - intval(TERM_OBJ_APP), - dbesc($cat) + if($cats) { + + $cat_sql_extra = " and ( "; + + foreach($cats as $cat) { + if(strpos($cat_sql_extra, 'term')) + $cat_sql_extra .= "or "; + + $cat_sql_extra .= "term = '" . dbesc($cat) . "' "; + } + + $cat_sql_extra .= ") "; + + $r = q("select oid from term where otype = %d $cat_sql_extra", + intval(TERM_OBJ_APP) ); if(! $r) return $r; diff --git a/Zotlabs/Module/Appman.php b/Zotlabs/Module/Appman.php index 5c0667357..64d4628ae 100644 --- a/Zotlabs/Module/Appman.php +++ b/Zotlabs/Module/Appman.php @@ -64,7 +64,11 @@ class Appman extends \Zotlabs\Web\Controller { } if($_POST['feature']) { - Zlib\Apps::app_feature(local_channel(),$papp); + Zlib\Apps::app_feature(local_channel(), $papp, $_POST['feature']); + } + + if($_POST['pin']) { + Zlib\Apps::app_feature(local_channel(), $papp, $_POST['pin']); } if($_SESSION['return_url']) diff --git a/Zotlabs/Widget/Appcategories.php b/Zotlabs/Widget/Appcategories.php index 490ec1abc..8ff14230f 100644 --- a/Zotlabs/Widget/Appcategories.php +++ b/Zotlabs/Widget/Appcategories.php @@ -26,6 +26,7 @@ class Appcategories { and term.uid = app_channel and term.otype = %d and term.term != 'nav_featured_app' + and term.term != 'nav_pinned_app' order by term.term asc", intval(local_channel()), intval(TERM_OBJ_APP) diff --git a/include/nav.php b/include/nav.php index 9df50c9fe..8d39d492a 100644 --- a/include/nav.php +++ b/include/nav.php @@ -253,7 +253,7 @@ EOT; } $syslist = array(); - $list = Zlib\Apps::app_list(local_channel(), false, 'nav_featured_app'); + $list = Zlib\Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']); if($list) { foreach($list as $li) { $syslist[] = Zlib\Apps::app_encode($li); @@ -274,16 +274,20 @@ EOT; $app['active'] = true; if($is_owner) { - $nav_apps[] = Zlib\Apps::app_render($app,'nav'); - if(strpos($app['categories'],'navbar_' . $template)) { + if(strpos($app['categories'],'nav_pinned_app')) { $navbar_apps[] = Zlib\Apps::app_render($app,'navbar'); } + else { + $nav_apps[] = Zlib\Apps::app_render($app,'nav'); + } } elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) { - $nav_apps[] = Zlib\Apps::app_render($app,'nav'); - if(strpos($app['categories'],'navbar_' . $template)) { + if(strpos($app['categories'],'nav_pinned_app')) { $navbar_apps[] = Zlib\Apps::app_render($app,'navbar'); } + else { + $nav_apps[] = Zlib\Apps::app_render($app,'nav'); + } } } diff --git a/view/tpl/app.tpl b/view/tpl/app.tpl index ac5c18deb..c8bbc4ce1 100644 --- a/view/tpl/app.tpl +++ b/view/tpl/app.tpl @@ -15,10 +15,11 @@
- {{if $install}}{{/if}} - {{if $edit}}{{/if}} - {{if $delete}}{{/if}} - {{if $feature}}{{/if}} + {{if $install}}{{/if}} + {{if $edit}}{{/if}} + {{if $delete}}{{/if}} + {{if $feature}}{{/if}} + {{if $pin}}{{/if}}
{{/if}} From cba602bf64dd4e9566e5c060c38480128735a60d Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 16 Nov 2017 13:10:08 +0100 Subject: [PATCH 02/17] compare strpos result against false --- include/nav.php | 4 ++-- view/tpl/app.tpl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/nav.php b/include/nav.php index 8d39d492a..2dcf68bc8 100644 --- a/include/nav.php +++ b/include/nav.php @@ -274,7 +274,7 @@ EOT; $app['active'] = true; if($is_owner) { - if(strpos($app['categories'],'nav_pinned_app')) { + if(strpos($app['categories'],'nav_pinned_app') !== false) { $navbar_apps[] = Zlib\Apps::app_render($app,'navbar'); } else { @@ -282,7 +282,7 @@ EOT; } } elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) { - if(strpos($app['categories'],'nav_pinned_app')) { + if(strpos($app['categories'],'nav_pinned_app') !== false) { $navbar_apps[] = Zlib\Apps::app_render($app,'navbar'); } else { diff --git a/view/tpl/app.tpl b/view/tpl/app.tpl index c8bbc4ce1..7d2e46c59 100644 --- a/view/tpl/app.tpl +++ b/view/tpl/app.tpl @@ -12,7 +12,7 @@ {{/if}} {{if $install || $update || $delete || $feature}} -
+
{{if $install}}{{/if}} From 3f2b7d756c2bcffef675770d28d5b65b380fc8f5 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Thu, 16 Nov 2017 21:42:39 +0100 Subject: [PATCH 03/17] add > pin and remove > unpin --- Zotlabs/Lib/Apps.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php index bd271e860..bbf777b18 100644 --- a/Zotlabs/Lib/Apps.php +++ b/Zotlabs/Lib/Apps.php @@ -408,8 +408,8 @@ class Apps { '$order' => (($mode == 'nav-order') ? true : false), '$add' => t('Add to app-tray'), '$remove' => t('Remove from app-tray'), - '$add_nav' => t('Add to navbar'), - '$remove_nav' => t('Remove from navbar') + '$add_nav' => t('Pin to navbar'), + '$remove_nav' => t('Unpin from navbar') )); } From 601ebee9692c3bb552100f08f789824c68bdd5e0 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 17 Nov 2017 10:40:34 +0100 Subject: [PATCH 04/17] strip author name from notify messages in notifications - fix issue #911 --- Zotlabs/Module/Ping.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php index 3c6dda1e9..b18ff84b8 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -262,6 +262,13 @@ class Ping extends \Zotlabs\Web\Controller { if($t) { foreach($t as $tt) { + + $message = trim(strip_tags(bbcode($tt['msg']))); + $count = 1; + + if(strpos($message, $tt['xname']) === 0) + $message = str_replace($tt['xname'], '', $message, $count); + $notifs[] = array( 'notify_link' => z_root() . '/notify/view/' . $tt['id'], 'name' => $tt['xname'], @@ -269,7 +276,7 @@ class Ping extends \Zotlabs\Web\Controller { 'photo' => $tt['photo'], 'when' => relative_date($tt['created']), 'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'), - 'message' => strip_tags(bbcode($tt['msg'])) + 'message' => $message ); } } From 76af8fa754467e13bcd8c83620ac1c174e777170 Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 17 Nov 2017 13:54:53 +0100 Subject: [PATCH 05/17] inroduce the HQ module - a module with the potential to become a nice landing page for hubzilla. It is nothing more than a downgraded mod display atm. --- Zotlabs/Module/Hq.php | 300 ++++++++++++++++++++++++++++++ Zotlabs/Module/Ping.php | 1 - view/css/mod_hq.css | 3 + view/pdl/mod_hq.pdl | 3 + view/tpl/notifications_widget.tpl | 2 +- 5 files changed, 307 insertions(+), 2 deletions(-) create mode 100644 Zotlabs/Module/Hq.php create mode 100644 view/css/mod_hq.css create mode 100644 view/pdl/mod_hq.pdl diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php new file mode 100644 index 000000000..1438d2764 --- /dev/null +++ b/Zotlabs/Module/Hq.php @@ -0,0 +1,300 @@ + 1 && argv(1) !== 'load') { + $item_hash = argv(1); + } + + if($_REQUEST['mid']) + $item_hash = $_REQUEST['mid']; + + require_once('include/channel.php'); + $sys = get_sys_channel(); + $sysid = $sys['channel_id']; + + if(! $item_hash) { + + $r = q("SELECT mid FROM item + WHERE uid = %d + AND mid = parent_mid + $item_normal + ORDER BY id DESC + limit 1", + local_channel() ? intval(local_channel()) : intval($sysid) + ); + $item_hash = 'b64.' . base64url_encode($r[0]['mid']); + + if(!$item_hash) { + \App::$error = 404; + notice( t('Item not found.') . EOL); + return; + } + } + + $observer_is_owner = false; + $updateable = false; + + if(local_channel() && (! $update)) { + + $channel = \App::get_channel(); + + $channel_acl = [ + 'allow_cid' => $channel['channel_allow_cid'], + 'allow_gid' => $channel['channel_allow_gid'], + 'deny_cid' => $channel['channel_deny_cid'], + 'deny_gid' => $channel['channel_deny_gid'] + ]; + + $x = [ + 'is_owner' => true, + 'allow_location' => ((intval(get_pconfig($channel['channel_id'],'system','use_browser_location'))) ? '1' : ''), + 'default_location' => $channel['channel_location'], + 'nickname' => $channel['channel_address'], + 'lockstate' => (($group || $cid || $channel['channel_allow_cid'] || $channel['channel_allow_gid'] || $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'), + + 'acl' => populate_acl($channel_acl), + 'permissions' => $channel_acl, + 'bang' => '', + 'visitor' => true, + 'profile_uid' => local_channel(), + 'return_path' => 'channel/' . $channel['channel_address'], + 'expanded' => true, + 'editor_autocomplete' => true, + 'bbco_autocomplete' => 'bbcode', + 'bbcode' => true, + 'jotnets' => true + ]; + + $o = '
'; + $o .= status_editor($a,$x); + $o .= '
'; + } + + $target_item = null; + + if(strpos($item_hash,'b64.') === 0) + $decoded = @base64url_decode(substr($item_hash,4)); + if($decoded) + $item_hash = $decoded; + + $r = q("select id, uid, mid, parent_mid, thr_parent, verb, item_type, item_deleted, item_blocked from item where mid like '%s' limit 1", + dbesc($item_hash . '%') + ); + + if($r) { + $target_item = $r[0]; + } + + //if the item is to be moderated redirect to /moderate + if($target_item['item_blocked'] == ITEM_MODERATED) { + goaway(z_root() . '/moderate/' . $target_item['id']); + } + + $r = null; + + if($target_item['item_type'] == ITEM_TYPE_WEBPAGE) { + $x = q("select * from channel where channel_id = %d limit 1", + intval($target_item['uid']) + ); + $y = q("select * from iconfig left join item on iconfig.iid = item.id + where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item.id = %d limit 1", + intval($target_item['uid']), + intval($target_item['id']) + ); + if($x && $y) { + goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['v']); + } + else { + notice( t('Page not found.') . EOL); + return ''; + } + } + + $static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0); + + + $simple_update = (($update) ? " AND item_unseen = 1 " : ''); + + if($update && $_SESSION['loadtime']) + $simple_update = " AND (( item_unseen = 1 AND item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) OR item.changed > '" . datetime_convert('UTC','UTC',$_SESSION['loadtime']) . "' ) "; + if($load) + $simple_update = ''; + + if($static && $simple_update) + $simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' "; + + if((! $update) && (! $load)) { + + $static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1); + + // if the target item is not a post (eg a like) we want to address its thread parent + + $mid = ((($target_item['verb'] == ACTIVITY_LIKE) || ($target_item['verb'] == ACTIVITY_DISLIKE)) ? $target_item['thr_parent'] : $target_item['mid']); + + // if we got a decoded hash we must encode it again before handing to javascript + if($decoded) + $mid = 'b64.' . base64url_encode($mid); + + $o .= '
' . "\r\n"; + $o .= "\r\n"; + + \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[ + '$baseurl' => z_root(), + '$pgtype' => 'display', + '$uid' => '0', + '$gid' => '0', + '$cid' => '0', + '$cmin' => '0', + '$cmax' => '99', + '$star' => '0', + '$liked' => '0', + '$conv' => '0', + '$spam' => '0', + '$fh' => '0', + '$nouveau' => '0', + '$wall' => '0', + '$static' => $static, + '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), + '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), + '$search' => '', + '$xchan' => '', + '$order' => '', + '$file' => '', + '$cats' => '', + '$tags' => '', + '$dend' => '', + '$dbegin' => '', + '$verb' => '', + '$net' => '', + '$mid' => $mid + ]); + + head_add_link([ + 'rel' => 'alternate', + 'type' => 'application/json+oembed', + 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), + 'title' => 'oembed' + ]); + + } + + $item_normal = item_normal(); + $item_normal_update = item_normal_update(); + + $sql_extra = ''; //public_permissions_sql($observer_hash); + + if(($update && $load) || ($checkjs->disabled())) { + + $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start'])); + + if($load || ($checkjs->disabled())) { + $r = null; + + $r = q("SELECT item.id as item_id from item + WHERE uid = %d + and mid = '%s' + $item_normal + limit 1", + intval(local_channel()), + dbesc($target_item['parent_mid']) + ); + if($r) { + $updateable = true; + } + } + } + + elseif($update && !$load) { + $r = null; + + require_once('include/channel.php'); + $sys = get_sys_channel(); + $sysid = $sys['channel_id']; + + $r = q("SELECT item.parent AS item_id from item + WHERE uid = %d + and parent_mid = '%s' + $item_normal_update + $simple_update + limit 1", + intval(local_channel()), + dbesc($target_item['parent_mid']) + ); + if($r) { + $updateable = true; + } + + $_SESSION['loadtime'] = datetime_convert(); + } + + else { + $r = []; + } + + if($r) { + $parents_str = ids_to_querystr($r,'item_id'); + if($parents_str) { + $items = q("SELECT item.*, item.id AS item_id + FROM item + WHERE parent in ( %s ) $item_normal ", + dbesc($parents_str) + ); + + xchan_query($items); + $items = fetch_post_tags($items,true); + $items = conv_sort($items,'created'); + } + } + else { + $items = []; + } + + + if ($checkjs->disabled()) { + $o .= conversation($items, 'display', $update, 'traditional'); + if ($items[0]['title']) + \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title']; + } + else { + $o .= conversation($items, 'display', $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/Ping.php b/Zotlabs/Module/Ping.php index b18ff84b8..39f123d21 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -262,7 +262,6 @@ class Ping extends \Zotlabs\Web\Controller { if($t) { foreach($t as $tt) { - $message = trim(strip_tags(bbcode($tt['msg']))); $count = 1; diff --git a/view/css/mod_hq.css b/view/css/mod_hq.css new file mode 100644 index 000000000..dde242d4e --- /dev/null +++ b/view/css/mod_hq.css @@ -0,0 +1,3 @@ +#jot-popup { + display: none; +} diff --git a/view/pdl/mod_hq.pdl b/view/pdl/mod_hq.pdl new file mode 100644 index 000000000..e657fa88b --- /dev/null +++ b/view/pdl/mod_hq.pdl @@ -0,0 +1,3 @@ +[region=right_aside] +[widget=notifications][/widget] +[/region] diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl index 3ef7bff7d..ce64671d2 100644 --- a/view/tpl/notifications_widget.tpl +++ b/view/tpl/notifications_widget.tpl @@ -15,7 +15,7 @@ }); }); - {{if $module == 'display'}} + {{if $module == 'display' || $module == 'hq'}} $(document).on('click', '.notification', function(e) { var b64mid = $(this).data('b64mid'); var path = $(this)[0].pathname.substr(1,7); From 8e6ebd4f7b84157dec9f4bacc997be71c990a43c Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 17 Nov 2017 14:12:10 +0100 Subject: [PATCH 06/17] remove obsolete variable --- Zotlabs/Module/Hq.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index 1438d2764..65cd84b82 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -55,7 +55,6 @@ class Hq extends \Zotlabs\Web\Controller { } } - $observer_is_owner = false; $updateable = false; if(local_channel() && (! $update)) { From ee2ba212469711755558dc0a83b1acca47b6bb05 Mon Sep 17 00:00:00 2001 From: Andrew Manning Date: Fri, 17 Nov 2017 10:27:17 -0500 Subject: [PATCH 07/17] Add French to help pages language dropdown selector --- view/tpl/help.tpl | 1 + 1 file changed, 1 insertion(+) diff --git a/view/tpl/help.tpl b/view/tpl/help.tpl index d36494123..c523c4115 100644 --- a/view/tpl/help.tpl +++ b/view/tpl/help.tpl @@ -9,6 +9,7 @@ de en es + fr
From 8a4ee0506cf8acd61c716976fb6760504ce2e8bc Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Fri, 17 Nov 2017 21:25:18 +0100 Subject: [PATCH 08/17] use substr() instead of str_replace() --- Zotlabs/Module/Ping.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php index 39f123d21..d05acba6c 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -263,10 +263,9 @@ class Ping extends \Zotlabs\Web\Controller { if($t) { foreach($t as $tt) { $message = trim(strip_tags(bbcode($tt['msg']))); - $count = 1; if(strpos($message, $tt['xname']) === 0) - $message = str_replace($tt['xname'], '', $message, $count); + $message = substr($message, strlen($tt['xname']) + 1); $notifs[] = array( 'notify_link' => z_root() . '/notify/view/' . $tt['id'], From fbc57fa8e36e468abe81e4f3d72b3115cbdd794c Mon Sep 17 00:00:00 2001 From: Mario Vavti Date: Sat, 18 Nov 2017 22:16:06 +0100 Subject: [PATCH 09/17] some more work on mod hq --- Zotlabs/Module/Hq.php | 117 ++++++++---------------- Zotlabs/Module/Notify.php | 2 +- Zotlabs/Module/Ping.php | 2 + view/js/main.js | 4 +- view/js/mod_hq.js | 145 ++++++++++++++++++++++++++++++ view/tpl/notifications_widget.tpl | 16 +++- 6 files changed, 203 insertions(+), 83 deletions(-) create mode 100644 view/js/mod_hq.js diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index 65cd84b82..a3b2e7a6d 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -10,21 +10,28 @@ require_once('include/items.php'); class Hq extends \Zotlabs\Web\Controller { + function post() { + + if(!local_channel()) + return; + + if($_REQUEST['notify_id']) { + q("update notify set seen = 1 where id = %d and uid = %d", + intval($_REQUEST['notify_id']), + intval(local_channel()) + ); + } + + } + function get($update = 0, $load = false) { if(!local_channel()) return; - $checkjs = new \Zotlabs\Web\CheckJS(1); - if($load) $_SESSION['loadtime'] = datetime_convert(); - if(observer_prohibited()) { - notice( t('Public access denied.') . EOL); - return; - } - if(argc() > 1 && argv(1) !== 'load') { $item_hash = argv(1); } @@ -32,10 +39,6 @@ class Hq extends \Zotlabs\Web\Controller { if($_REQUEST['mid']) $item_hash = $_REQUEST['mid']; - require_once('include/channel.php'); - $sys = get_sys_channel(); - $sysid = $sys['channel_id']; - if(! $item_hash) { $r = q("SELECT mid FROM item @@ -44,7 +47,7 @@ class Hq extends \Zotlabs\Web\Controller { $item_normal ORDER BY id DESC limit 1", - local_channel() ? intval(local_channel()) : intval($sysid) + local_channel() ); $item_hash = 'b64.' . base64url_encode($r[0]['mid']); @@ -57,7 +60,7 @@ class Hq extends \Zotlabs\Web\Controller { $updateable = false; - if(local_channel() && (! $update)) { + if(! $update) { $channel = \App::get_channel(); @@ -113,29 +116,8 @@ class Hq extends \Zotlabs\Web\Controller { goaway(z_root() . '/moderate/' . $target_item['id']); } - $r = null; - - if($target_item['item_type'] == ITEM_TYPE_WEBPAGE) { - $x = q("select * from channel where channel_id = %d limit 1", - intval($target_item['uid']) - ); - $y = q("select * from iconfig left join item on iconfig.iid = item.id - where item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item.id = %d limit 1", - intval($target_item['uid']), - intval($target_item['id']) - ); - if($x && $y) { - goaway(z_root() . '/page/' . $x[0]['channel_address'] . '/' . $y[0]['v']); - } - else { - notice( t('Page not found.') . EOL); - return ''; - } - } - $static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0); - - + $simple_update = (($update) ? " AND item_unseen = 1 " : ''); if($update && $_SESSION['loadtime']) @@ -146,7 +128,7 @@ class Hq extends \Zotlabs\Web\Controller { if($static && $simple_update) $simple_update .= " and item_thread_top = 0 and author_xchan = '" . protect_sprintf(get_observer_hash()) . "' "; - if((! $update) && (! $load)) { + if(! $update && ! $load) { $static = ((local_channel()) ? channel_manual_conv_update(local_channel()) : 1); @@ -159,7 +141,7 @@ class Hq extends \Zotlabs\Web\Controller { $mid = 'b64.' . base64url_encode($mid); $o .= '
' . "\r\n"; - $o .= "\r\n"; \App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),[ @@ -178,7 +160,7 @@ class Hq extends \Zotlabs\Web\Controller { '$nouveau' => '0', '$wall' => '0', '$static' => $static, - '$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1), + '$page' => 1, '$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0), '$search' => '', '$xchan' => '', @@ -193,47 +175,30 @@ class Hq extends \Zotlabs\Web\Controller { '$mid' => $mid ]); - head_add_link([ - 'rel' => 'alternate', - 'type' => 'application/json+oembed', - 'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string), - 'title' => 'oembed' - ]); - } $item_normal = item_normal(); $item_normal_update = item_normal_update(); - $sql_extra = ''; //public_permissions_sql($observer_hash); + if($load) { + $r = null; - if(($update && $load) || ($checkjs->disabled())) { - - $pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start'])); - - if($load || ($checkjs->disabled())) { - $r = null; - - $r = q("SELECT item.id as item_id from item - WHERE uid = %d - and mid = '%s' - $item_normal - limit 1", - intval(local_channel()), - dbesc($target_item['parent_mid']) - ); - if($r) { - $updateable = true; - } + $r = q("SELECT item.id as item_id from item + WHERE uid = %d + and mid = '%s' + $item_normal + limit 1", + intval(local_channel()), + dbesc($target_item['parent_mid']) + ); + if($r) { + $updateable = true; } + } - elseif($update && !$load) { + elseif($update) { $r = null; - - require_once('include/channel.php'); - $sys = get_sys_channel(); - $sysid = $sys['channel_id']; $r = q("SELECT item.parent AS item_id from item WHERE uid = %d @@ -273,15 +238,7 @@ class Hq extends \Zotlabs\Web\Controller { $items = []; } - - if ($checkjs->disabled()) { - $o .= conversation($items, 'display', $update, 'traditional'); - if ($items[0]['title']) - \App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title']; - } - else { - $o .= conversation($items, 'display', $update, 'client'); - } + $o .= conversation($items, 'display', $update, 'client'); if($updateable) { $x = q("UPDATE item SET item_unseen = 0 where item_unseen = 1 AND uid = %d and parent = %d ", @@ -292,6 +249,10 @@ class Hq extends \Zotlabs\Web\Controller { $o .= '
'; + if(($update && $load) && (! $items)) { + notice( t('Something went wrong.') . EOL ); + } + return $o; } diff --git a/Zotlabs/Module/Notify.php b/Zotlabs/Module/Notify.php index 3d6e1c2e7..cffcc8099 100644 --- a/Zotlabs/Module/Notify.php +++ b/Zotlabs/Module/Notify.php @@ -34,7 +34,7 @@ class Notify extends \Zotlabs\Web\Controller { } - function get() { + function get() { if(! local_channel()) return login(); diff --git a/Zotlabs/Module/Ping.php b/Zotlabs/Module/Ping.php index d05acba6c..a6df1d3a6 100644 --- a/Zotlabs/Module/Ping.php +++ b/Zotlabs/Module/Ping.php @@ -274,6 +274,8 @@ class Ping extends \Zotlabs\Web\Controller { 'photo' => $tt['photo'], 'when' => relative_date($tt['created']), 'hclass' => (($tt['seen']) ? 'notify-seen' : 'notify-unseen'), + 'b64mid' => 'b64.' . base64url_encode(basename($tt['link'])), + 'notify_id' => $tt['id'], 'message' => $message ); } diff --git a/view/js/main.js b/view/js/main.js index e231dac60..026036300 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -959,9 +959,9 @@ function notify_popup_loader(notifyType) { $("." + notifyType + "-update").html(data.notify.length); $(data.notify).each(function() { - html = navbar_notifications_tpl.format(this.notify_link,this.photo,this.name,this.message,this.when,this.hclass,this.b64mid); + html = navbar_notifications_tpl.format(this.notify_link,this.photo,this.name,this.message,this.when,this.hclass,this.b64mid,this.notify_id); $("#navbar-" + notifyType + "-menu").append(html); - html = notifications_tpl.format(this.notify_link,this.photo,this.name,this.message,this.when,this.hclass,this.b64mid); + html = notifications_tpl.format(this.notify_link,this.photo,this.name,this.message,this.when,this.hclass,this.b64mid,this.notify_id); $("#nav-" + notifyType + "-menu").append(html); }); diff --git a/view/js/mod_hq.js b/view/js/mod_hq.js new file mode 100644 index 000000000..cf7ec941c --- /dev/null +++ b/view/js/mod_hq.js @@ -0,0 +1,145 @@ +function hqLiveUpdate(notify_id, b64mid) { + + if(typeof profile_uid === 'undefined') profile_uid = false; /* Should probably be unified with channelId defined in head.tpl */ + if((src === null) || (stopped) || (! profile_uid)) { $('.like-rotator').hide(); return; } + if(($('.comment-edit-text.expanded').length) || (in_progress)) { + if(livetime) { + clearTimeout(livetime); + } + livetime = setTimeout(liveUpdate, 10000); + return; + } + if(livetime !== null) + livetime = null; + + prev = 'live-' + src; + + in_progress = true; + + var update_url; + var update_mode; + + if(scroll_next) { + bParam_page = next_page; + page_load = true; + } + else { + bParam_page = 1; + } + + update_url = buildCmd(); + + if(page_load) { + $("#page-spinner").show(); + if(bParam_page == 1) + update_mode = 'replace'; + else + update_mode = 'append'; + } + else { + update_mode = 'update'; + var orgHeight = $("#region_2").height(); + } + + var dstart = new Date(); + console.log('LOADING data...'); + $.get(update_url, function(data) { + + // on shared hosts occasionally the live update process will be killed + // leaving an incomplete HTML structure, which leads to conversations getting + // truncated and the page messed up if all the divs aren't closed. We will try + // again and give up if we can't get a valid HTML response after 10 tries. + + if((data.indexOf("") != (-1)) && (data.indexOf("") == (-1))) { + console.log('Incomplete data. Reloading'); + in_progress = false; + liveRecurse ++; + if(liveRecurse < 10) { + liveUpdate(); + } + else { + console.log('Incomplete data. Too many attempts. Giving up.'); + } + } + + // else data was valid - reset the recursion counter + liveRecurse = 0; + + if(notify_id !== 'undefined') { + $.post( + "hq", + { + "notify_id" : notify_id + }, + function(data) { + if(timer) clearTimeout(timer); + timer = setTimeout(NavUpdate,10); + } + ); + } + + var dready = new Date(); + console.log('DATA ready in: ' + (dready - dstart)/1000 + ' seconds.'); + + if(update_mode === 'update' || preloadImages) { + console.log('LOADING images...'); + + $('.wall-item-body, .wall-photo-item',data).imagesLoaded( function() { + var iready = new Date(); + console.log('IMAGES ready in: ' + (iready - dready)/1000 + ' seconds.'); + + page_load = false; + scroll_next = false; + updateConvItems(update_mode,data); + $("#page-spinner").hide(); + $("#profile-jot-text-loading").hide(); + + // adjust scroll position if new content was added above viewport + if(update_mode === 'update') { + $(window).scrollTop($(window).scrollTop() + $("#region_2").height() - orgHeight + contentHeightDiff); + } + + in_progress = false; + + // FIXME - the following lines were added so that almost + // immediately after we update the posts on the page, we + // re-check and update the notification counts. + // As it turns out this causes a bit of an inefficiency + // as we're pinging twice for every update, once before + // and once after. A btter way to do this is to rewrite + // NavUpdate and perhaps LiveUpdate so that we check for + // post updates first and only call the notification ping + // once. + + updateCountsOnly = true; + if(timer) clearTimeout(timer); + timer = setTimeout(NavUpdate,10); + + }); + } + else { + page_load = false; + scroll_next = false; + updateConvItems(update_mode,data); + $("#page-spinner").hide(); + $("#profile-jot-text-loading").hide(); + + in_progress = false; + + // FIXME - the following lines were added so that almost + // immediately after we update the posts on the page, we + // re-check and update the notification counts. + // As it turns out this causes a bit of an inefficiency + // as we're pinging twice for every update, once before + // and once after. A btter way to do this is to rewrite + // NavUpdate and perhaps LiveUpdate so that we check for + // post updates first and only call the notification ping + // once. + + updateCountsOnly = true; + if(timer) clearTimeout(timer); + timer = setTimeout(NavUpdate,10); + + } + }); +} diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl index ce64671d2..136b14abd 100644 --- a/view/tpl/notifications_widget.tpl +++ b/view/tpl/notifications_widget.tpl @@ -18,18 +18,30 @@ {{if $module == 'display' || $module == '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); + {{if $module == 'hq'}} + if(b64mid !== 'undefined') { + {{else}} if(path === 'display' && b64mid) { + {{/if}} e.preventDefault(); e.stopPropagation(); $('.thread-wrapper').remove(); - $(this).fadeOut(); + + if(! page_load) + $(this).fadeOut(); + bParam_mid = b64mid; mode = 'replace'; page_load = true; + {{if $module == 'hq'}} + hqLiveUpdate(notify_id); + {{else}} liveUpdate(); + {{/if}} if($('#notifications_wrapper').hasClass('fs')) $('#notifications_wrapper').prependTo('#' + notifications_parent).removeClass('fs'); @@ -43,7 +55,7 @@