implemented dynamic quick reactions by surfacing emojis from message content in the chat options dialog
This commit is contained in:
@@ -10,6 +10,8 @@ const int _zwj = 0x200D;
|
||||
const int _vs15 = 0xFE0E;
|
||||
const int _vs16 = 0xFE0F;
|
||||
const int _keycap = 0x20E3;
|
||||
const int _skinToneStart = 0x1F3FB;
|
||||
const int _skinToneEnd = 0x1F3FF;
|
||||
|
||||
/// Codepoints that only ever glue an emoji sequence together and never stand
|
||||
/// on their own — they don't disqualify a cluster from counting as emoji.
|
||||
@@ -18,7 +20,7 @@ bool _isModifier(int r) =>
|
||||
r == _vs15 ||
|
||||
r == _vs16 ||
|
||||
r == _keycap ||
|
||||
(r >= 0x1F3FB && r <= 0x1F3FF) || // skin-tone modifiers
|
||||
(r >= _skinToneStart && r <= _skinToneEnd) || // skin-tone modifiers
|
||||
(r >= 0xE0020 && r <= 0xE007F); // tag characters (flag sequences)
|
||||
|
||||
/// The digits, `#` and `*` that become emoji only when combined with the
|
||||
@@ -84,3 +86,31 @@ double? standaloneEmojiFontSize(String text) {
|
||||
if (count == 0) return null;
|
||||
return 34;
|
||||
}
|
||||
|
||||
/// [emoji] with any Fitzpatrick skin-tone modifier stripped, so tone variants
|
||||
/// of the same emoji compare equal (👍🏻 → 👍). Used to dedupe reactions that
|
||||
/// only differ in skin tone.
|
||||
String emojiSkinToneNeutral(String emoji) => String.fromCharCodes(
|
||||
emoji.runes.where((r) => r < _skinToneStart || r > _skinToneEnd),
|
||||
);
|
||||
|
||||
/// Distinct emojis contained in [text], most-frequent first with ties broken
|
||||
/// by first appearance. Used to offer a message's own emojis as quick
|
||||
/// reactions.
|
||||
List<String> extractEmojis(String text) {
|
||||
final counts = <String, int>{};
|
||||
final firstSeen = <String, int>{};
|
||||
var order = 0;
|
||||
for (final cluster in text.characters) {
|
||||
if (!_isEmojiCluster(cluster)) continue;
|
||||
counts.update(cluster, (value) => value + 1, ifAbsent: () => 1);
|
||||
firstSeen.putIfAbsent(cluster, () => order++);
|
||||
}
|
||||
|
||||
final emojis = counts.keys.toList();
|
||||
emojis.sort((a, b) {
|
||||
final byCount = counts[b]!.compareTo(counts[a]!);
|
||||
return byCount != 0 ? byCount : firstSeen[a]!.compareTo(firstSeen[b]!);
|
||||
});
|
||||
return emojis;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user