user_status: Fix status emoji handling of deactivated custom emoji.

Previously, if a user had a realm emoji set as their status emoji and
someone deleted the realm emoji, the app would fail to initialize,
because of the error we throw from `./shared/js/emoji.js`.

This commit fixes this by just displaying the deactivated emoji,
similar to how we do when realm_emoji used as reactions are deleted.

As part of the fix, we add a function get_emoji_details_for_rendering,
which duplicates some of the logic used in `reactions.js`, we can
refactor to remove the duplication in `reactions.js` in future
commits.

Note that the following behaviour is a part of our design:
If a user sets their emoji to a particular realm emoji, say for
example "octo-ninja", and "octo-ninja" was then deleted, and a new
emoji was added with the name "octo-ninja", the user's status emoji
would change to show the new emoji instead of the deleted emoji.

Also note that in the `user_status.js` node test, we were able to
change the name for the 991 realm_emoji because it had not been
previously used anywhere in the test (possibly added as just a copy
paste artifact?).

Fixes: #20274.

emoji: Use reaction_type parameter to analyze emoji.
This commit is contained in:
YashRE42 2021-11-20 14:44:52 +05:30
parent 1f8b7b7d8d
commit 3d86267041
4 changed files with 98 additions and 12 deletions

View File

@ -39,7 +39,6 @@ mock_esm("../../static/js/stream_popover", {
const people = zrequire("people");
const user_status = zrequire("user_status");
const message_edit = zrequire("message_edit");
const emoji = zrequire("../shared/js/emoji");
// Bypass some scary code that runs when we import the module.
const popovers = with_field($.fn, "popover", noop, () => zrequire("popovers"));
@ -114,7 +113,6 @@ function test_ui(label, f) {
test_ui("sender_hover", ({override, mock_template}) => {
page_params.is_spectator = false;
override($.fn, "popover", noop);
override(emoji, "get_emoji_details_by_name", noop);
const selection = ".sender_name, .sender_name-in-status, .inline_profile_picture";
const handler = $("#main_div").get_on_handler("click", selection);

View File

@ -16,10 +16,18 @@ const emoji_params = {
realm_emoji: {
991: {
id: "991",
name: "realm_emoji",
name: "example_realm_emoji",
source_url: "/url/for/991",
still_url: "/url/still/991",
deactivated: false,
},
992: {
id: "992",
name: "deactivated_realm_emoji",
source_url: "/url/for/992",
still_url: "/url/still/992",
deactivated: true,
},
},
emoji_codes,
};
@ -33,6 +41,11 @@ function initialize() {
2: {away: true},
3: {away: true},
4: {emoji_name: "smiley", emoji_code: "1f603", reaction_type: "unicode_emoji"},
5: {
emoji_name: "deactivated_realm_emoji",
emoji_code: "992",
reaction_type: "realm_emoji",
},
},
};
user_status.initialize(params);
@ -40,6 +53,31 @@ function initialize() {
run_test("basics", () => {
initialize();
assert.deepEqual(user_status.get_status_emoji(5), {
emoji_code: "992",
emoji_name: "deactivated_realm_emoji",
reaction_type: "realm_emoji",
url: "/url/for/992",
still_url: "/url/still/992",
});
user_status.set_status_emoji({
user_id: 5,
emoji_code: "991",
emoji_name: "example_realm_emoji",
reaction_type: "realm_emoji",
});
assert.deepEqual(user_status.get_status_emoji(5), {
emoji_alt_code: false,
emoji_code: "991",
emoji_name: "example_realm_emoji",
reaction_type: "realm_emoji",
still_url: "/url/still/991",
url: "/url/for/991",
});
assert.ok(user_status.is_away(2));
assert.ok(!user_status.is_away(99));
@ -73,7 +111,6 @@ run_test("basics", () => {
emoji_name: "smiley",
emoji_code: "1f603",
reaction_type: "unicode_emoji",
// Extra parameters that were added by `emoji.get_emoji_details_by_name`
emoji_alt_code: false,
});
@ -135,4 +172,31 @@ run_test("defensive checks", () => {
blueslip.expect("error", "need ints for user_id", 2);
user_status.set_away("string");
user_status.revoke_away("string");
assert.throws(
() =>
user_status.set_status_emoji({
user_id: 5,
emoji_name: "emoji",
// no status code or reaction type.
}),
{
name: "Error",
message: "Invalid params.",
},
);
assert.throws(
() =>
user_status.set_status_emoji({
user_id: 5,
reaction_type: "realm_emoji",
emoji_name: "does_not_exist",
emoji_code: "fake_code",
}),
{
name: "Error",
message: "Cannot find realm emoji for code 'fake_code'.",
},
);
});

View File

@ -77,11 +77,12 @@ export function set_status_emoji(opts) {
}
user_status_emoji_info.set(opts.user_id, {
emoji_name: opts.emoji_name,
emoji_code: opts.emoji_code,
reaction_type: opts.reaction_type,
emoji_alt_code: user_settings.emojiset === "text",
...emoji.get_emoji_details_by_name(opts.emoji_name),
...emoji.get_emoji_details_for_rendering({
emoji_name: opts.emoji_name,
emoji_code: opts.emoji_code,
reaction_type: opts.reaction_type,
}),
});
}
@ -104,10 +105,7 @@ export function initialize(params) {
if (dct.emoji_name) {
user_status_emoji_info.set(user_id, {
emoji_name: dct.emoji_name,
emoji_code: dct.emoji_code,
reaction_type: dct.reaction_type,
...emoji.get_emoji_details_by_name(dct.emoji_name),
...emoji.get_emoji_details_for_rendering(dct),
});
}
}

View File

@ -218,6 +218,32 @@ export function get_emoji_details_by_name(emoji_name) {
return emoji_info;
}
export function get_emoji_details_for_rendering(opts) {
if (!opts.emoji_name || !opts.emoji_code || !opts.reaction_type) {
throw new Error("Invalid params.");
}
if (opts.reaction_type !== "unicode_emoji") {
const realm_emoji = all_realm_emojis.get(opts.emoji_code);
if (!realm_emoji) {
throw new Error(`Cannot find realm emoji for code '${opts.emoji_code}'.`);
}
return {
url: realm_emoji.emoji_url,
still_url: realm_emoji.still_url,
emoji_name: opts.emoji_name,
emoji_code: opts.emoji_code,
reaction_type: opts.reaction_type,
};
}
// else
return {
emoji_name: opts.emoji_name,
emoji_code: opts.emoji_code,
reaction_type: opts.reaction_type,
};
}
export function initialize(params) {
emoji_codes = params.emoji_codes;