nolanlawson / emoji-picker-element

A lightweight emoji picker for the modern web
https://nolanlawson.github.io/emoji-picker-element/
Apache License 2.0
1.48k stars 83 forks source link

Alternative emoji support level check? #378

Closed mary-ext closed 4 months ago

mary-ext commented 10 months ago

Heya, I've been writing an emoji picker of my own and was looking into multiple implementations that checks if a given emoji is supported by the system/fonts a user is using

It seems that GitLab's implementation of this supports handling compound emojis as well, which might solve emoji-picker-element's issue of having two code paths to check for support (non-compound for the general Unicode support level, and compound for the rest)

I've adapted a generalized version of the implementation and it seems to handle Twemoji/Noto Color Emoji rather well, however I'm only able to test this on Linux (and only on Firefox at the moment)

Could we try to see if this works across platforms? It could very well simplify the way compound emojis are being done on emoji-picker-element.

Edit 1: Given the relatively small-ish amount of compound emojis needing to be checked, we could just move it as part of the async query functions, in my emoji picker this doesn't seem to be very taxing if one were to browse around the picker

Edit 2: I've seen this blog post and it mentioned that it doesn't work quite well on black and white emojis, but I've tested this with the black bird emoji that was introduced in Unicode 15 and it seems to work just fine. Twemoji doesn't support it, it successfully filtered it out. Noto Color Emoji support it, it passed.

nolanlawson commented 10 months ago

This is interesting, so basically you have a technique that can use Canvas to identify compound emojis?

This would definitely simplify the code path for detecting emoji support in emoji-picker-element, but I have some concerns around performance. The current technique is highly performance-tuned:

  1. Step 1: quick filter using one representative emoji from each version (only 12 emojis need to be rendered) (uses canvas)
  2. Step 2: render everything normally
  3. Step 3: in a requestAnimationFrame to avoid actually rendering to the screen, check the emoji widths of the characters we already rendered
  4. Step 4: filter and re-render if anything needs to be filtered

With the system you're proposing, we would check for emoji support in one pass, but this would (AIUI) require rendering all emoji in both canvas and the DOM, potentially doubling the rendering cost. We can mitigate this as you say by only checking known compound emoji, but this requires us keeping a list of those somewhere (or a regex heuristic or something), which adds to the code complexity and might miss some. Plus, we would still be rendering all those emoji twice.

Maybe I am overthinking it, but I kind of like the current approach since it's highly performance-optimized, even if the code is a bit ugly.