recent_topics: Show user presence status in PMs messages.

We have bound the `mouseenter` event with a circle
status parent element to render the tooltip. Instead of passing
the tooltip content directly in `data-tippy-content`, we
are rendering it via JS because when showing the bot
tooltip we want a multiline tooltip.

We have also made some minor changes to `do_render_buddy_list_tooltip`,
so we can append the tooltip to the target element and avoid adding
a observer to it.

This commit also sets the font weight for tippy content to
400 to avoid bold content.
This commit is contained in:
Riken Shah 2022-10-20 17:19:03 +05:30 committed by Tim Abbott
parent 6e3d8c7733
commit 9d12a9c21e
4 changed files with 109 additions and 29 deletions

View File

@ -592,7 +592,12 @@ export function initialize() {
$(".tooltip").remove(); $(".tooltip").remove();
}); });
function do_render_buddy_list_tooltip($elem, title_data) { function do_render_buddy_list_tooltip(
$elem,
title_data,
parent_element_to_append = null,
is_custom_observer_needed = true,
) {
let placement = "left"; let placement = "left";
let observer; let observer;
if (window.innerWidth < media_breakpoints_num.md) { if (window.innerWidth < media_breakpoints_num.md) {
@ -611,9 +616,14 @@ export function initialize() {
showOnCreate: true, showOnCreate: true,
onHidden: (instance) => { onHidden: (instance) => {
instance.destroy(); instance.destroy();
if (is_custom_observer_needed) {
observer.disconnect(); observer.disconnect();
}
}, },
onShow: (instance) => { onShow: (instance) => {
if (!is_custom_observer_needed) {
return;
}
// For both buddy list and top left corner pm list, `target_node` // For both buddy list and top left corner pm list, `target_node`
// is their parent `ul` element. We cannot use MutationObserver // is their parent `ul` element. We cannot use MutationObserver
// directly on the reference element because it will be removed // directly on the reference element because it will be removed
@ -638,7 +648,7 @@ export function initialize() {
observer = new MutationObserver(callback); observer = new MutationObserver(callback);
observer.observe(target_node, config); observer.observe(target_node, config);
}, },
appendTo: () => document.body, appendTo: () => parent_element_to_append || document.body,
}); });
} }
@ -663,6 +673,19 @@ export function initialize() {
do_render_buddy_list_tooltip($elem, title_data); do_render_buddy_list_tooltip($elem, title_data);
}); });
// Recent conversations PMs
$("body").on("mouseenter", ".recent_topic_stream .pm_status_icon", (e) => {
e.stopPropagation();
const $elem = $(e.currentTarget);
const user_ids_string = $elem.attr("data-user-ids-string");
// Don't show tooltip for group PMs.
if (!user_ids_string || user_ids_string.split(",").length !== 1) {
return;
}
const title_data = recent_topics_ui.get_pm_tooltip_data(user_ids_string);
do_render_buddy_list_tooltip($elem, title_data, undefined, false);
});
// MISC // MISC
{ {

View File

@ -318,6 +318,43 @@ function message_to_conversation_unread_count(msg) {
return unread.num_unread_for_topic(msg.stream_id, msg.topic); return unread.num_unread_for_topic(msg.stream_id, msg.topic);
} }
export function get_pm_tooltip_data(user_ids_string) {
const user_id = Number.parseInt(user_ids_string, 10);
const person = people.get_by_user_id(user_id);
if (person.is_bot) {
const bot_owner = people.get_bot_owner_user(person);
if (bot_owner) {
const bot_owner_name = $t(
{defaultMessage: "Owner: {name}"},
{name: bot_owner.full_name},
);
return {
first_line: person.full_name,
second_line: bot_owner_name,
};
}
// Bot does not have an owner.
return {
first_line: person.full_name,
second_line: "",
third_line: "",
};
}
const last_seen = buddy_data.user_last_seen_time_status(user_id);
// Users does not have a status.
return {
first_line: last_seen,
second_line: "",
third_line: "",
};
}
function format_conversation(conversation_data) { function format_conversation(conversation_data) {
const context = {}; const context = {};
const last_msg = message_store.get(conversation_data.last_msg_id); const last_msg = message_store.get(conversation_data.last_msg_id);
@ -379,9 +416,15 @@ function format_conversation(conversation_data) {
senders = all_senders.slice(-MAX_AVATAR).map((sender) => sender.id); senders = all_senders.slice(-MAX_AVATAR).map((sender) => sender.id);
if (!context.is_group) { if (!context.is_group) {
context.user_circle_class = buddy_data.get_user_circle_class( const user_id = Number.parseInt(last_msg.to_user_ids, 10);
Number.parseInt(last_msg.to_user_ids, 10), const user = people.get_by_user_id(user_id);
); if (user.is_bot) {
// Bots do not have status emoji, and are modeled as
// always present.
context.user_circle_class = "user_circle_green";
} else {
context.user_circle_class = buddy_data.get_user_circle_class(user_id);
}
} }
// Collect extra senders fullname for tooltip. // Collect extra senders fullname for tooltip.

View File

@ -170,6 +170,10 @@
/* Flex container to fit in user circle and group icon */ /* Flex container to fit in user circle and group icon */
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
.tippy-content {
font-weight: 400;
}
} }
.flex_container { .flex_container {
@ -382,13 +386,22 @@
} }
} }
.private_conversation_row {
.recent_topic_stream {
/* Reduce padding of stream section so that user status
icon can have more padding without impacting height of the row */
padding: 5px 0 5px 8px;
}
.pm_status_icon { .pm_status_icon {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
/* Increasing vertical padding any further will increase /* Increasing vertical padding any further will increase
the height of the row. */ the height of the row. */
padding: 5px 0 5px 8px; padding: 8px;
position: relative;
right: -8px; /* To cancel padding-right */
/* To accommodate fa-group icon */ /* To accommodate fa-group icon */
width: 14px; width: 14px;
height: 14px; height: 14px;
@ -408,6 +421,7 @@
} }
} }
} }
}
#recent_topics_bottom_whitespace { #recent_topics_bottom_whitespace {
/* For visual reasons, in a message feed, we require a large /* For visual reasons, in a message feed, we require a large

View File

@ -1,4 +1,4 @@
<tr id="recent_conversation:{{conversation_key}}" {{#if unread_count}}class="unread_topic"{{/if}} data-unread-count="{{unread_count}}" data-muted="{{muted}}" data-participated="{{participated}}" data-private="{{is_private}}"> <tr id="recent_conversation:{{conversation_key}}" class="{{#if unread_count}}unread_topic{{/if}} {{#if is_private}}private_conversation_row{{/if}}" data-unread-count="{{unread_count}}" data-muted="{{muted}}" data-participated="{{participated}}" data-private="{{is_private}}">
<td class="recent_topic_stream"> <td class="recent_topic_stream">
<div class="flex_container flex_container_pm"> <div class="flex_container flex_container_pm">
<div class="left_part recent_topics_focusable"> <div class="left_part recent_topics_focusable">
@ -15,7 +15,7 @@
{{!-- For presence/group indicator --}} {{!-- For presence/group indicator --}}
{{#if is_private}} {{#if is_private}}
<div class="right_part"> <div class="right_part">
<span class="pm_status_icon"> <span class="pm_status_icon {{#unless is_group}}show-tooltip{{/unless}}" data-tippy-placement="top" data-user-ids-string="{{user_ids_string}}">
{{#if is_group}} {{#if is_group}}
<span class="fa fa-group"></span> <span class="fa fa-group"></span>
{{else}} {{else}}