diff --git a/appiumtests/emojiertest.py b/appiumtests/emojiertest.py index c5e274fb7b..fe7e39c4df 100755 --- a/appiumtests/emojiertest.py +++ b/appiumtests/emojiertest.py @@ -67,6 +67,13 @@ class EmojierTest(unittest.TestCase): self.driver.find_element(AppiumBy.NAME, "Recent").click() self.driver.find_element(AppiumBy.NAME, "grinning face") + def test_3_select_variant(self) -> None: + self.driver.find_element(AppiumBy.NAME, "All").click() + self.driver.find_element(AppiumBy.NAME, "Search").send_keys("handshake") + self.driver.find_element(AppiumBy.NAME, "Select Variant of \"handshake\"").click() + self.driver.find_element(AppiumBy.NAME, "handshake: light skin tone, medium skin tone").click() + time.sleep(1) + self.assertEqual(self.driver.get_clipboard_text(), "šŸ«±šŸ»ā€šŸ«²šŸ½") if __name__ == '__main__': unittest.main() diff --git a/emojier/data/en.dict b/emojier/data/en.dict index 059424f9a6..b265632762 100644 Binary files a/emojier/data/en.dict and b/emojier/data/en.dict differ diff --git a/emojier/data/update-emoji-data.py b/emojier/data/update-emoji-data.py index 600195b06d..42723bc8e4 100755 --- a/emojier/data/update-emoji-data.py +++ b/emojier/data/update-emoji-data.py @@ -24,6 +24,21 @@ CLDR_URL = f"https://unicode.org/Public/cldr/{CLDR_VERSION}/{CLDR_FILE}" CLDR_ANNOTATIONS_DIR = "common/annotations" CLDR_ANNOTATIONS_DERIVED_DIR = "common/annotationsDerived" +SKIN_TONES = { + b"light skin tone", + b"medium-light skin tone", + b"medium skin tone", + b"medium-dark skin tone", + b"dark skin tone", +} + +GENDER_SYMBOLS = { + "\u200Dā™‚ļø", + "šŸ‘Ø", + "\u200Dā™€ļø", + "šŸ‘©", +} + class EmojiAnnotation(object): def __init__(self): self.description = "" @@ -35,6 +50,42 @@ class EmojiParser(object): self.categoryNames = [] self.emojis = collections.OrderedDict() + self.descriptionEmojiMap = {} + self.skinToneMap = collections.defaultdict(list) + self.genderMap = collections.defaultdict(lambda: [None, None, None]) + self.genderAndSkinToneVariants = set() + + def addToGenderMap(self, emoji): + isMale = "šŸ‘Ø" in emoji or "\u200Dā™‚ļø" in emoji + isFemale = "šŸ‘©" in emoji or "\u200Dā™€ļø" in emoji + + if isMale and isFemale: + genderIndex = 0 + elif isMale: + genderIndex = 1 + else: + genderIndex = 2 + + neutralEmoji = emoji.replace("\u200Dā™‚ļø", "") + neutralEmoji = neutralEmoji.replace("šŸ‘Ø", "šŸ§‘") + neutralEmoji = neutralEmoji.replace("\u200Dā™€ļø", "") + neutralEmoji = neutralEmoji.replace("šŸ‘©", "šŸ§‘") + + if neutralEmoji not in self.emojis: + return + + self.genderMap[neutralEmoji][genderIndex] = emoji + self.genderAndSkinToneVariants.add(emoji) + + def getSkinToneVariantsDict(self, emoji): + if emoji is None: + return {} + + skinToneVariants = {emoji: self.emojis[emoji]} + for variant in self.skinToneMap[emoji]: + skinToneVariants[variant] = self.emojis[variant] + return skinToneVariants + def parseEmojiTest(self, emojiTestData): descriptionMapping = dict() currentGroup = 0; @@ -69,6 +120,11 @@ class EmojiParser(object): if status == b"fully-qualified": self.emojis[emoji] = currentGroup descriptionMapping[description] = emoji + + # description format: "version emoji name: modifiers" + versionNameDelimiter = description.index(b" ") + descriptionWithoutVersion = description[versionNameDelimiter+1:] + self.descriptionEmojiMap[descriptionWithoutVersion] = emoji else: fullyQualified = descriptionMapping.get(description, None); if fullyQualified: @@ -76,6 +132,45 @@ class EmojiParser(object): except e: pass + for description, emoji in self.descriptionEmojiMap.items(): + # description format: "emoji name: modifier 1, modifier 2, ..., modifier n" + nameAndModifiers = description.split(b": ") + if len(nameAndModifiers) == 2: + name, modifiers = nameAndModifiers + + if any(skinTone in modifiers for skinTone in SKIN_TONES): + modifiers = modifiers.split(b", ") + modifiersWithoutSkinTone = b", ".join(mod for mod in modifiers if mod not in SKIN_TONES and mod != b"person") + descriptionWithoutSkinTone = name + (b": " + modifiersWithoutSkinTone if modifiersWithoutSkinTone else b"") + + try: + neutralEmoji = self.descriptionEmojiMap[descriptionWithoutSkinTone] + self.skinToneMap[neutralEmoji].append(emoji) + self.genderAndSkinToneVariants.add(emoji) + except: + pass + elif any(gender in emoji for gender in GENDER_SYMBOLS): + self.addToGenderMap(emoji) + elif any(gender in emoji for gender in GENDER_SYMBOLS): + self.addToGenderMap(emoji) + + self.genderMap["šŸ§‘ā€šŸ¤ā€šŸ§‘"] = ["šŸ‘«", "šŸ‘¬", "šŸ‘­"] + self.genderAndSkinToneVariants.update(["šŸ‘«", "šŸ‘¬", "šŸ‘­"]) + + sortedEmojis = {} + for emoji, group in self.emojis.items(): + if emoji in self.genderAndSkinToneVariants: + pass + elif emoji in self.genderMap: + for genderEmoji in [emoji] + self.genderMap[emoji]: + sortedEmojis.update(self.getSkinToneVariantsDict(genderEmoji)) + elif emoji in self.skinToneMap: + sortedEmojis.update(self.getSkinToneVariantsDict(emoji)) + else: + sortedEmojis[emoji] = group + + self.emojis = sortedEmojis + def parseCldr(self, cldrList): annotations = dict() for data in cldrList: