From 771cef8e80b096aa79bfe78c1eaa272d90fd1861 Mon Sep 17 00:00:00 2001 From: infi Date: Wed, 29 Jul 2026 05:21:04 +0200 Subject: [PATCH] fix: numbers are not emoji contrary to what unicode claims --- .../chat/stoat/internals/text/Gigamoji.kt | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/chat/stoat/internals/text/Gigamoji.kt b/app/src/main/java/chat/stoat/internals/text/Gigamoji.kt index 8b429a71..5c346cea 100644 --- a/app/src/main/java/chat/stoat/internals/text/Gigamoji.kt +++ b/app/src/main/java/chat/stoat/internals/text/Gigamoji.kt @@ -2,6 +2,11 @@ package chat.stoat.internals.text private val STRING_IS_CUSTOM_EMOTES_REGEX = Regex("(?::[0-9A-HJKMNP-TV-Z]{26}:|\\s)+") private val CUSTOM_EMOTE_REGEX = Regex(":[0-9A-HJKMNP-TV-Z]{26}:") +private const val VARIATION_SELECTOR_16 = 0xFE0F +private const val COMBINING_ENCLOSING_KEYCAP = 0x20E3 + +private fun isKeycapBase(codepoint: Int): Boolean = + codepoint == '#'.code || codepoint == '*'.code || codepoint in '0'.code..'9'.code sealed class GigamojiState { object None : GigamojiState() @@ -19,12 +24,28 @@ object Gigamoji { val content = unfilteredContent.replace(STRING_IS_CUSTOM_EMOTES_REGEX, "") if (content.isBlank()) return 0 + val codepoints = content.codePoints().toArray() var count = 0 var lastWasZwj = false - for (codepoint in content.codePoints()) { + var index = 0 + while (index < codepoints.size) { + val codepoint = codepoints[index] when { Character.isWhitespace(codepoint) -> lastWasZwj = false codepoint == 0x200D -> lastWasZwj = true + isKeycapBase(codepoint) -> { + val selectorOffset = + if (codepoints.getOrNull(index + 1) == VARIATION_SELECTOR_16) 1 else 0 + if (codepoints.getOrNull(index + selectorOffset + 1) != + COMBINING_ENCLOSING_KEYCAP + ) { + return null + } + + if (!lastWasZwj) count++ + lastWasZwj = false + index += selectorOffset + 1 + } codepoint == 0xFE0F || codepoint == 0xFE0E || codepoint == 0x20E3 -> Unit codepoint in PUA_MIN..PUA_MAX -> Unit codepoint in 0x1F3FB..0x1F3FF -> lastWasZwj = false @@ -34,6 +55,7 @@ object Gigamoji { } else -> return null } + index++ } return count }