messagebox: Add classnames to mark which messages contain which mentions.

This is part of redesigning messages (#22059). This commit adds
classnames to messages with mentions, differentiating direct mentions
from wildcard mentions from usergroup mentions, and this set us up
for a future commit where we'll have those different kinds of messages
be displayed in different colors.
This commit is contained in:
evykassirer 2022-09-03 11:48:38 -07:00 committed by Tim Abbott
parent a276603766
commit 3f66a9ef2b
4 changed files with 60 additions and 14 deletions

View File

@ -6,6 +6,7 @@ const _ = require("lodash");
const {mock_esm, set_global, zrequire} = require("../zjsunit/namespace"); const {mock_esm, set_global, zrequire} = require("../zjsunit/namespace");
const {run_test} = require("../zjsunit/test"); const {run_test} = require("../zjsunit/test");
const $ = require("../zjsunit/zjquery");
set_global("document", "document-stub"); set_global("document", "document-stub");
@ -309,11 +310,26 @@ test("muted_message_vars", () => {
} }
(function test_hidden_message_variables() { (function test_hidden_message_variables() {
// We want to have no search results, which apparently works like this.
// See https://chat.zulip.org/#narrow/stream/6-frontend/topic/set_find_results.20with.20no.20results/near/1414799
const empty_list_stub = $.create("empty-stub", {children: []});
$("<message-stub-1>").set_find_results(".user-mention:not(.silent)", empty_list_stub);
$("<message-stub2>").set_find_results(".user-mention:not(.silent)", empty_list_stub);
$("<message-stub-3>").set_find_results(".user-mention:not(.silent)", empty_list_stub);
// Make a representative message group of three messages. // Make a representative message group of three messages.
const messages = [ const messages = [
build_message_context({sender_id: 10}, {include_sender: true}), build_message_context(
build_message_context({mentioned: true, sender_id: 10}, {include_sender: false}), {sender_id: 10, content: "<message-stub-1>"},
build_message_context({sender_id: 10}, {include_sender: false}), {include_sender: true},
),
build_message_context(
{mentioned: true, sender_id: 10, content: "<message-stub2>"},
{include_sender: false},
),
build_message_context(
{sender_id: 10, content: "<message-stub-3>"},
{include_sender: false},
),
]; ];
const message_group = build_message_group(messages); const message_group = build_message_group(messages);
const list = build_list([message_group]); const list = build_list([message_group]);
@ -336,8 +352,8 @@ test("muted_message_vars", () => {
assert.equal(result[1].include_sender, false); assert.equal(result[1].include_sender, false);
assert.equal(result[2].include_sender, false); assert.equal(result[2].include_sender, false);
// Additionally test that, `contains_mention` is true on that message has a mention. // Additionally test that the message with a mention is marked as such.
assert.equal(result[1].contains_mention, true); assert.equal(result[1].mention_classname, "group_mention");
// Now, mute the sender. // Now, mute the sender.
muted_users.add_muted_user(10); muted_users.add_muted_user(10);
@ -352,8 +368,9 @@ test("muted_message_vars", () => {
assert.equal(result[1].include_sender, false); assert.equal(result[1].include_sender, false);
assert.equal(result[2].include_sender, false); assert.equal(result[2].include_sender, false);
// Additionally test that, `contains_mention` is false even on that message which has a mention. // Additionally test that, both there is no mention classname even on that message
assert.equal(result[1].contains_mention, false); // which has a mention, since we don't want to display muted mentions so visibly.
assert.equal(result[1].mention_classname, null);
// Now, reveal the hidden messages. // Now, reveal the hidden messages.
let is_revealed = true; let is_revealed = true;
@ -368,8 +385,8 @@ test("muted_message_vars", () => {
assert.equal(result[1].include_sender, true); assert.equal(result[1].include_sender, true);
assert.equal(result[2].include_sender, true); assert.equal(result[2].include_sender, true);
// Additionally test that, `contains_mention` is true on that message which has a mention. // Additionally test that the message with a mention is marked as such.
assert.equal(result[1].contains_mention, true); assert.equal(result[1].mention_classname, "group_mention");
// Now test rehiding muted user's message // Now test rehiding muted user's message
is_revealed = false; is_revealed = false;
@ -384,8 +401,9 @@ test("muted_message_vars", () => {
assert.equal(result[1].include_sender, false); assert.equal(result[1].include_sender, false);
assert.equal(result[2].include_sender, false); assert.equal(result[2].include_sender, false);
// Additionally test that, `contains_mention` is false on that message which has a mention. // Additionally test that, both there is no mention classname even on that message
assert.equal(result[1].contains_mention, false); // which has a mention, since we don't want to display hidden mentions so visibly.
assert.equal(result[1].mention_classname, null);
})(); })();
}); });

View File

@ -326,8 +326,36 @@ export class MessageListView {
message_container.is_hidden = is_hidden; message_container.is_hidden = is_hidden;
// Make sure the right thing happens if the message was edited to mention us. // Make sure the right thing happens if the message was edited to mention us.
message_container.contains_mention = message_container.msg.mentioned && !is_hidden; if (!is_hidden && message_container.msg.mentioned) {
// Currently the API does not differentiate between a group mention and
// a user mention. For now, we parse the markdown to see if the message
// mentions the user.
let is_user_mention = false;
const $msg = $(message_container.msg.content);
$msg.find(".user-mention:not(.silent)").each(function () {
const user_id = rendered_markdown.get_user_id_for_mention_button(this);
if (user_id === "*") {
return;
}
if (people.is_my_user_id(user_id)) {
is_user_mention = true;
}
});
// If a message includes a user mention, then we don't care if there is a
// group/wildcard mention, and color the message as a user mention. If the
// message didn't include a user mention, then it was a usergroup/wildcard
// mention (which is the only other option for `mentioned` being true).
if (message_container.msg.mentioned_me_directly && is_user_mention) {
message_container.mention_classname = "direct_mention";
} else {
message_container.mention_classname = "group_mention";
}
} else {
// If there are no mentions, the classname might need to be updated (i.e.
// removed) to reflect this.
message_container.mention_classname = null;
}
message_container.include_sender = message_container.include_sender && !is_hidden; message_container.include_sender = message_container.include_sender && !is_hidden;
if (is_revealed) { if (is_revealed) {
// If the message is to be revealed, we show the sender anyways, because the // If the message is to be revealed, we show the sender anyways, because the

View File

@ -27,7 +27,7 @@ import {user_settings} from "./user_settings";
is being displayed. is being displayed.
*/ */
function get_user_id_for_mention_button(elem) { export function get_user_id_for_mention_button(elem) {
const user_id_string = $(elem).attr("data-user-id"); const user_id_string = $(elem).attr("data-user-id");
// Handle legacy Markdown that was rendered before we cut // Handle legacy Markdown that was rendered before we cut
// over to using data-user-id. // over to using data-user-id.

View File

@ -1,5 +1,5 @@
<div zid="{{msg/id}}" id="{{table_name}}{{msg/id}}" <div zid="{{msg/id}}" id="{{table_name}}{{msg/id}}"
class="message_row{{^msg/is_stream}} private-message{{/msg/is_stream}}{{#include_sender}} include-sender{{/include_sender}}{{#contains_mention}} mention{{/contains_mention}}{{#include_footer}} last_message{{/include_footer}}{{#msg.unread}} unread{{/msg.unread}} {{#if msg.locally_echoed}}local{{/if}} selectable_row" class="message_row{{^msg/is_stream}} private-message{{/msg/is_stream}}{{#include_sender}} include-sender{{/include_sender}}{{#if mention_classname}} {{mention_classname}}{{/if}}{{#include_footer}} last_message{{/include_footer}}{{#msg.unread}} unread{{/msg.unread}} {{#if msg.locally_echoed}}local{{/if}} selectable_row"
role="listitem"> role="listitem">
<div class="unread_marker"><div class="unread-marker-fill"></div></div> <div class="unread_marker"><div class="unread-marker-fill"></div></div>
{{#if want_date_divider}} {{#if want_date_divider}}