feat: fix skin tone picker, show more emoji
This commit is contained in:
parent
db39522bbb
commit
584ce90b64
|
|
@ -106,24 +106,48 @@ class EmojiImpl {
|
||||||
val category =
|
val category =
|
||||||
UnicodeEmojiSection.entries.find { it.googleName == group.group } ?: continue
|
UnicodeEmojiSection.entries.find { it.googleName == group.group } ?: continue
|
||||||
list.add(EmojiPickerItem.Section(Category.UnicodeEmojiCategory(category)))
|
list.add(EmojiPickerItem.Section(Category.UnicodeEmojiCategory(category)))
|
||||||
list.addAll(
|
list.addAll(group.emoji.flatMap { emoji -> emojiToPickerItems(emoji) })
|
||||||
group.emoji.map { emoji ->
|
|
||||||
EmojiPickerItem.UnicodeEmoji(
|
|
||||||
emoji.base.joinToString("") { String(Character.toChars(it.toInt())) },
|
|
||||||
emoji.alternates.any { alternate ->
|
|
||||||
alternate.any { codepoint ->
|
|
||||||
codepoint in 0x1F3FB..0x1F3FF
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emoji.alternates
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun emojiToPickerItems(emoji: Emoji): List<EmojiPickerItem.UnicodeEmoji> {
|
||||||
|
val items = mutableListOf<EmojiPickerItem.UnicodeEmoji>()
|
||||||
|
|
||||||
|
items.add(
|
||||||
|
EmojiPickerItem.UnicodeEmoji(
|
||||||
|
emoji.base.joinToString("") { String(Character.toChars(it.toInt())) },
|
||||||
|
emoji.alternates.any { alternate ->
|
||||||
|
alternate.any { codepoint -> codepoint in 0x1F3FB..0x1F3FF }
|
||||||
|
},
|
||||||
|
emoji.alternates
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Non-skintone alternates (like gender variants) as separate picker items.
|
||||||
|
// Technically this breaks the Google metadata's assumption of 9 items per row.
|
||||||
|
// So far, this has not caused issues.
|
||||||
|
val nonSkintoneAlts = emoji.alternates.filter { alt ->
|
||||||
|
alt.none { cp -> cp in 0x1F3FB..0x1F3FF } && alt != emoji.base
|
||||||
|
}
|
||||||
|
for (nonSkintoneAlt in nonSkintoneAlts) {
|
||||||
|
val skintoneVariants = emoji.alternates.filter { alt ->
|
||||||
|
alt.any { cp -> cp in 0x1F3FB..0x1F3FF } &&
|
||||||
|
alt.filter { cp -> cp !in 0x1F3FB..0x1F3FF } == nonSkintoneAlt
|
||||||
|
}
|
||||||
|
items.add(
|
||||||
|
EmojiPickerItem.UnicodeEmoji(
|
||||||
|
nonSkintoneAlt.joinToString("") { String(Character.toChars(it.toInt())) },
|
||||||
|
skintoneVariants.isNotEmpty(),
|
||||||
|
skintoneVariants
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a map of category to start and end index of the category in the flat picker list
|
* Returns a map of category to start and end index of the category in the flat picker list
|
||||||
* Impl
|
* Impl
|
||||||
|
|
@ -183,15 +207,12 @@ class EmojiImpl {
|
||||||
): String {
|
): String {
|
||||||
if (!item.hasSkinTones || skinType == FitzpatrickSkinTone.None) return item.character
|
if (!item.hasSkinTones || skinType == FitzpatrickSkinTone.None) return item.character
|
||||||
|
|
||||||
// HACK: We simply find the modifier version from metadata that
|
val targetModifier = skinType.modifierCodepoint!!.toLong()
|
||||||
// contains the skin tone modifier codepoint.
|
// Pick the alternate that carries exactly one Fitzpatrick modifier and it is the target.
|
||||||
val modifier = item.alternates.maxByOrNull { alternate ->
|
// This avoids selecting multi-skintone combo alternates (e.g. 🫱🏻🫲🏼) when the user
|
||||||
// HACK HACK: We find the alternate with the most frequency of our skin tone modifier.
|
// only wants the simple single-tone variant (e.g. 🤝🏼).
|
||||||
// This is because some emoji have multiple skin tone modifier and we are taking the
|
val modifier = item.alternates.firstOrNull { alternate ->
|
||||||
// easy way here by only allowing a single skin tone change. This is not ideal.
|
alternate.count { it in 0x1F3FB..0x1F3FF } == 1 && targetModifier in alternate
|
||||||
// Users are encouraged to use the system emoji keyboard to get the full range of
|
|
||||||
// skin tone modifiers.
|
|
||||||
alternate.count { it == skinType.modifierCodepoint?.toLong() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifier?.joinToString("") { String(Character.toChars(it.toInt())) }
|
return modifier?.joinToString("") { String(Character.toChars(it.toInt())) }
|
||||||
|
|
@ -228,19 +249,7 @@ class EmojiImpl {
|
||||||
val category =
|
val category =
|
||||||
UnicodeEmojiSection.entries.find { it.googleName == group.group } ?: continue
|
UnicodeEmojiSection.entries.find { it.googleName == group.group } ?: continue
|
||||||
list.add(EmojiPickerItem.Section(Category.UnicodeEmojiCategory(category)))
|
list.add(EmojiPickerItem.Section(Category.UnicodeEmojiCategory(category)))
|
||||||
list.addAll(
|
list.addAll(matchingEmoji.flatMap { emoji -> emojiToPickerItems(emoji) })
|
||||||
matchingEmoji.map { emoji ->
|
|
||||||
EmojiPickerItem.UnicodeEmoji(
|
|
||||||
emoji.base.joinToString("") { String(Character.toChars(it.toInt())) },
|
|
||||||
emoji.alternates.any { alternate ->
|
|
||||||
alternate.any { codepoint ->
|
|
||||||
codepoint in 0x1F3FB..0x1F3FF
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emoji.alternates
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue