mirror of https://github.com/zulip/zulip.git
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:
parent
6e3d8c7733
commit
9d12a9c21e
|
@ -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
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
Loading…
Reference in New Issue