mirror of https://github.com/zulip/zulip.git
reactions: Implement display_emoji_reaction_users setting.
This setting provides a more ergonomic experience when viewing a message where only a small number of emoji reactions are present; you no longer need to hover over the reaction to see who reacted, which is often quite important to understanding what it means. We added this setting (visible in the development environment only, and implemented on mobile) a few months ago; so to complete this feature, we just need to add the frontend rendering/live update logic and publish it. As documented in the code comments, the current rule is "messages with 3 or fewer reactions" for which messages will display the names of the users reacting. The previous set_reaction_count API made sense when the display of a given reaction was a pure function of its data. However, we will soon be making it a function of the total number of reactions on the message. Thus, view functions to update reaction display now need to call a shared update_vote_text_on_message function in all code paths, even code paths like "add the first vote for a reaction" and "remove the sole vote of a reaction" which previously did not need to call set_reaction_count. Fixes #20890.
This commit is contained in:
parent
98c478d994
commit
d47f29c2d6
|
@ -7,7 +7,7 @@ const {make_stub} = require("../zjsunit/stub");
|
|||
const {run_test} = require("../zjsunit/test");
|
||||
const blueslip = require("../zjsunit/zblueslip");
|
||||
const $ = require("../zjsunit/zjquery");
|
||||
const {page_params} = require("../zjsunit/zpage_params");
|
||||
const {page_params, user_settings} = require("../zjsunit/zpage_params");
|
||||
|
||||
const alice_user_id = 5;
|
||||
|
||||
|
@ -162,6 +162,7 @@ test("basics", () => {
|
|||
emoji_code: "1f641",
|
||||
local_id: "unicode_emoji,1f641",
|
||||
count: 1,
|
||||
vote_text: "1",
|
||||
user_ids: [7],
|
||||
label: "translated: Cali reacted with :frown:",
|
||||
emoji_alt_code: false,
|
||||
|
@ -174,6 +175,7 @@ test("basics", () => {
|
|||
emoji_code: "992",
|
||||
local_id: "realm_emoji,992",
|
||||
count: 1,
|
||||
vote_text: "1",
|
||||
user_ids: [5],
|
||||
label: "translated: You (click to remove) reacted with :inactive_realm_emoji:",
|
||||
emoji_alt_code: false,
|
||||
|
@ -188,6 +190,7 @@ test("basics", () => {
|
|||
emoji_code: "1f642",
|
||||
local_id: "unicode_emoji,1f642",
|
||||
count: 2,
|
||||
vote_text: "2",
|
||||
user_ids: [5, 6],
|
||||
label: "translated: You (click to remove) and Bob van Roberts reacted with :smile:",
|
||||
emoji_alt_code: false,
|
||||
|
@ -200,6 +203,7 @@ test("basics", () => {
|
|||
emoji_code: "1f389",
|
||||
local_id: "unicode_emoji,1f389",
|
||||
count: 2,
|
||||
vote_text: "2",
|
||||
user_ids: [7, 8],
|
||||
label: "translated: Cali and Alexus reacted with :tada:",
|
||||
emoji_alt_code: false,
|
||||
|
@ -212,6 +216,7 @@ test("basics", () => {
|
|||
emoji_code: "1f680",
|
||||
local_id: "unicode_emoji,1f680",
|
||||
count: 3,
|
||||
vote_text: "3",
|
||||
user_ids: [5, 6, 7],
|
||||
label: "translated: You (click to remove), Bob van Roberts and Cali reacted with :rocket:",
|
||||
emoji_alt_code: false,
|
||||
|
@ -224,6 +229,7 @@ test("basics", () => {
|
|||
emoji_code: "1f44b",
|
||||
local_id: "unicode_emoji,1f44b",
|
||||
count: 3,
|
||||
vote_text: "3",
|
||||
user_ids: [6, 7, 8],
|
||||
label: "translated: Bob van Roberts, Cali and Alexus reacted with :wave:",
|
||||
emoji_alt_code: false,
|
||||
|
@ -380,15 +386,107 @@ function stub_reaction(message_id, local_id) {
|
|||
return $reaction;
|
||||
}
|
||||
|
||||
test("set_reaction_count", () => {
|
||||
const $count_element = $.create("count-stub");
|
||||
const $reaction_element = $.create("reaction-stub");
|
||||
test("get_vote_text (more than 3 reactions)", () => {
|
||||
const user_ids = [5, 6, 7];
|
||||
const message = {...sample_message};
|
||||
|
||||
$reaction_element.set_find_results(".message_reaction_count", $count_element);
|
||||
user_settings.display_emoji_reaction_users = true;
|
||||
assert.equal(
|
||||
"translated: You, Bob van Roberts, Cali",
|
||||
reactions.get_vote_text({user_ids}, message),
|
||||
);
|
||||
});
|
||||
|
||||
reactions.set_reaction_count($reaction_element, 5);
|
||||
test("get_vote_text (3 reactions)", () => {
|
||||
const user_ids = [5, 6, 7];
|
||||
const message = {...sample_message};
|
||||
|
||||
assert.equal($count_element.text(), "5");
|
||||
// slicing the reactions array to only include first 3 reactions
|
||||
message.reactions = message.reactions.slice(0, 3);
|
||||
|
||||
user_settings.display_emoji_reaction_users = true;
|
||||
assert.equal(
|
||||
"translated: You, Bob van Roberts, Cali",
|
||||
reactions.get_vote_text({user_ids}, message),
|
||||
);
|
||||
});
|
||||
|
||||
test("update_vote_text_on_message", ({override_rewire}) => {
|
||||
// the vote_text in this message is intentionally wrong.
|
||||
// After calling update_vote_text_on_message(), we
|
||||
// will check if the vote_text has been correctly updated.
|
||||
const message = {
|
||||
id: 1001,
|
||||
reactions: [
|
||||
{
|
||||
emoji_name: "wave",
|
||||
user_id: 5,
|
||||
reaction_type: "unicode_emoji",
|
||||
emoji_code: "1f44b",
|
||||
vote_text: "2",
|
||||
},
|
||||
{
|
||||
emoji_name: "wave",
|
||||
user_id: 6,
|
||||
reaction_type: "unicode_emoji",
|
||||
emoji_code: "1f44b",
|
||||
vote_text: "2",
|
||||
},
|
||||
|
||||
{
|
||||
emoji_name: "inactive_realm_emoji",
|
||||
user_id: 5,
|
||||
reaction_type: "realm_emoji",
|
||||
emoji_code: "992",
|
||||
vote_text: "1",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
user_settings.display_emoji_reaction_users = true;
|
||||
|
||||
override_rewire(reactions, "find_reaction", () => {});
|
||||
override_rewire(reactions, "set_reaction_vote_text", () => {});
|
||||
|
||||
reactions.update_vote_text_on_message(message);
|
||||
|
||||
const updated_message = {
|
||||
clean_reactions: new Map(
|
||||
Object.entries({
|
||||
"realm_emoji,992": {
|
||||
class: "message_reaction reacted",
|
||||
count: 1,
|
||||
emoji_alt_code: false,
|
||||
emoji_code: "992",
|
||||
emoji_name: "inactive_realm_emoji",
|
||||
is_realm_emoji: true,
|
||||
label: "translated: You (click to remove) reacted with :inactive_realm_emoji:",
|
||||
local_id: "realm_emoji,992",
|
||||
reaction_type: "realm_emoji",
|
||||
still_url: "/still/url/for/992",
|
||||
url: "/url/for/992",
|
||||
user_ids: [5],
|
||||
vote_text: "translated: You",
|
||||
},
|
||||
"unicode_emoji,1f44b": {
|
||||
class: "message_reaction reacted",
|
||||
count: 2,
|
||||
emoji_alt_code: false,
|
||||
emoji_code: "1f44b",
|
||||
emoji_name: "wave",
|
||||
is_realm_emoji: false,
|
||||
label: "translated: You (click to remove) and Bob van Roberts reacted with :wave:",
|
||||
local_id: "unicode_emoji,1f44b",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_ids: [5, 6],
|
||||
vote_text: "translated: You, Bob van Roberts",
|
||||
},
|
||||
}),
|
||||
),
|
||||
id: 1001,
|
||||
};
|
||||
// message.reactions is deleted too.
|
||||
assert.deepEqual(message, updated_message);
|
||||
});
|
||||
|
||||
test("find_reaction", () => {
|
||||
|
@ -427,6 +525,8 @@ test("add_reaction/remove_reaction", ({override}) => {
|
|||
reactions: [],
|
||||
};
|
||||
|
||||
user_settings.display_emoji_reaction_users = true;
|
||||
|
||||
override(message_store, "get", () => message);
|
||||
|
||||
let view_calls = [];
|
||||
|
@ -502,6 +602,7 @@ test("add_reaction/remove_reaction", ({override}) => {
|
|||
local_id: "unicode_emoji,1f3b1",
|
||||
reaction_type: alice_8ball_event.reaction_type,
|
||||
user_ids: [alice.user_id],
|
||||
vote_text: "translated: You",
|
||||
};
|
||||
test_view_calls({
|
||||
run_code() {
|
||||
|
@ -545,6 +646,7 @@ test("add_reaction/remove_reaction", ({override}) => {
|
|||
local_id: "unicode_emoji,1f3b1",
|
||||
reaction_type: bob_8ball_event.reaction_type,
|
||||
user_ids: [alice.user_id, bob.user_id],
|
||||
vote_text: "translated: You, Bob van Roberts",
|
||||
};
|
||||
test_view_calls({
|
||||
run_code() {
|
||||
|
@ -579,6 +681,7 @@ test("add_reaction/remove_reaction", ({override}) => {
|
|||
local_id: "unicode_emoji,2708",
|
||||
reaction_type: cali_airplane_event.reaction_type,
|
||||
user_ids: [cali.user_id],
|
||||
vote_text: "Cali",
|
||||
};
|
||||
test_view_calls({
|
||||
run_code() {
|
||||
|
@ -634,8 +737,17 @@ test("add_reaction/remove_reaction", ({override}) => {
|
|||
{
|
||||
name: "remove_reaction",
|
||||
clean_reaction_object: {
|
||||
...clean_reaction_object_alice,
|
||||
count: 0,
|
||||
class: "message_reaction",
|
||||
emoji_alt_code: false,
|
||||
emoji_code: alice_8ball_event.emoji_code,
|
||||
emoji_name: alice_8ball_event.emoji_name,
|
||||
is_realm_emoji: false,
|
||||
label: "translated: and reacted with :8ball:",
|
||||
local_id: "unicode_emoji,1f3b1",
|
||||
reaction_type: alice_8ball_event.reaction_type,
|
||||
user_ids: [],
|
||||
vote_text: "",
|
||||
},
|
||||
message: {
|
||||
clean_reactions: new Map(
|
||||
|
@ -677,9 +789,11 @@ test("view.insert_new_reaction (me w/unicode emoji)", ({mock_template}) => {
|
|||
const message_id = 501;
|
||||
|
||||
const $message_reactions = stub_reactions(message_id);
|
||||
$message_reactions.find = (selector) => {
|
||||
assert.equal(selector, ".reaction_button");
|
||||
return "reaction-button-stub";
|
||||
const $reaction_button = $.create("reaction-button-stub");
|
||||
$message_reactions.find = () => $reaction_button;
|
||||
$reaction_button.find = (selector) => {
|
||||
assert.equal(selector, ".message_reaction_count");
|
||||
return $.create("message-reaction-count-stub");
|
||||
};
|
||||
|
||||
mock_template("message_reaction.hbs", false, (data) => {
|
||||
|
@ -700,11 +814,25 @@ test("view.insert_new_reaction (me w/unicode emoji)", ({mock_template}) => {
|
|||
|
||||
let insert_called;
|
||||
$("<new-reaction-stub>").insertBefore = (element) => {
|
||||
assert.equal(element, "reaction-button-stub");
|
||||
assert.equal(element, $reaction_button);
|
||||
insert_called = true;
|
||||
};
|
||||
|
||||
reactions.view.insert_new_reaction(clean_reaction_object, {id: message_id}, alice.user_id);
|
||||
reactions.view.insert_new_reaction(
|
||||
clean_reaction_object,
|
||||
{
|
||||
id: message_id,
|
||||
reactions: [
|
||||
{
|
||||
emoji_name: "8ball",
|
||||
user_id: alice.user_id,
|
||||
reaction_type: "unicode_emoji",
|
||||
emoji_code: "1f3b1",
|
||||
},
|
||||
],
|
||||
},
|
||||
alice.user_id,
|
||||
);
|
||||
assert.ok(insert_called);
|
||||
});
|
||||
|
||||
|
@ -716,7 +844,7 @@ test("view.insert_new_reaction (them w/zulip emoji)", ({mock_template}) => {
|
|||
emoji_code: "zulip",
|
||||
emoji_name: "zulip",
|
||||
is_realm_emoji: false,
|
||||
label: "translated: You (click to remove) reacted with :zulip:",
|
||||
label: "translated: Bob van Roberts reacted with :zulip:",
|
||||
local_id: "realm_emoji,zulip",
|
||||
reaction_type: "realm_emoji",
|
||||
user_ids: [bob.user_id],
|
||||
|
@ -724,9 +852,11 @@ test("view.insert_new_reaction (them w/zulip emoji)", ({mock_template}) => {
|
|||
const message_id = 501;
|
||||
|
||||
const $message_reactions = stub_reactions(message_id);
|
||||
$message_reactions.find = (selector) => {
|
||||
assert.equal(selector, ".reaction_button");
|
||||
return "reaction-button-stub";
|
||||
const $reaction_button = $.create("reaction-button-stub");
|
||||
$message_reactions.find = () => $reaction_button;
|
||||
$reaction_button.find = (selector) => {
|
||||
assert.equal(selector, ".message_reaction_count");
|
||||
return $.create("message-reaction-count-stub");
|
||||
};
|
||||
|
||||
mock_template("message_reaction.hbs", false, (data) => {
|
||||
|
@ -749,18 +879,32 @@ test("view.insert_new_reaction (them w/zulip emoji)", ({mock_template}) => {
|
|||
|
||||
let insert_called;
|
||||
$("<new-reaction-stub>").insertBefore = (element) => {
|
||||
assert.equal(element, "reaction-button-stub");
|
||||
assert.equal(element, $reaction_button);
|
||||
insert_called = true;
|
||||
};
|
||||
|
||||
reactions.view.insert_new_reaction(clean_reaction_object, {id: message_id}, bob.user_id);
|
||||
reactions.view.insert_new_reaction(
|
||||
clean_reaction_object,
|
||||
{
|
||||
id: message_id,
|
||||
reactions: [
|
||||
{
|
||||
emoji_name: "8ball",
|
||||
user_id: bob.user_id,
|
||||
reaction_type: "unicode_emoji",
|
||||
emoji_code: "1f3b1",
|
||||
},
|
||||
],
|
||||
},
|
||||
bob.user_id,
|
||||
);
|
||||
assert.ok(insert_called);
|
||||
});
|
||||
|
||||
test("view.update_existing_reaction (me)", () => {
|
||||
const clean_reaction_object = {
|
||||
class: "message_reaction",
|
||||
count: 1,
|
||||
count: 2,
|
||||
emoji_alt_code: false,
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
|
@ -775,9 +919,28 @@ test("view.update_existing_reaction (me)", () => {
|
|||
const $reaction_count = $.create("reaction-count-stub");
|
||||
$our_reaction.set_find_results(".message_reaction_count", $reaction_count);
|
||||
|
||||
reactions.view.update_existing_reaction(clean_reaction_object, {id: message_id}, alice.user_id);
|
||||
reactions.view.update_existing_reaction(
|
||||
clean_reaction_object,
|
||||
{
|
||||
id: message_id,
|
||||
reactions: [
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: alice.user_id,
|
||||
},
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: bob.user_id,
|
||||
},
|
||||
],
|
||||
},
|
||||
alice.user_id,
|
||||
);
|
||||
|
||||
assert.equal($reaction_count.text(), "2");
|
||||
assert.ok($our_reaction.hasClass("reacted"));
|
||||
assert.equal(
|
||||
$our_reaction.attr("aria-label"),
|
||||
|
@ -788,7 +951,7 @@ test("view.update_existing_reaction (me)", () => {
|
|||
test("view.update_existing_reaction (them)", () => {
|
||||
const clean_reaction_object = {
|
||||
class: "message_reaction",
|
||||
count: 1,
|
||||
count: 4,
|
||||
emoji_alt_code: false,
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
|
@ -805,11 +968,38 @@ test("view.update_existing_reaction (them)", () => {
|
|||
|
||||
reactions.view.update_existing_reaction(
|
||||
clean_reaction_object,
|
||||
{id: message_id},
|
||||
{
|
||||
id: message_id,
|
||||
reactions: [
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: alice.user_id,
|
||||
},
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: bob.user_id,
|
||||
},
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: cali.user_id,
|
||||
},
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: alexus.user_id,
|
||||
},
|
||||
],
|
||||
},
|
||||
alexus.user_id,
|
||||
);
|
||||
|
||||
assert.equal($reaction_count.text(), "4");
|
||||
assert.ok(!$our_reaction.hasClass("reacted"));
|
||||
assert.equal(
|
||||
$our_reaction.attr("aria-label"),
|
||||
|
@ -820,7 +1010,7 @@ test("view.update_existing_reaction (them)", () => {
|
|||
test("view.remove_reaction (me)", () => {
|
||||
const clean_reaction_object = {
|
||||
class: "message_reaction",
|
||||
count: 1,
|
||||
count: 2,
|
||||
emoji_alt_code: false,
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
|
@ -831,17 +1021,36 @@ test("view.remove_reaction (me)", () => {
|
|||
};
|
||||
const message_id = 505;
|
||||
|
||||
const $our_reaction = stub_reaction(message_id, "unicode_emoji,1f3b1");
|
||||
const $reaction_count = $.create("reaction-count-stub");
|
||||
$our_reaction.addClass("reacted");
|
||||
$our_reaction.set_find_results(".message_reaction_count", $reaction_count);
|
||||
const $message_reactions = stub_reaction(message_id, "unicode_emoji,1f3b1");
|
||||
$message_reactions.addClass("reacted");
|
||||
const $reaction_button = $.create("reaction-button-stub");
|
||||
$message_reactions.find = () => $reaction_button;
|
||||
|
||||
reactions.view.remove_reaction(clean_reaction_object, {id: message_id}, alice.user_id);
|
||||
reactions.view.remove_reaction(
|
||||
clean_reaction_object,
|
||||
{
|
||||
id: message_id,
|
||||
reactions: [
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: bob.user_id,
|
||||
},
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: cali.user_id,
|
||||
},
|
||||
],
|
||||
},
|
||||
alice.user_id,
|
||||
);
|
||||
|
||||
assert.equal($reaction_count.text(), "2");
|
||||
assert.ok(!$our_reaction.hasClass("reacted"));
|
||||
assert.ok(!$message_reactions.hasClass("reacted"));
|
||||
assert.equal(
|
||||
$our_reaction.attr("aria-label"),
|
||||
$message_reactions.attr("aria-label"),
|
||||
"translated: Bob van Roberts and Cali reacted with :8ball:",
|
||||
);
|
||||
});
|
||||
|
@ -860,18 +1069,30 @@ test("view.remove_reaction (them)", () => {
|
|||
};
|
||||
const message_id = 506;
|
||||
|
||||
const $our_reaction = stub_reaction(message_id, "unicode_emoji,1f3b1");
|
||||
const $reaction_count = $.create("reaction-count-stub");
|
||||
$our_reaction.addClass("reacted");
|
||||
$our_reaction.set_find_results(".message_reaction_count", $reaction_count);
|
||||
const $message_reactions = stub_reaction(message_id, "unicode_emoji,1f3b1");
|
||||
$message_reactions.addClass("reacted");
|
||||
const $reaction_button = $.create("reaction-button-stub");
|
||||
$message_reactions.find = () => $reaction_button;
|
||||
|
||||
$our_reaction.addClass("reacted");
|
||||
reactions.view.remove_reaction(clean_reaction_object, {id: message_id}, bob.user_id);
|
||||
reactions.view.remove_reaction(
|
||||
clean_reaction_object,
|
||||
{
|
||||
id: message_id,
|
||||
reactions: [
|
||||
{
|
||||
emoji_code: "1f3b1",
|
||||
emoji_name: "8ball",
|
||||
reaction_type: "unicode_emoji",
|
||||
user_id: alice.user_id,
|
||||
},
|
||||
],
|
||||
},
|
||||
bob.user_id,
|
||||
);
|
||||
|
||||
assert.equal($reaction_count.text(), "1");
|
||||
assert.ok($our_reaction.hasClass("reacted"));
|
||||
assert.ok($message_reactions.hasClass("reacted"));
|
||||
assert.equal(
|
||||
$our_reaction.attr("aria-label"),
|
||||
$message_reactions.attr("aria-label"),
|
||||
"translated: You (click to remove) reacted with :8ball:",
|
||||
);
|
||||
});
|
||||
|
@ -896,7 +1117,11 @@ test("view.remove_reaction (last person)", () => {
|
|||
$our_reaction.remove = () => {
|
||||
removed = true;
|
||||
};
|
||||
reactions.view.remove_reaction(clean_reaction_object, {id: message_id}, bob.user_id);
|
||||
reactions.view.remove_reaction(
|
||||
clean_reaction_object,
|
||||
{id: message_id, reactions: []},
|
||||
bob.user_id,
|
||||
);
|
||||
assert.ok(removed);
|
||||
});
|
||||
|
||||
|
|
|
@ -221,9 +221,9 @@ export function get_add_reaction_button(message_id) {
|
|||
return $add_button;
|
||||
}
|
||||
|
||||
export function set_reaction_count($reaction, count) {
|
||||
export function set_reaction_vote_text($reaction, vote_text) {
|
||||
const $count_element = $reaction.find(".message_reaction_count");
|
||||
$count_element.text(count);
|
||||
$count_element.text(vote_text);
|
||||
}
|
||||
|
||||
export function add_reaction(event) {
|
||||
|
@ -248,7 +248,7 @@ export function add_reaction(event) {
|
|||
|
||||
if (clean_reaction_object) {
|
||||
clean_reaction_object.user_ids.push(user_id);
|
||||
update_user_fields(clean_reaction_object);
|
||||
update_user_fields(clean_reaction_object, message.clean_reactions);
|
||||
view.update_existing_reaction(clean_reaction_object, message, user_id);
|
||||
} else {
|
||||
clean_reaction_object = make_clean_reaction({
|
||||
|
@ -260,6 +260,7 @@ export function add_reaction(event) {
|
|||
});
|
||||
|
||||
message.clean_reactions.set(local_id, clean_reaction_object);
|
||||
update_user_fields(clean_reaction_object, message.clean_reactions);
|
||||
view.insert_new_reaction(clean_reaction_object, message, user_id);
|
||||
}
|
||||
}
|
||||
|
@ -271,8 +272,6 @@ view.update_existing_reaction = function (clean_reaction_object, message, acting
|
|||
const local_id = get_local_reaction_id(clean_reaction_object);
|
||||
const $reaction = find_reaction(message.id, local_id);
|
||||
|
||||
set_reaction_count($reaction, clean_reaction_object.user_ids.length);
|
||||
|
||||
const new_label = generate_title(
|
||||
clean_reaction_object.emoji_name,
|
||||
clean_reaction_object.user_ids,
|
||||
|
@ -282,6 +281,8 @@ view.update_existing_reaction = function (clean_reaction_object, message, acting
|
|||
if (acting_user_id === page_params.user_id) {
|
||||
$reaction.addClass("reacted");
|
||||
}
|
||||
|
||||
update_vote_text_on_message(message);
|
||||
};
|
||||
|
||||
view.insert_new_reaction = function (clean_reaction_object, message, user_id) {
|
||||
|
@ -317,6 +318,8 @@ view.insert_new_reaction = function (clean_reaction_object, message, user_id) {
|
|||
// Now insert it before the add button.
|
||||
const $reaction_button_element = get_add_reaction_button(message.id);
|
||||
$new_reaction.insertBefore($reaction_button_element);
|
||||
|
||||
update_vote_text_on_message(message);
|
||||
};
|
||||
|
||||
export function remove_reaction(event) {
|
||||
|
@ -345,12 +348,13 @@ export function remove_reaction(event) {
|
|||
}
|
||||
|
||||
clean_reaction_object.user_ids = clean_reaction_object.user_ids.filter((id) => id !== user_id);
|
||||
if (clean_reaction_object.user_ids.length > 0) {
|
||||
update_user_fields(clean_reaction_object);
|
||||
} else {
|
||||
if (clean_reaction_object.user_ids.length === 0) {
|
||||
message.clean_reactions.delete(local_id);
|
||||
}
|
||||
|
||||
const should_display_reactors = check_should_display_reactors(message.clean_reactions);
|
||||
update_user_fields(clean_reaction_object, should_display_reactors);
|
||||
|
||||
view.remove_reaction(clean_reaction_object, message, user_id);
|
||||
}
|
||||
|
||||
|
@ -363,6 +367,7 @@ view.remove_reaction = function (clean_reaction_object, message, user_id) {
|
|||
// If this user was the only one reacting for this emoji, we simply
|
||||
// remove the reaction and exit.
|
||||
$reaction.remove();
|
||||
update_vote_text_on_message(message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -374,10 +379,11 @@ view.remove_reaction = function (clean_reaction_object, message, user_id) {
|
|||
clean_reaction_object.user_ids,
|
||||
);
|
||||
$reaction.attr("aria-label", new_label);
|
||||
set_reaction_count($reaction, reaction_count);
|
||||
if (user_id === page_params.user_id) {
|
||||
$reaction.removeClass("reacted");
|
||||
}
|
||||
|
||||
update_vote_text_on_message(message);
|
||||
};
|
||||
|
||||
export function get_emojis_used_by_user_for_message_id(message_id) {
|
||||
|
@ -412,6 +418,14 @@ export function set_clean_reactions(message) {
|
|||
*/
|
||||
|
||||
if (message.clean_reactions) {
|
||||
// Update display details for the reaction. In particular,
|
||||
// user_settings.display_emoji_reaction_users or the names of
|
||||
// the users appearing in the reaction may have changed since
|
||||
// this reaction was first rendered.
|
||||
const should_display_reactors = check_should_display_reactors(message.clean_reactions);
|
||||
for (const clean_reaction of message.clean_reactions.values()) {
|
||||
update_user_fields(clean_reaction, should_display_reactors);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -462,6 +476,15 @@ export function set_clean_reactions(message) {
|
|||
);
|
||||
}
|
||||
|
||||
// We do update_user_fields in a separate loop, because doing so
|
||||
// lets us avoid duplicating check_should_display_reactors to
|
||||
// determine whether to store in the vote_text field a count or
|
||||
// the names of reactors (users who reacted).
|
||||
const should_display_reactors = check_should_display_reactors(message.clean_reactions);
|
||||
for (const clean_reaction of message.clean_reactions.values()) {
|
||||
update_user_fields(clean_reaction, should_display_reactors);
|
||||
}
|
||||
|
||||
// We don't maintain message.reactions when users react to
|
||||
// messages we already have a copy of, so it's safest to delete it
|
||||
// after we've processed the reactions data for a message into the
|
||||
|
@ -479,14 +502,14 @@ function make_clean_reaction({local_id, user_ids, emoji_name, emoji_code, reacti
|
|||
clean_reaction_object.is_realm_emoji =
|
||||
clean_reaction_object.reaction_type === "realm_emoji" ||
|
||||
clean_reaction_object.reaction_type === "zulip_extra_emoji";
|
||||
|
||||
// Call update_user_fields last, so it can rely on
|
||||
// clean_reaction_object being otherwise fully populated.
|
||||
update_user_fields(clean_reaction_object);
|
||||
return clean_reaction_object;
|
||||
}
|
||||
|
||||
export function update_user_fields(clean_reaction_object) {
|
||||
export function update_user_fields(clean_reaction_object, should_display_reactors) {
|
||||
// update_user_fields needs to be called whenever the set of users
|
||||
// whor eacted on a message might have changed, including due to
|
||||
// upvote/downvotes on ANY reaction in the message, because those
|
||||
// can change the correct value of should_display_reactors to use.
|
||||
clean_reaction_object.count = clean_reaction_object.user_ids.length;
|
||||
clean_reaction_object.label = generate_title(
|
||||
clean_reaction_object.emoji_name,
|
||||
|
@ -497,4 +520,64 @@ export function update_user_fields(clean_reaction_object) {
|
|||
} else {
|
||||
clean_reaction_object.class = "message_reaction";
|
||||
}
|
||||
|
||||
clean_reaction_object.count = clean_reaction_object.user_ids.length;
|
||||
clean_reaction_object.label = generate_title(
|
||||
clean_reaction_object.emoji_name,
|
||||
clean_reaction_object.user_ids,
|
||||
);
|
||||
|
||||
// The vote_text field set here is used directly in the Handlebars
|
||||
// template for rendering (or rerendering!) a message.
|
||||
clean_reaction_object.vote_text = get_vote_text(clean_reaction_object, should_display_reactors);
|
||||
}
|
||||
|
||||
export function get_vote_text(clean_reaction_object, should_display_reactors) {
|
||||
if (should_display_reactors) {
|
||||
return comma_separated_usernames(clean_reaction_object.user_ids);
|
||||
}
|
||||
return `${clean_reaction_object.user_ids.length}`;
|
||||
}
|
||||
|
||||
function check_should_display_reactors(cleaned_reactions) {
|
||||
if (!user_settings.display_emoji_reaction_users) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let total_reactions = 0;
|
||||
for (const r of cleaned_reactions.values()) {
|
||||
// r.count is not yet initialized when this is called during
|
||||
// set_clean_reactions.
|
||||
total_reactions += r.count || r.user_ids.length;
|
||||
}
|
||||
return total_reactions <= 3;
|
||||
}
|
||||
|
||||
function comma_separated_usernames(user_list) {
|
||||
const usernames = people.get_display_full_names(user_list);
|
||||
const current_user_has_reacted = user_list.includes(page_params.user_id);
|
||||
|
||||
if (current_user_has_reacted) {
|
||||
const current_user_index = user_list.indexOf(page_params.user_id);
|
||||
usernames[current_user_index] = $t({
|
||||
defaultMessage: "You",
|
||||
});
|
||||
}
|
||||
const comma_separated_usernames = usernames.join(", ");
|
||||
return comma_separated_usernames;
|
||||
}
|
||||
|
||||
export function update_vote_text_on_message(message) {
|
||||
// Because whether we display a count or the names of reacting
|
||||
// users depends on total reactions on the message, we need to
|
||||
// recalculate this whenever adjusting reaction rendering on a
|
||||
// message.
|
||||
const cleaned_reactions = get_message_reactions(message);
|
||||
const should_display_reactors = check_should_display_reactors(cleaned_reactions);
|
||||
for (const [reaction, clean_reaction] of message.clean_reactions.entries()) {
|
||||
const reaction_elem = find_reaction(message.id, clean_reaction.local_id);
|
||||
const vote_text = get_vote_text(clean_reaction, should_display_reactors);
|
||||
message.clean_reactions.get(reaction).vote_text = vote_text;
|
||||
set_reaction_vote_text(reaction_elem, vote_text);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
{{else}}
|
||||
<div class="emoji emoji-{{this.emoji_code}}"></div>
|
||||
{{/if}}
|
||||
<div class="message_reaction_count">{{this.count}}</div>
|
||||
<div class="message_reaction_count">{{this.vote_text}}</div>
|
||||
</div>
|
||||
|
|
|
@ -74,13 +74,11 @@
|
|||
label=settings_label.translate_emoticons
|
||||
prefix=prefix}}
|
||||
|
||||
{{#if page_params.development_environment }}
|
||||
{{> settings_checkbox
|
||||
setting_name="display_emoji_reaction_users"
|
||||
is_checked=settings_object.display_emoji_reaction_users
|
||||
label=settings_label.display_emoji_reaction_users
|
||||
prefix=prefix}}
|
||||
{{/if}}
|
||||
|
||||
<div class="input-group">
|
||||
<label class="title">{{t "User list style" }}</label>
|
||||
|
|
Loading…
Reference in New Issue