diff --git a/static/js/click_handlers.js b/static/js/click_handlers.js index 0e109e9f14..10f6bcc1e0 100644 --- a/static/js/click_handlers.js +++ b/static/js/click_handlers.js @@ -592,7 +592,12 @@ export function initialize() { $(".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 observer; if (window.innerWidth < media_breakpoints_num.md) { @@ -611,9 +616,14 @@ export function initialize() { showOnCreate: true, onHidden: (instance) => { instance.destroy(); - observer.disconnect(); + if (is_custom_observer_needed) { + observer.disconnect(); + } }, onShow: (instance) => { + if (!is_custom_observer_needed) { + return; + } // For both buddy list and top left corner pm list, `target_node` // is their parent `ul` element. We cannot use MutationObserver // directly on the reference element because it will be removed @@ -638,7 +648,7 @@ export function initialize() { observer = new MutationObserver(callback); 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); }); + // 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 { diff --git a/static/js/recent_topics_ui.js b/static/js/recent_topics_ui.js index 4c3eb35d4d..f8d9754940 100644 --- a/static/js/recent_topics_ui.js +++ b/static/js/recent_topics_ui.js @@ -318,6 +318,43 @@ function message_to_conversation_unread_count(msg) { 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) { const context = {}; 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); if (!context.is_group) { - context.user_circle_class = buddy_data.get_user_circle_class( - Number.parseInt(last_msg.to_user_ids, 10), - ); + const user_id = 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. diff --git a/static/styles/recent_topics.css b/static/styles/recent_topics.css index 119d2d6ac3..abcc8a6c79 100644 --- a/static/styles/recent_topics.css +++ b/static/styles/recent_topics.css @@ -170,6 +170,10 @@ /* Flex container to fit in user circle and group icon */ display: flex; justify-content: space-between; + + .tippy-content { + font-weight: 400; + } } .flex_container { @@ -382,29 +386,39 @@ } } - .pm_status_icon { - display: flex; - justify-content: center; - align-items: center; - /* Increasing vertical padding any further will increase - the height of the row. */ - padding: 5px 0 5px 8px; - /* To accommodate fa-group icon */ - width: 14px; - height: 14px; - - .fa-group { - font-size: 0.8rem; - /* color: hsl(105, 2%, 50%); */ - opacity: 0.6; + .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; } - .user_circle { - /* Shrink the user activity circle for the recent topics context. */ - width: 7px; - height: 7px; - float: left; - position: unset; + .pm_status_icon { + display: flex; + justify-content: center; + align-items: center; + /* Increasing vertical padding any further will increase + the height of the row. */ + padding: 8px; + position: relative; + right: -8px; /* To cancel padding-right */ + /* To accommodate fa-group icon */ + width: 14px; + height: 14px; + + .fa-group { + font-size: 0.8rem; + /* color: hsl(105, 2%, 50%); */ + opacity: 0.6; + } + + .user_circle { + /* Shrink the user activity circle for the recent topics context. */ + width: 7px; + height: 7px; + float: left; + position: unset; + } } } } diff --git a/static/templates/recent_topic_row.hbs b/static/templates/recent_topic_row.hbs index 155a5b082b..43cdc81e7d 100644 --- a/static/templates/recent_topic_row.hbs +++ b/static/templates/recent_topic_row.hbs @@ -1,4 +1,4 @@ -