diff options
-rw-r--r-- | Zotlabs/Lib/ThreadItem.php | 40 | ||||
-rw-r--r-- | Zotlabs/Module/Channel.php | 9 | ||||
-rw-r--r-- | Zotlabs/Module/Display.php | 2 | ||||
-rw-r--r-- | Zotlabs/Module/Hq.php | 2 | ||||
-rw-r--r-- | Zotlabs/Module/Like.php | 14 | ||||
-rw-r--r-- | Zotlabs/Module/Network.php | 6 | ||||
-rw-r--r-- | Zotlabs/Module/Pubstream.php | 6 | ||||
-rw-r--r-- | Zotlabs/Module/Request.php | 6 | ||||
-rw-r--r-- | include/conversation.php | 12 | ||||
-rw-r--r-- | include/items.php | 362 | ||||
-rw-r--r-- | view/js/main.js | 5 | ||||
-rw-r--r-- | view/tpl/conv_item.tpl | 5 |
12 files changed, 234 insertions, 235 deletions
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 5bb658bba..ee74ffa60 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -206,9 +206,9 @@ class ThreadItem { } if (in_array($item['obj_type'], ['Event', ACTIVITY_OBJ_EVENT])) { - $response_verbs[] = 'attendyes'; - $response_verbs[] = 'attendno'; - $response_verbs[] = 'attendmaybe'; + $response_verbs[] = 'accept'; + $response_verbs[] = 'reject'; + $response_verbs[] = 'tentativeaccept'; if($this->is_commentable() && $observer) { $isevent = true; $attend = array( t('I will attend'), t('I will not attend'), t('I might attend')); @@ -222,7 +222,6 @@ class ThreadItem { $response_verbs[] = 'comment'; $responses = get_responses($response_verbs, $item); - /* * We should avoid doing this all the time, but it depends on the conversation mode * And the conv mode may change when we change the conv, or it changes its mode @@ -231,7 +230,10 @@ class ThreadItem { $this->check_wall_to_wall(); + $toplevel_comments_total = 0; if($this->is_toplevel()) { + $toplevel_comments_total = $responses['comment']['count'] ?? 0; + if((local_channel() && $conv->get_profile_owner() === local_channel()) || (local_channel() && App::$module === 'pubstream')) { $star = [ 'toggle' => t("Toggle Star Status"), @@ -243,7 +245,6 @@ class ThreadItem { $is_comment = true; } - $verified = (intval($item['item_verified']) ? t('Message signature validated') : ''); $forged = ((($item['sig']) && (! intval($item['item_verified']))) ? t('Message signature incorrect') : ''); $unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : ''); @@ -350,6 +351,17 @@ class ThreadItem { $contact = App::$contacts[$item['author_xchan']]; } + $load_more = ''; + $load_more_title = ''; + if ($toplevel_comments_total > $total_children) { + if (is_site_admin()) { + // provide a load more comments button + $load_more = t('Load more'); + $load_more_title = sprintf(t('Load more of %d replies'), $toplevel_comments_total); + + } + } + $tmp_item = array( 'template' => $this->get_template(), 'mode' => $mode, @@ -463,18 +475,20 @@ class ThreadItem { 'reaction_str' => [t('Add yours'), t('Remove yours')], 'is_contained' => $this->is_toplevel() && str_contains($item['tgt_type'], 'Collection'), 'observer_activity' => [ - 'like' => intval($item['observer_liked'] ?? 0), - 'dislike' => intval($item['observer_disliked'] ?? 0), - 'announce' => intval($item['observer_announced'] ?? 0), - 'comment' => intval($item['observer_commented'] ?? 0), - 'attendyes' => intval($item['observer_accepted'] ?? 0), - 'attendno' => intval($item['observer_rejected'] ?? 0), - 'attendmaybe' => intval($item['observer_tentativelyaccepted'] ?? 0) + 'like' => intval($item['observer_like_count'] ?? 0), + 'dislike' => intval($item['observer_dislike_count'] ?? 0), + 'announce' => intval($item['observer_announce_count'] ?? 0), + 'comment' => intval($item['observer_comment_count'] ?? 0), + 'accept' => intval($item['observer_accept_count'] ?? 0), + 'reject' => intval($item['observer_reject_count'] ?? 0), + 'tentativeaccept' => intval($item['observer_tentativeaccept_count'] ?? 0) ], 'threaded' => $this->threaded, 'blog_mode' => $this->get_display_mode() === 'list', 'collapse_comments' => t('show less'), - 'expand_comments' => $this->threaded ? t('show more') : t('show all') + 'expand_comments' => $this->threaded ? t('show more') : t('show all'), + 'load_more' => $load_more, + 'load_more_title' => $load_more_title, ); $arr = array('item' => $item, 'output' => $tmp_item); diff --git a/Zotlabs/Module/Channel.php b/Zotlabs/Module/Channel.php index 93803da18..27c627e34 100644 --- a/Zotlabs/Module/Channel.php +++ b/Zotlabs/Module/Channel.php @@ -417,14 +417,7 @@ class Channel extends Controller { } } if ($r) { - //$parents_str = ids_to_querystr($r, 'item_id'); - - //$r = items_by_parent_ids($parents_str, permission_sql: $permission_sql, blog_mode: $blog_mode); - $items = []; - foreach($r as $parent) { - $nitems = items_by_parent_id($parent['item_id'], permission_sql: $permission_sql, blog_mode: $blog_mode); - $items = array_merge($items, $nitems); - } + $items = items_by_parent_ids($r, permission_sql: $permission_sql, blog_mode: $blog_mode); xchan_query($items); $items = fetch_post_tags($items, true); diff --git a/Zotlabs/Module/Display.php b/Zotlabs/Module/Display.php index d3657149f..094466665 100644 --- a/Zotlabs/Module/Display.php +++ b/Zotlabs/Module/Display.php @@ -289,7 +289,7 @@ class Display extends Controller { if($r) { $thr_parents = get_recursive_thr_parents($target_item); - $items = items_by_parent_id($r[0]['item_id'], $thr_parents, $permission_sql); + $items = items_by_parent_ids($r, $thr_parents, $permission_sql); xchan_query($items); $items = fetch_post_tags($items,true); diff --git a/Zotlabs/Module/Hq.php b/Zotlabs/Module/Hq.php index c4f812854..241a5101a 100644 --- a/Zotlabs/Module/Hq.php +++ b/Zotlabs/Module/Hq.php @@ -201,7 +201,7 @@ class Hq extends \Zotlabs\Web\Controller { if($r) { $thr_parents = get_recursive_thr_parents($target_item); - $items = items_by_parent_id($r[0]['item_id'], $thr_parents); + $items = items_by_parent_ids($r, $thr_parents); xchan_query($items,true,(($sys_item) ? local_channel() : 0)); $items = fetch_post_tags($items,true); diff --git a/Zotlabs/Module/Like.php b/Zotlabs/Module/Like.php index 218d35f1e..e704c397e 100644 --- a/Zotlabs/Module/Like.php +++ b/Zotlabs/Module/Like.php @@ -22,9 +22,9 @@ class Like extends Controller { 'like' => 'Like', 'dislike' => 'Dislike', 'announce' => ACTIVITY_SHARE, - 'attendyes' => 'Accept', - 'attendno' => 'Reject', - 'attendmaybe' => 'TentativeAccept' + 'accept' => 'Accept', + 'reject' => 'Reject', + 'tentativeaccept' => 'TentativeAccept' ]; // unlike (etc.) reactions are an undo of positive reactions, rather than a negative action. @@ -474,11 +474,11 @@ class Like extends Controller { $bodyverb = t('%1$s likes %2$s\'s %3$s'); if ($verb === 'dislike') $bodyverb = t('%1$s doesn\'t like %2$s\'s %3$s'); - if ($verb === 'attendyes') + if ($verb === 'accept') $bodyverb = t('%1$s is attending %2$s\'s %3$s'); - if ($verb === 'attendno') + if ($verb === 'reject') $bodyverb = t('%1$s is not attending %2$s\'s %3$s'); - if ($verb === 'attendmaybe') + if ($verb === 'tentativeaccept') $bodyverb = t('%1$s may attend %2$s\'s %3$s'); if (!isset($bodyverb)) @@ -561,7 +561,7 @@ class Like extends Controller { call_hooks('post_local_end', $arr); - if ($is_rsvp && in_array($verb, ['attendyes', 'attendmaybe'])) { + if ($is_rsvp && in_array($verb, ['accept', 'tentativeaccept'])) { event_addtocal($item_id, local_channel()); } diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 6dd00f13c..f95d92fe2 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -507,11 +507,7 @@ class Network extends \Zotlabs\Web\Controller { // Then fetch all the children of the parents that are on this page if($r) { - $items = []; - foreach($r as $parent) { - $nitems = items_by_parent_id($parent['item_id'], blog_mode: $blog_mode); - $items = array_merge($items, $nitems); - } + $items = items_by_parent_ids($r, blog_mode: $blog_mode); xchan_query($items, true); $items = fetch_post_tags($items, true); diff --git a/Zotlabs/Module/Pubstream.php b/Zotlabs/Module/Pubstream.php index 2944e496a..99b8ab587 100644 --- a/Zotlabs/Module/Pubstream.php +++ b/Zotlabs/Module/Pubstream.php @@ -251,11 +251,7 @@ class Pubstream extends \Zotlabs\Web\Controller { $parents_str = ''; if($r) { - $items = []; - foreach($r as $parent) { - $nitems = items_by_parent_id($parent['item_id']); - $items = array_merge($items, $nitems); - } + $items = items_by_parent_ids($r); // use effective_uid param of xchan_query to help sort out comment permission // for sys_channel owned items. diff --git a/Zotlabs/Module/Request.php b/Zotlabs/Module/Request.php index bfd75ad95..0174694b2 100644 --- a/Zotlabs/Module/Request.php +++ b/Zotlabs/Module/Request.php @@ -12,9 +12,9 @@ class Request extends Controller 'like' => 'Like', 'dislike' => 'Dislike', 'announce' => 'Announce', - 'attendyes' => 'Accept', - 'attendno' => 'Reject', - 'attendmaybe' => 'TentativeAccept' + 'accept' => 'Accept', + 'reject' => 'Reject', + 'tentativeaccept' => 'TentativeAccept' ]; if (array_key_exists($verb, $verbs)) { diff --git a/include/conversation.php b/include/conversation.php index 97a65c27d..bd1b7f863 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -1448,14 +1448,14 @@ function get_response_button_text($v, $count = 0) { case 'comment': return ['label' => tt('Reply','Replies',$count,'noun'), 'icon' => 'chat', 'class' => 'comment', 'action' => '']; break; - case 'attendyes': - return ['label' => tt('Attending','Attending',$count,'noun'), 'icon' => 'calendar-check', 'class' => 'attendyes', 'action' => 'dolike']; + case 'accept': + return ['label' => tt('Attending','Attending',$count,'noun'), 'icon' => 'calendar-check', 'class' => 'accept', 'action' => 'dolike']; break; - case 'attendno': - return ['label' => tt('Not attending','Not attending',$count,'noun'), 'icon' => 'calendar-x', 'class' => 'attendno', 'action' => 'dolike']; + case 'reject': + return ['label' => tt('Not attending','Not attending',$count,'noun'), 'icon' => 'calendar-x', 'class' => 'reject', 'action' => 'dolike']; break; - case 'attendmaybe': - return ['label' => tt('Undecided','Undecided',$count,'noun'), 'icon' => 'calendar', 'class' => 'attendmaybe', 'action' => 'dolike']; + case 'tentativeaccept': + return ['label' => tt('Undecided','Undecided',$count,'noun'), 'icon' => 'calendar', 'class' => 'tentativeaccept', 'action' => 'dolike']; break; default: return []; diff --git a/include/items.php b/include/items.php index 94e909293..a2c171a64 100644 --- a/include/items.php +++ b/include/items.php @@ -5374,16 +5374,16 @@ function item_activity_sql($prefix = 'c') { if ($observer) { $sql = <<<SQL - COUNT(CASE WHEN $prefix.verb = 'Like' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_liked, - COUNT(CASE WHEN $prefix.verb = 'Dislike' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_disliked, - COUNT(CASE WHEN $prefix.verb = 'Announce' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_announced, - COUNT(CASE WHEN $prefix.verb = 'Accept' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_accepted, - COUNT(CASE WHEN $prefix.verb = 'Reject' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_rejected, - COUNT(CASE WHEN $prefix.verb = 'TentativeAccept' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_tentativelyaccepted, + COUNT(CASE WHEN $prefix.verb = 'Like' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_like_count, + COUNT(CASE WHEN $prefix.verb = 'Dislike' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_dislike_count, + COUNT(CASE WHEN $prefix.verb = 'Announce' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_announce_count, + COUNT(CASE WHEN $prefix.verb = 'Accept' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_accept_count, + COUNT(CASE WHEN $prefix.verb = 'Reject' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_reject_count, + COUNT(CASE WHEN $prefix.verb = 'TentativeAccept' AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_tentativeaccept_count, SQL; if ($thread_allow) { - $sql .= " COUNT(CASE WHEN $prefix.verb IN ('Create','Update') AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_commented, "; + $sql .= " COUNT(CASE WHEN $prefix.verb IN ('Create','Update') AND $prefix.author_xchan = '$observer' THEN 1 END) AS observer_comment_count, "; } } @@ -5396,9 +5396,9 @@ function item_activity_sql($prefix = 'c') { COUNT(CASE WHEN $prefix.verb = 'Like' THEN 1 END) AS like_count, COUNT(CASE WHEN $prefix.verb = 'Dislike' THEN 1 END) AS dislike_count, COUNT(CASE WHEN $prefix.verb = 'Announce' THEN 1 END) AS announce_count, - COUNT(CASE WHEN $prefix.verb = 'Accept' THEN 1 END) AS attendyes_count, - COUNT(CASE WHEN $prefix.verb = 'Reject' THEN 1 END) AS attendno_count, - COUNT(CASE WHEN $prefix.verb = 'TentativeAccept' THEN 1 END) AS attendmaybe_count + COUNT(CASE WHEN $prefix.verb = 'Accept' THEN 1 END) AS accept_count, + COUNT(CASE WHEN $prefix.verb = 'Reject' THEN 1 END) AS reject_count, + COUNT(CASE WHEN $prefix.verb = 'TentativeAccept' THEN 1 END) AS tentativeaccept_count SQL; return $sql; @@ -5443,77 +5443,145 @@ function item_by_item_id(int $id): array * @brief returns an array of items by ids * ATTENTION: no permissions for the pa are checked here!!! * Permissions MUST be checked by the function which returns the ids. - * @param string $ids - a string with ids separated by comma - * @param array $thr_parents (optional) - a string with thr_parent mids separated by comma - * which will be included + * @param array $ids + * @param array $thr_parents (optional) - thr_parent mids which will be included * @param string $permission_sql (optional) - SQL provided by item_permission_sql() from the calling module * @param bool $blog_mode (optional) - if set to yes only the parent items will be returned */ -// TODO: improve SQL performance -function items_by_parent_ids(string $ids, array $thr_parents = [], string $permission_sql = '', bool $blog_mode = false): array +function items_by_parent_ids(array $parents, array $thr_parents = [], string $permission_sql = '', bool $blog_mode = false): array { - if (!$ids) { + if (!$parents) { return []; } + $ids = ids_to_querystr($parents, 'item_id'); $thread_allow = ((local_channel()) ? PConfig::Get(local_channel(), 'system', 'thread_allow', true) : Config::Get('system', 'thread_allow', true)); - $item_normal_sql = item_normal(); - $activity_sql_cte = item_activity_sql_cte(); - $activity_sql_cte_sub = item_activity_sql_cte('sub'); $thr_parent_sql = (($thread_allow) ? " AND item.thr_parent = item.parent_mid " : ''); - if ($thr_parents && $thread_allow) { $thr_parent_str = stringify_array($thr_parents, true); $thr_parent_sql = " AND item.thr_parent IN (" . protect_sprintf($thr_parent_str) . ") "; } + $reaction = item_reaction_sql($ids, $permission_sql); + $reaction_cte_sql = $reaction['cte']; + $reaction_select_sql = $reaction['select']; + if ($blog_mode) { - $ret = q("SELECT item.*, - $activity_sql_cte - FROM item - WHERE item.id IN (%s) - $item_normal_sql - $permission_sql", - dbesc($ids) + $ret = dbq("WITH + parent_items_base AS ( + SELECT item.* + FROM item + WHERE item.id IN ($ids) + $item_normal_sql + $permission_sql + ), + + $reaction_cte_sql, + + parent_items AS ( + SELECT + parent_items_base.*, + $reaction_select_sql + + FROM parent_items_base + LEFT JOIN reaction_like + ON reaction_like.thr_parent = parent_items_base.mid + LEFT JOIN reaction_dislike + ON reaction_dislike.thr_parent = parent_items_base.mid + LEFT JOIN reaction_announce + ON reaction_announce.thr_parent = parent_items_base.mid + LEFT JOIN reaction_accept + ON reaction_accept.thr_parent = parent_items_base.mid + LEFT JOIN reaction_reject + ON reaction_reject.thr_parent = parent_items_base.mid + LEFT JOIN reaction_tentativeaccept + ON reaction_tentativeaccept.thr_parent = parent_items_base.mid + LEFT JOIN reaction_comment + ON reaction_comment.thr_parent = parent_items_base.mid + ) + + SELECT * FROM parent_items" ); } else { - $ret = q("WITH parents AS ( - SELECT item.*, - 0 AS rn, -- this is required for union (equal amount of coulumns) - $activity_sql_cte - FROM item - WHERE item.id IN (%s) - $item_normal_sql - $permission_sql + $ret = dbq("WITH + parent_items_base AS ( + SELECT item.* + FROM item + WHERE item.id IN ($ids) + $item_normal_sql + $permission_sql + ), + + $reaction_cte_sql, + + parent_items AS ( + SELECT + parent_items_base.*, + 0 AS rn, + $reaction_select_sql + + FROM parent_items_base + LEFT JOIN reaction_like + ON reaction_like.thr_parent = parent_items_base.mid + LEFT JOIN reaction_dislike + ON reaction_dislike.thr_parent = parent_items_base.mid + LEFT JOIN reaction_announce + ON reaction_announce.thr_parent = parent_items_base.mid + LEFT JOIN reaction_accept + ON reaction_accept.thr_parent = parent_items_base.mid + LEFT JOIN reaction_reject + ON reaction_reject.thr_parent = parent_items_base.mid + LEFT JOIN reaction_tentativeaccept + ON reaction_tentativeaccept.thr_parent = parent_items_base.mid + LEFT JOIN reaction_comment + ON reaction_comment.thr_parent = parent_items_base.mid ), - comments AS ( - SELECT sub.*, - $activity_sql_cte_sub - FROM ( - SELECT item.*, - ROW_NUMBER() OVER (PARTITION BY item.parent ORDER BY item.created DESC) AS rn - FROM item - WHERE item.parent IN (%s) - AND item.id != item.parent - AND ( - item.verb NOT IN ('Like', 'Dislike', 'Announce', 'Accept', 'Reject', 'TentativeAccept') - OR (item.verb = 'Announce' AND item.item_thread_top = 1) - ) - $thr_parent_sql - $item_normal_sql - $permission_sql - ) sub - WHERE rn <= 100 -- number of comments we want to load + + all_comments AS ( + SELECT item.*, + ROW_NUMBER() OVER (PARTITION BY item.parent ORDER BY item.created DESC) AS rn + FROM item + WHERE item.id != item.parent + AND item.parent IN ($ids) + AND ( + item.verb NOT IN ('Like', 'Dislike', 'Announce', 'Accept', 'Reject', 'TentativeAccept') + OR (item.verb = 'Announce' AND item.item_thread_top = 1) + ) + $thr_parent_sql + $item_normal_sql + $permission_sql + ), + + last_comments AS ( + SELECT + all_comments.*, + $reaction_select_sql + + FROM all_comments + LEFT JOIN reaction_like + ON reaction_like.thr_parent = all_comments.mid + LEFT JOIN reaction_dislike + ON reaction_dislike.thr_parent = all_comments.mid + LEFT JOIN reaction_announce + ON reaction_announce.thr_parent = all_comments.mid + LEFT JOIN reaction_accept + ON reaction_accept.thr_parent = all_comments.mid + LEFT JOIN reaction_reject + ON reaction_reject.thr_parent = all_comments.mid + LEFT JOIN reaction_tentativeaccept + ON reaction_tentativeaccept.thr_parent = all_comments.mid + LEFT JOIN reaction_comment + ON reaction_comment.thr_parent = all_comments.mid + + WHERE all_comments.rn <= 100 ) - SELECT * FROM parents + SELECT * FROM parent_items UNION ALL - SELECT * FROM comments", - dbesc($ids), - dbesc($ids) + SELECT * FROM last_comments" ); } @@ -5521,156 +5589,79 @@ function items_by_parent_ids(string $ids, array $thr_parents = [], string $permi } /** - * @brief returns an array of items by ids + * @brief prepare reaction sql for items_by_parent_ids() * ATTENTION: no permissions for the pa are checked here!!! * Permissions MUST be checked by the function which returns the ids. - * @param int $id - a parent item id - * @param array $thr_parents (optional) - a string with thr_parent mids separated by comma - * which will be included - * @param string $permission_sql (optional) - SQL provided by item_permission_sql() from the calling module - * @param bool $blog_mode (optional) - if set to yes only the parent items will be returned - */ - -function items_by_parent_id(int $id, array $thr_parents = [], string $permission_sql = '', bool $blog_mode = false): array -{ - if (!$id) { - return []; - } - - $item_normal = item_normal(); - $item_normal_c = item_normal(prefix: 'c'); - $activity_sql = item_activity_sql('c'); - $thread_allow = ((local_channel()) ? PConfig::Get(local_channel(), 'system', 'thread_allow', true) : Config::Get('system', 'thread_allow', true)); - - $blog_mode_sql = (($blog_mode) ? 'item.id' : 'item.parent'); - - $thr_parent_sql = (($thread_allow) ? " AND item.thr_parent = item.parent_mid " : ''); - if ($thr_parents && $thread_allow) { - $thr_parent_str = stringify_array($thr_parents, true); - $thr_parent_sql = " AND item.thr_parent IN (" . protect_sprintf($thr_parent_str) . ") "; - } - - $permission_sql_c = ''; - if ($permission_sql) { - $permission_sql_c = str_replace('item.', 'c.', $permission_sql); - } - - $thread_limit_sql = ''; - if (!$blog_mode && $thread_allow) { - // Get the last x replies but make sure the toplevel is included anyway - $thread_limit_sql = <<<SQL - ORDER BY - CASE WHEN item.id = item.parent THEN 0 ELSE 1 END, - item.created DESC - LIMIT 101 - SQL; - } - - $ret = q( - "SELECT item.*, - $activity_sql - FROM item - LEFT JOIN item c - ON c.parent = item.parent - AND c.item_thread_top = 0 - AND c.thr_parent = item.mid - $item_normal_c - $permission_sql_c - WHERE $blog_mode_sql = %d - AND ( - item.verb NOT IN ('Like', 'Dislike', 'Announce') - OR (item.verb = 'Announce' AND item.item_thread_top = 1) - ) - $thr_parent_sql - $item_normal - $permission_sql - GROUP BY item.id - $thread_limit_sql", - intval($id) - ); - - return $ret; -} - - - -/** - * @brief returns SQL which counts activities for an item and - * if there is an observer also count activities authored by observer. - * @param string $prefix (optional) + * @param string $ids + * @param string $permission_sql (optional) - SQL provided by item_permission_sql() */ -function item_activity_sql_cte($prefix = 'item'): string +function item_reaction_sql(string $ids, string $permission_sql = ''): array { - $thread_allow = ((local_channel()) ? PConfig::Get(local_channel(), 'system', 'thread_allow', true) : Config::Get('system', 'thread_allow', true)); + $item_normal_sql = item_normal(); $observer = get_observer_hash(); - $sql = ''; - if ($observer) { - $observer_verbs = [ - 'Like' => 'observer_liked', - 'Dislike' => 'observer_disliked', - 'Announce' => 'observer_announced', - 'Accept' => 'observer_accepted', - 'Reject' => 'observer_rejected', - 'TentativeAccept' => 'observer_tentativelyaccepted' - ]; + $verbs = [ + 'like' => ['Like'], + 'dislike' => ['Dislike'], + 'announce' => ['Announce'], + 'accept' => ['Accept'], + 'reject' => ['Reject'], + 'tentativeaccept' => ['TentativeAccept'], + 'comment' => ['Create', 'Update'] + ]; - foreach($observer_verbs as $k => $v) { - if ($sql) { - $sql .= ",\n"; - } + $cte = ''; + $select = ''; - $sql .= <<<SQL - (SELECT COUNT(*) FROM item AS reaction - WHERE reaction.parent = $prefix.parent AND reaction.verb = '$k' AND reaction.author_xchan = '$observer' AND reaction.item_thread_top = 0 AND reaction.thr_parent = $prefix.mid - ) AS $v - SQL; - } + foreach($verbs as $k => $v) { - if ($thread_allow) { - $sql .= ",\n"; - $sql .= <<<SQL - (SELECT COUNT(*) FROM item AS reaction - WHERE reaction.parent = $prefix.parent AND reaction.verb IN ('Create', 'Update') AND reaction.author_xchan = '$observer' AND reaction.item_thread_top = 0 AND reaction.thr_parent = $prefix.mid - ) AS observer_commented - SQL; + $observer_sql = "0 AS observer_{$k}_count"; + if ($observer) { + $observer_sql = "COUNT(CASE WHEN item.author_xchan = '$observer' THEN 1 END) AS observer_{$k}_count"; } - } - $verbs = [ - 'Like' => 'like_count', - 'Dislike' => 'dislike_count', - 'Announce' => 'announce_count', - 'Accept' => 'attendyes_count', - 'Reject' => 'attendno_count', - 'TentativeAccept' => 'attendmaybe_count' - ]; + $verbs_str = stringify_array($v); - foreach($verbs as $k => $v) { - if ($sql) { - $sql .= ",\n"; + if ($cte) { + $cte .= ",\n"; } - $sql .= <<<SQL - (SELECT COUNT(*) FROM item AS reaction - WHERE reaction.parent = $prefix.parent AND reaction.verb = '$k' AND reaction.item_thread_top = 0 AND reaction.thr_parent = $prefix.mid - ) AS $v + $cte .= <<<SQL + reaction_{$k} AS ( + SELECT + item.thr_parent, + COUNT(*) AS {$k}_count, + $observer_sql + FROM item + WHERE item.verb IN ($verbs_str) + AND item.item_thread_top = 0 + AND item.parent IN ($ids) + $item_normal_sql + $permission_sql + GROUP BY item.thr_parent + ) SQL; - } - if ($thread_allow) { - $sql .= ",\n"; - $sql .= <<<SQL - (SELECT COUNT(*) FROM item AS reaction - WHERE reaction.parent = $prefix.parent AND reaction.verb IN ('Create', 'Update') AND reaction.item_thread_top = 0 AND reaction.thr_parent = $prefix.mid - ) AS comment_count + if ($select) { + $select .= ",\n"; + } + + $select .= <<<SQL + COALESCE(reaction_{$k}.{$k}_count, 0) AS {$k}_count, + COALESCE(reaction_{$k}.observer_{$k}_count, 0) AS observer_{$k}_count SQL; + } - return $sql; + $ret['cte'] = $cte; + $ret['select'] = $select; + + return $ret; } + + /** * @brief returns an array of items by thr_parent mid of a parent @@ -5678,6 +5669,7 @@ function item_activity_sql_cte($prefix = 'item'): string * @param int $parent */ +// TODO: streamline logic with items_by_parent_ids() - function items_by_thr_parent(string $mid, int $parent): array { if (!$mid && !$parent) { diff --git a/view/js/main.js b/view/js/main.js index 7043c8577..6d79f9092 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -1294,6 +1294,11 @@ function justifyPhotosAjax(id) { function request(id, mid, verb, parent, uuid) { + if (!id) { + console.log('load_more'); + return; + } + const loading = document.getElementById('like-rotator-' + id); loading.style.display = 'block'; diff --git a/view/tpl/conv_item.tpl b/view/tpl/conv_item.tpl index 6d8aa6abc..3bca23df8 100644 --- a/view/tpl/conv_item.tpl +++ b/view/tpl/conv_item.tpl @@ -207,9 +207,12 @@ <div class="dropdown-divider"></div> <a class="dropdown-item" href="dreport/{{$item.dreport_link}}">{{$item.dreport}}</a> {{/if}} + {{if $item.load_more}} + <a class="dropdown-item conversation-load-more" title="{{$item.load_more_title}}" href="#" onclick="request(''); return false;">{{$item.load_more}}</a> + {{/if}} {{if $item.settings}} <div class="dropdown-divider"></div> - <a class="dropdown-item conversation-settings-link" href="" data-bs-toggle="modal" data-bs-target="#conversation_settings">{{$item.settings}}</a> + <a class="dropdown-item conversation-settings-link" href="#" data-bs-toggle="modal" data-bs-target="#conversation_settings">{{$item.settings}}</a> {{/if}} </div> </div> |