mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 14:03:30 +00:00 
			
		
		
		
	notifications: Render emoji in desktop notifications.
In desktop notifications, we no longer display an emoji's status code. Instead, we show the corresponding Unicode emoji to render it properly in desktop notifications. For custom emojis, we continue to display their name. Fixes #30598. Co-authored-by: Tanmay Kumar <tnmdotkr@gmail.com> Co-authored-by: Tim Abbott <tabbott@zulip.com>
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							a2c0d2d385
						
					
				
				
					commit
					d3c20f0b25
				
			@@ -40,7 +40,7 @@ function get_notification_content(message: Message | TestNotificationMessage): s
 | 
				
			|||||||
    let content;
 | 
					    let content;
 | 
				
			||||||
    // Convert the content to plain text, replacing emoji with their alt text
 | 
					    // Convert the content to plain text, replacing emoji with their alt text
 | 
				
			||||||
    const $content = $("<div>").html(message.content);
 | 
					    const $content = $("<div>").html(message.content);
 | 
				
			||||||
    ui_util.replace_emoji_with_text($content);
 | 
					    ui_util.convert_unicode_eligible_emoji_to_unicode($content);
 | 
				
			||||||
    ui_util.change_katex_to_raw_latex($content);
 | 
					    ui_util.change_katex_to_raw_latex($content);
 | 
				
			||||||
    ui_util.potentially_collapse_quotes($content);
 | 
					    ui_util.potentially_collapse_quotes($content);
 | 
				
			||||||
    spoilers.hide_spoilers_in_notification($content);
 | 
					    spoilers.hide_spoilers_in_notification($content);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,14 +22,62 @@ export function place_caret_at_end(el: HTMLElement): void {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function replace_emoji_with_text($element: JQuery): void {
 | 
					function extract_emoji_code_from_class(emoji_class_string: string | undefined): string | undefined {
 | 
				
			||||||
 | 
					    if (emoji_class_string === undefined) {
 | 
				
			||||||
 | 
					        return undefined;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const classes = emoji_class_string.split(/\s+/);
 | 
				
			||||||
 | 
					    const regex = /^emoji-([0-9a-fA-F-]+)$/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const cls of classes) {
 | 
				
			||||||
 | 
					        const match = regex.exec(cls);
 | 
				
			||||||
 | 
					        if (match) {
 | 
				
			||||||
 | 
					            return match?.[1] ?? undefined;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return undefined;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function convert_emoji_element_to_unicode($emoji_elt: JQuery): string {
 | 
				
			||||||
 | 
					    // This is a custom emoji, we do not have corresponding emoji
 | 
				
			||||||
 | 
					    // unicode for these so we return original markdown.
 | 
				
			||||||
 | 
					    if ($emoji_elt.is("img")) {
 | 
				
			||||||
 | 
					        return $emoji_elt.attr("alt") ?? "";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const emoji_class_string = $emoji_elt.attr("class");
 | 
				
			||||||
 | 
					    const emoji_code_hex_string = extract_emoji_code_from_class(emoji_class_string);
 | 
				
			||||||
 | 
					    if (emoji_code_hex_string === undefined) {
 | 
				
			||||||
 | 
					        return $emoji_elt.text();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const emoji_code_parts = emoji_code_hex_string.split("-");
 | 
				
			||||||
 | 
					    const emoji_unicode = emoji_code_parts
 | 
				
			||||||
 | 
					        .map((emoji_code) => {
 | 
				
			||||||
 | 
					            const emoji_code_int = Number.parseInt(emoji_code, 16);
 | 
				
			||||||
 | 
					            // Validate the parameter passed to String.fromCodePoint() (here, emoji_code_int).
 | 
				
			||||||
 | 
					            // "An integer between 0 and 0x10FFFF (inclusive) representing a Unicode code point."
 | 
				
			||||||
 | 
					            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint
 | 
				
			||||||
 | 
					            // for details.
 | 
				
			||||||
 | 
					            if (
 | 
				
			||||||
 | 
					                Number.isNaN(emoji_code_int) ||
 | 
				
			||||||
 | 
					                !(emoji_code_int >= 0 && emoji_code_int <= 0x10ffff)
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                blueslip.error("Invalid unicode codepoint for emoji", {emoji_code_int});
 | 
				
			||||||
 | 
					                return $emoji_elt.text();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return String.fromCodePoint(emoji_code_int);
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .join("");
 | 
				
			||||||
 | 
					    return emoji_unicode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function convert_unicode_eligible_emoji_to_unicode($element: JQuery): void {
 | 
				
			||||||
    $element
 | 
					    $element
 | 
				
			||||||
        .find(".emoji")
 | 
					        .find(".emoji")
 | 
				
			||||||
        .text(function () {
 | 
					        .text(function () {
 | 
				
			||||||
            if ($(this).is("img")) {
 | 
					            return convert_emoji_element_to_unicode($(this));
 | 
				
			||||||
                return $(this).attr("alt") ?? "";
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return $(this).text();
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .contents()
 | 
					        .contents()
 | 
				
			||||||
        .unwrap();
 | 
					        .unwrap();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,3 +67,15 @@ run_test("potentially_collapse_quotes", ({override_rewire}) => {
 | 
				
			|||||||
        expected_texts,
 | 
					        expected_texts,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					run_test("replace_emoji_name_with_emoji_unicode", () => {
 | 
				
			||||||
 | 
					    const $emoji = $.create("span").attr("class", "emoji emoji-1f419");
 | 
				
			||||||
 | 
					    $emoji.is = () => false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const octopus_emoji = "🐙";
 | 
				
			||||||
 | 
					    assert.equal(octopus_emoji, ui_util.convert_emoji_element_to_unicode($emoji));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $emoji.attr("class", "emoji emoji-1f468-200d-1f373");
 | 
				
			||||||
 | 
					    const man_cook_emoji = "👨🍳";
 | 
				
			||||||
 | 
					    assert.equal(man_cook_emoji, ui_util.convert_emoji_element_to_unicode($emoji));
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user