diff --git a/frontend_tests/node_tests/user_status.js b/frontend_tests/node_tests/user_status.js index 97afb1130b..ccc643bafc 100644 --- a/frontend_tests/node_tests/user_status.js +++ b/frontend_tests/node_tests/user_status.js @@ -8,6 +8,23 @@ const blueslip = require("../zjsunit/zblueslip"); const channel = mock_esm("../../static/js/channel"); const user_status = zrequire("user_status"); +const emoji_codes = zrequire("../generated/emoji/emoji_codes.json"); +const emoji = zrequire("../shared/js/emoji"); +const {page_params} = require("../zjsunit/zpage_params"); + +const emoji_params = { + realm_emoji: { + 991: { + id: "991", + name: "realm_emoji", + source_url: "/url/for/991", + deactivated: false, + }, + }, + emoji_codes, +}; + +emoji.initialize(emoji_params); function initialize() { const params = { @@ -15,11 +32,115 @@ function initialize() { 1: {away: true, status_text: "in a meeting"}, 2: {away: true}, 3: {away: true}, + 4: {emoji_name: "smiley", emoji_code: "1f603", reaction_type: "unicode_emoji"}, }, }; user_status.initialize(params); } +run_test("get_extra_emoji_info", () => { + page_params.emojiset = "text"; + + let emoji_info = {}; + + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, {}); + + emoji_info = {emoji_name: "smile"}; + + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, { + emoji_name: "smile", + emoji_alt_code: true, + }); + + page_params.emojiset = "google"; + + // Test adding an unicode_emoji. + emoji_info = {emoji_name: "smile", emoji_code: "1f642", reaction_type: "unicode_emoji"}; + + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, { + emoji_name: "smile", + emoji_alt_code: false, + reaction_type: "unicode_emoji", + emoji_code: "1f642", + }); + + // Test adding an unicode_emoji's name only. + // It should fill in other details automatically. + emoji_info = {emoji_name: "smile"}; + + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, { + emoji_name: "smile", + emoji_alt_code: false, + reaction_type: "unicode_emoji", + emoji_code: "1f642", + }); + + // Test adding zulip emoji. + emoji_info = {emoji_name: "zulip", emoji_code: "zulip", reaction_type: "zulip_extra_emoji"}; + + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, { + emoji_name: "zulip", + emoji_alt_code: false, + reaction_type: "zulip_extra_emoji", + emoji_code: "zulip", + url: "/static/generated/emoji/images/emoji/unicode/zulip.png", + }); + + // Test adding zulip emoji's name only. + emoji_info = {emoji_name: "zulip"}; + + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, { + emoji_name: "zulip", + emoji_alt_code: false, + reaction_type: "zulip_extra_emoji", + emoji_code: "zulip", + url: "/static/generated/emoji/images/emoji/unicode/zulip.png", + }); + + // Test adding realm_emoji emoji. + emoji_info = { + emoji_name: "realm_emoji", + emoji_code: "991", + reaction_type: "realm_emoji", + }; + + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, { + emoji_name: "realm_emoji", + emoji_alt_code: false, + reaction_type: "realm_emoji", + emoji_code: "991", + url: "/url/for/991", + }); + + // Test adding only realm_emoji's name only. + // It should fill in other details automatically. + emoji_info = { + emoji_name: "realm_emoji", + }; + + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, { + emoji_name: "realm_emoji", + emoji_alt_code: false, + reaction_type: "realm_emoji", + emoji_code: "991", + url: "/url/for/991", + }); + + // Test sending an unknown emoji. + emoji_info = {emoji_name: "unknown-emoji"}; + blueslip.expect("warn", "Bad emoji name: " + emoji_info.emoji_name); + emoji_info = user_status.get_emoji_info(emoji_info); + assert.deepEqual(emoji_info, {}); +}); + run_test("basics", () => { initialize(); assert.ok(user_status.is_away(2)); diff --git a/static/js/user_status.js b/static/js/user_status.js index bd42f85b7e..525283640e 100644 --- a/static/js/user_status.js +++ b/static/js/user_status.js @@ -1,5 +1,8 @@ +import * as emoji from "../shared/js/emoji"; + import * as blueslip from "./blueslip"; import * as channel from "./channel"; +import {page_params} from "./page_params"; const away_user_ids = new Set(); const user_info = new Map(); @@ -42,6 +45,44 @@ export function revoke_away(user_id) { away_user_ids.delete(user_id); } +// This function will add missing/extra parameters to the emoji info object, +// that would need by template to render an emoji. +export function get_emoji_info(emoji_info) { + // To call this function you must pass at least an emoji name. + if (!emoji_info || !emoji_info.emoji_name) { + return {}; + } + + const status_emoji_info = {...emoji_info}; + + status_emoji_info.emoji_alt_code = page_params.emojiset === "text"; + if (status_emoji_info.emoji_alt_code) { + return status_emoji_info; + } + + if (emoji.active_realm_emojis.has(emoji_info.emoji_name)) { + if (!emoji_info.reaction_type) { + if (emoji_info.emoji_name === "zulip") { + status_emoji_info.reaction_type = "zulip_extra_emoji"; + } else { + status_emoji_info.reaction_type = "realm_emoji"; + } + } + const more_emoji_info = emoji.active_realm_emojis.get(emoji_info.emoji_name); + status_emoji_info.emoji_code = emoji_info.emoji_code || more_emoji_info.id; + status_emoji_info.url = more_emoji_info.emoji_url; + } else { + const codepoint = emoji.get_emoji_codepoint(emoji_info.emoji_name); + if (codepoint === undefined) { + blueslip.warn("Bad emoji name: " + emoji_info.emoji_name); + return {}; + } + status_emoji_info.reaction_type = emoji_info.reaction_type || "unicode_emoji"; + status_emoji_info.emoji_code = emoji_info.emoji_code || codepoint; + } + return status_emoji_info; +} + export function is_away(user_id) { return away_user_ids.has(user_id); }