Skip to main content

iris_chat_core/
emoji.rs

1//! Shared emoji catalog and search aliases used by the picker on
2//! every platform that ships its own grid (iOS/macOS, Android,
3//! Windows). Linux uses the native GTK EmojiChooser and ignores
4//! this catalog.
5
6#[derive(uniffi::Record, Clone, Debug, PartialEq, Eq)]
7pub struct EmojiCategorySnapshot {
8    pub name: String,
9    pub emojis: Vec<String>,
10}
11
12#[derive(uniffi::Record, Clone, Debug, PartialEq, Eq)]
13pub struct EmojiAliasSnapshot {
14    pub emoji: String,
15    pub keywords: String,
16}
17
18fn cat(name: &str, emojis: &[&str]) -> EmojiCategorySnapshot {
19    EmojiCategorySnapshot {
20        name: name.to_string(),
21        emojis: emojis.iter().map(|s| (*s).to_string()).collect(),
22    }
23}
24
25fn alias(emoji: &str, keywords: &str) -> EmojiAliasSnapshot {
26    EmojiAliasSnapshot {
27        emoji: emoji.to_string(),
28        keywords: keywords.to_string(),
29    }
30}
31
32#[uniffi::export]
33pub fn iris_emoji_catalog() -> Vec<EmojiCategorySnapshot> {
34    vec![
35        cat(
36            "Smileys",
37            &[
38                "๐Ÿ˜€",
39                "๐Ÿ˜ƒ",
40                "๐Ÿ˜„",
41                "๐Ÿ˜",
42                "๐Ÿ˜†",
43                "๐Ÿ˜…",
44                "๐Ÿคฃ",
45                "๐Ÿ˜‚",
46                "๐Ÿ™‚",
47                "๐Ÿ™ƒ",
48                "๐Ÿซ ",
49                "๐Ÿ˜‰",
50                "๐Ÿ˜Š",
51                "๐Ÿ˜‡",
52                "๐Ÿฅฐ",
53                "๐Ÿ˜",
54                "๐Ÿคฉ",
55                "๐Ÿ˜˜",
56                "๐Ÿ˜—",
57                "โ˜บ๏ธ",
58                "๐Ÿ˜š",
59                "๐Ÿ˜™",
60                "๐Ÿฅฒ",
61                "๐Ÿ˜‹",
62                "๐Ÿ˜›",
63                "๐Ÿ˜œ",
64                "๐Ÿคช",
65                "๐Ÿ˜",
66                "๐Ÿค‘",
67                "๐Ÿค—",
68                "๐Ÿคญ",
69                "๐Ÿซข",
70                "๐Ÿซฃ",
71                "๐Ÿคซ",
72                "๐Ÿค”",
73                "๐Ÿซก",
74                "๐Ÿค",
75                "๐Ÿคจ",
76                "๐Ÿ˜",
77                "๐Ÿ˜‘",
78                "๐Ÿ˜ถ",
79                "๐Ÿซฅ",
80                "๐Ÿ˜ถโ€๐ŸŒซ๏ธ",
81                "๐Ÿ˜",
82                "๐Ÿ˜’",
83                "๐Ÿ™„",
84                "๐Ÿ˜ฌ",
85                "๐Ÿ˜ฎโ€๐Ÿ’จ",
86                "๐Ÿคฅ",
87                "๐Ÿ˜Œ",
88                "๐Ÿ˜”",
89                "๐Ÿ˜ช",
90                "๐Ÿคค",
91                "๐Ÿ˜ด",
92                "๐Ÿ˜ท",
93                "๐Ÿค’",
94                "๐Ÿค•",
95                "๐Ÿคข",
96                "๐Ÿคฎ",
97                "๐Ÿคง",
98                "๐Ÿฅต",
99                "๐Ÿฅถ",
100                "๐Ÿฅด",
101                "๐Ÿ˜ต",
102                "๐Ÿ˜ตโ€๐Ÿ’ซ",
103                "๐Ÿคฏ",
104                "๐Ÿค ",
105                "๐Ÿฅณ",
106                "๐Ÿฅธ",
107                "๐Ÿ˜Ž",
108                "๐Ÿค“",
109                "๐Ÿง",
110                "๐Ÿ˜•",
111                "๐Ÿซค",
112                "๐Ÿ˜Ÿ",
113                "๐Ÿ™",
114                "โ˜น๏ธ",
115                "๐Ÿ˜ฎ",
116                "๐Ÿ˜ฏ",
117                "๐Ÿ˜ฒ",
118                "๐Ÿ˜ณ",
119                "๐Ÿฅบ",
120                "๐Ÿฅน",
121                "๐Ÿ˜ฆ",
122                "๐Ÿ˜ง",
123                "๐Ÿ˜จ",
124                "๐Ÿ˜ฐ",
125                "๐Ÿ˜ฅ",
126                "๐Ÿ˜ข",
127                "๐Ÿ˜ญ",
128                "๐Ÿ˜ฑ",
129                "๐Ÿ˜–",
130                "๐Ÿ˜ฃ",
131                "๐Ÿ˜ž",
132                "๐Ÿ˜“",
133                "๐Ÿ˜ฉ",
134                "๐Ÿ˜ซ",
135                "๐Ÿฅฑ",
136                "๐Ÿ˜ค",
137                "๐Ÿ˜ก",
138                "๐Ÿ˜ ",
139                "๐Ÿคฌ",
140                "๐Ÿ˜ˆ",
141                "๐Ÿ‘ฟ",
142                "๐Ÿ’€",
143                "โ˜ ๏ธ",
144                "๐Ÿ’ฉ",
145                "๐Ÿคก",
146                "๐Ÿ‘น",
147                "๐Ÿ‘บ",
148                "๐Ÿ‘ป",
149                "๐Ÿ‘ฝ",
150                "๐Ÿ‘พ",
151                "๐Ÿค–",
152                "๐Ÿ˜บ",
153                "๐Ÿ˜ธ",
154                "๐Ÿ˜น",
155                "๐Ÿ˜ป",
156                "๐Ÿ˜ผ",
157                "๐Ÿ˜ฝ",
158                "๐Ÿ™€",
159                "๐Ÿ˜ฟ",
160                "๐Ÿ˜พ",
161            ],
162        ),
163        cat(
164            "Hearts",
165            &[
166                "โค๏ธ",
167                "๐Ÿงก",
168                "๐Ÿ’›",
169                "๐Ÿ’š",
170                "๐Ÿ’™",
171                "๐Ÿ’œ",
172                "๐Ÿ–ค",
173                "๐Ÿค",
174                "๐ŸคŽ",
175                "๐Ÿ’–",
176                "๐Ÿ’—",
177                "๐Ÿ’“",
178                "๐Ÿ’ž",
179                "๐Ÿ’•",
180                "๐Ÿ’˜",
181                "๐Ÿ’",
182                "๐Ÿ’Ÿ",
183                "โ™ฅ๏ธ",
184                "๐Ÿ’”",
185                "โฃ๏ธ",
186                "โค๏ธโ€๐Ÿ”ฅ",
187                "โค๏ธโ€๐Ÿฉน",
188            ],
189        ),
190        cat(
191            "Hands",
192            &[
193                "๐Ÿ‘", "๐Ÿ‘Ž", "๐Ÿ‘Œ", "๐ŸคŒ", "๐Ÿค", "โœŒ๏ธ", "๐Ÿคž", "๐Ÿซฐ", "๐ŸคŸ", "๐Ÿค˜", "๐Ÿค™", "๐Ÿ‘ˆ", "๐Ÿ‘‰", "๐Ÿ‘†",
194                "๐Ÿ‘‡", "โ˜๏ธ", "โœ‹", "๐Ÿคš", "๐Ÿ–", "๐Ÿ––", "๐Ÿ‘‹", "๐Ÿค", "๐Ÿ™", "๐Ÿ‘", "๐Ÿ™Œ", "๐Ÿซถ", "๐Ÿ’ช", "๐Ÿซต",
195                "๐Ÿซฑ", "๐Ÿซฒ",
196            ],
197        ),
198        cat(
199            "Animals",
200            &[
201                "๐Ÿถ", "๐Ÿฑ", "๐Ÿญ", "๐Ÿน", "๐Ÿฐ", "๐ŸฆŠ", "๐Ÿป", "๐Ÿผ", "๐Ÿจ", "๐Ÿฏ", "๐Ÿฆ", "๐Ÿฎ", "๐Ÿท", "๐Ÿธ",
202                "๐Ÿต", "๐Ÿ™ˆ", "๐Ÿ™‰", "๐Ÿ™Š", "๐Ÿ”", "๐Ÿง", "๐Ÿฆ", "๐Ÿฆ…", "๐Ÿฆ‰", "๐Ÿฆ„", "๐Ÿ", "๐Ÿฆ‹", "๐Ÿž", "๐Ÿข",
203                "๐Ÿ", "๐Ÿฆ–", "๐Ÿ™", "๐Ÿฆ€", "๐Ÿฌ", "๐Ÿณ", "๐Ÿฆˆ",
204            ],
205        ),
206        cat(
207            "Food",
208            &[
209                "๐Ÿ", "๐ŸŽ", "๐Ÿ", "๐ŸŠ", "๐Ÿ‹", "๐ŸŒ", "๐Ÿ‰", "๐Ÿ‡", "๐Ÿ“", "๐Ÿซ", "๐Ÿ’", "๐Ÿ‘", "๐Ÿฅญ", "๐Ÿ",
210                "๐Ÿฅฅ", "๐Ÿฅ", "๐Ÿ…", "๐Ÿฅ‘", "๐Ÿฅ•", "๐ŸŒฝ", "๐Ÿ†", "๐Ÿฅ”", "๐Ÿ•", "๐Ÿ”", "๐ŸŸ", "๐ŸŒญ", "๐Ÿฟ", "๐Ÿฅช",
211                "๐ŸŒฎ", "๐ŸŒฏ", "๐Ÿฃ", "๐Ÿœ", "๐Ÿ", "๐Ÿฆ", "๐Ÿฉ", "๐Ÿช", "๐ŸŽ‚", "๐Ÿฐ", "โ˜•", "๐Ÿต", "๐Ÿบ", "๐Ÿฅ‚",
212                "๐Ÿท", "๐Ÿฅƒ",
213            ],
214        ),
215        cat(
216            "Activities",
217            &[
218                "โšฝ", "๐Ÿ€", "๐Ÿˆ", "โšพ", "๐ŸฅŽ", "๐ŸŽพ", "๐Ÿ", "๐Ÿ‰", "๐ŸŽฑ", "๐Ÿช€", "๐Ÿ“", "๐Ÿธ", "๐Ÿฅ…", "๐Ÿ’",
219                "๐Ÿ‘", "๐Ÿฅ", "๐Ÿ", "๐Ÿชƒ", "๐ŸฅŠ", "๐Ÿฅ‹", "๐ŸŽฝ", "โ›ธ", "๐ŸฅŒ", "๐Ÿ›ท", "๐Ÿช‚", "๐Ÿ‹๏ธ", "๐Ÿคธ", "๐Ÿคบ",
220                "๐Ÿ‡", "โ›ท", "๐Ÿ‚", "๐ŸŒ๏ธ", "๐Ÿ„", "๐Ÿšฃ", "๐ŸŠ", "๐Ÿคฝ", "๐Ÿšด", "๐Ÿšต", "๐ŸŽฏ", "๐ŸŽฎ", "๐ŸŽฒ", "๐ŸŽผ",
221                "๐ŸŽค", "๐ŸŽง", "๐ŸŽท", "๐ŸŽธ", "๐Ÿฅ",
222            ],
223        ),
224        cat(
225            "Travel",
226            &[
227                "๐Ÿš—", "๐Ÿš•", "๐Ÿš™", "๐ŸšŒ", "๐ŸšŽ", "๐ŸŽ", "๐Ÿš“", "๐Ÿš‘", "๐Ÿš’", "๐Ÿš", "๐Ÿ›ป", "๐Ÿšš", "๐Ÿš›", "๐Ÿšœ",
228                "๐Ÿ›ต", "๐Ÿ", "๐Ÿ›บ", "๐Ÿšฒ", "๐Ÿ›ด", "๐Ÿ›น", "๐Ÿš‚", "โœˆ๏ธ", "๐Ÿš€", "๐Ÿ›ธ", "๐Ÿ›ถ", "โ›ต", "๐Ÿšข", "๐Ÿš",
229                "๐Ÿ—บ", "๐Ÿ—ฝ", "๐Ÿ—ผ", "๐Ÿฐ", "๐ŸŽก", "๐ŸŽข", "๐ŸŽ ", "๐Ÿ–", "๐Ÿ", "๐Ÿ”", "๐ŸŒ‹", "๐Ÿ•", "๐ŸŒ„", "๐ŸŒ…",
230                "๐ŸŒŒ",
231            ],
232        ),
233        cat(
234            "Objects",
235            &[
236                "๐Ÿ“ฑ", "๐Ÿ’ป", "โŒจ๏ธ", "๐Ÿ–ฅ", "๐Ÿ–จ", "๐Ÿ–ฑ", "๐Ÿ’พ", "๐Ÿ’ฟ", "๐Ÿ“ท", "๐Ÿ“ธ", "๐Ÿ“น", "๐ŸŽฅ", "๐Ÿ“บ", "๐Ÿ“ป",
237                "๐Ÿ“ž", "โ˜Ž๏ธ", "๐Ÿ”Œ", "๐Ÿ”‹", "๐Ÿ’ก", "๐Ÿ”ฆ", "๐Ÿ•ฏ", "๐Ÿงฏ", "๐Ÿ›ข", "๐Ÿ’ต", "๐Ÿ’ฐ", "๐Ÿ’ณ", "๐Ÿ’Ž", "โš–๏ธ",
238                "๐Ÿ”ง", "๐Ÿ”จ", "๐Ÿ› ", "โ›", "๐Ÿช›", "๐Ÿชš", "๐Ÿ”ฉ", "โš™๏ธ", "๐Ÿงฑ", "โ›“", "๐Ÿงฒ", "๐Ÿ”ซ", "๐Ÿ’ฃ", "๐Ÿงจ",
239            ],
240        ),
241        cat(
242            "Symbols",
243            &[
244                "โœ…", "โŽ", "โœ”๏ธ", "โŒ", "โญ•", "๐Ÿšซ", "โš ๏ธ", "๐Ÿ”ฑ", "โ˜‘๏ธ", "๐Ÿ’ฏ", "๐Ÿ”ฅ", "โœจ", "๐ŸŒŸ", "โญ",
245                "๐ŸŒˆ", "โ˜€๏ธ", "๐ŸŒ™", "โšก", "โ˜„๏ธ", "๐Ÿ’ฅ", "๐ŸŒŠ", "๐Ÿ’ง", "๐Ÿ’ฆ", "๐ŸŽ‰", "๐ŸŽŠ", "๐ŸŽ", "๐ŸŽ€", "๐ŸŽˆ",
246                "๐Ÿช…", "๐Ÿพ", "๐Ÿฅ‡", "๐Ÿฅˆ", "๐Ÿฅ‰", "๐Ÿ†", "๐ŸŽ–", "๐Ÿ…", "๐Ÿ’ค", "๐Ÿ’ญ", "๐Ÿ—ฏ", "๐Ÿ’ฌ", "๐Ÿ†—", "๐Ÿ†•",
247                "๐Ÿ†’", "๐Ÿ†“", "๐Ÿ†™", "๐Ÿ”", "โ™ป๏ธ", "โ˜ฎ๏ธ", "โœ๏ธ", "โ˜ช๏ธ", "๐Ÿ•‰", "โ˜ธ๏ธ", "โœก๏ธ", "โ˜ฏ๏ธ", "โ˜ฆ๏ธ",
248            ],
249        ),
250    ]
251}
252
253#[uniffi::export]
254pub fn iris_emoji_search_aliases() -> Vec<EmojiAliasSnapshot> {
255    vec![
256        alias("๐Ÿ˜‚", "laugh laughing lol haha"),
257        alias("๐Ÿคฃ", "laugh laughing lol haha rolling"),
258        alias("๐Ÿ˜Š", "smile smiling happy"),
259        alias("๐Ÿ™‚", "smile smiling happy"),
260        alias("๐Ÿ˜", "love heart eyes"),
261        alias("๐Ÿฅฐ", "love hearts"),
262        alias("๐Ÿ˜˜", "kiss love"),
263        alias("๐Ÿ˜ข", "sad tear crying"),
264        alias("๐Ÿ˜ญ", "sad cry crying"),
265        alias("๐Ÿ˜ ", "angry mad"),
266        alias("๐Ÿคฌ", "angry mad swearing"),
267        alias("๐Ÿ™", "pray praying thanks thank you please"),
268        alias("๐Ÿ‘", "clap applause"),
269        alias("๐Ÿ™Œ", "hooray yay hands"),
270        alias("โค๏ธ", "love heart red"),
271        alias("โ™ฅ๏ธ", "love heart red"),
272        alias("๐Ÿ”ฅ", "fire lit hot"),
273        alias("๐ŸŽ‰", "party celebrate celebration"),
274        alias("๐ŸŽŠ", "party celebrate celebration"),
275        alias("โœจ", "sparkle sparkles"),
276        alias("โœ…", "yes check done"),
277        alias("โŒ", "no cross x"),
278        alias("๐Ÿ‘€", "eyes look watching"),
279        alias("๐Ÿ’ฏ", "hundred perfect"),
280        alias("๐Ÿ˜ฎ", "wow surprised shock shocked open mouth"),
281        alias("๐Ÿ˜ฏ", "wow surprised hushed"),
282        alias("๐Ÿ˜ฒ", "wow surprised astonished shock"),
283        alias("๐Ÿคฏ", "mind blown shock wow"),
284        alias("๐Ÿ˜ฑ", "scream shock shocked wow"),
285        alias("๐Ÿค”", "thinking hmm think"),
286        alias("๐Ÿคข", "sick gross nauseated"),
287        alias("๐Ÿคฎ", "sick gross vomit puke"),
288        alias("๐Ÿฅฑ", "yawn yawning tired bored"),
289        alias("๐Ÿ˜ด", "sleep sleeping tired"),
290        alias("๐Ÿค“", "nerd nerdy glasses"),
291        alias("๐Ÿง", "monocle inspect curious"),
292        alias("๐Ÿ’€", "skull dead"),
293        alias("๐Ÿ‘ป", "ghost spooky"),
294        alias("๐Ÿคก", "clown"),
295        alias("๐Ÿ‘ฝ", "alien"),
296        alias("๐Ÿค–", "robot bot"),
297        alias("๐Ÿ’ฉ", "poo poop"),
298        alias("๐Ÿ˜ˆ", "devil smiling devil"),
299        alias("๐Ÿ‘", "thumbs up like yes"),
300        alias("๐Ÿ‘Ž", "thumbs down dislike no"),
301        alias("๐Ÿฅบ", "pleading puppy eyes"),
302    ]
303}
304
305#[cfg(test)]
306mod tests {
307    use super::*;
308
309    #[test]
310    fn catalog_contains_wow_emoji() {
311        let catalog = iris_emoji_catalog();
312        let smileys = catalog
313            .iter()
314            .find(|c| c.name == "Smileys")
315            .expect("Smileys category");
316        assert!(
317            smileys.emojis.iter().any(|e| e == "๐Ÿ˜ฎ"),
318            "Smileys must include the open-mouth (wow) emoji"
319        );
320    }
321
322    #[test]
323    fn aliases_route_wow_to_open_mouth() {
324        let aliases = iris_emoji_search_aliases();
325        let hit = aliases
326            .iter()
327            .find(|a| a.emoji == "๐Ÿ˜ฎ")
328            .expect("alias entry for open-mouth emoji");
329        assert!(hit.keywords.contains("wow"));
330    }
331}