imessage_database/message_types/expressives.rs
1/*!
2 [Expressives](https://support.apple.com/en-us/HT206894) are effects that you can select by tapping and holding the send button.
3*/
4
5use std::fmt;
6
7/// Bubble effects are effects that alter the display of the chat bubble.
8///
9/// Read more [here](https://www.imore.com/how-to-use-bubble-and-screen-effects-imessage-iphone-ipad).
10#[derive(Debug, PartialEq, Eq, Clone, Copy)]
11pub enum BubbleEffect {
12 /// Creates a slam effect that makes the bubble appear to slam down onto the screen.
13 Slam,
14 /// Creates a loud effect that makes the bubble appear to enlarge temporarily.
15 Loud,
16 /// Creates a gentle effect that makes the bubble appear to shrink temporarily.
17 Gentle,
18 /// Creates an invisible ink effect that hides the message until the recipient swipes over it.
19 InvisibleInk,
20}
21
22/// Screen effects are effects that alter the entire background of the message view.
23///
24/// Read more [here](https://www.imore.com/how-to-use-bubble-and-screen-effects-imessage-iphone-ipad).
25#[derive(Debug, PartialEq, Eq, Clone, Copy)]
26pub enum ScreenEffect {
27 /// Creates a confetti effect that sprinkles confetti across the screen.
28 Confetti,
29 /// Creates an echo effect that sends multiple copies of the message across the screen.
30 Echo,
31 /// Creates a fireworks effect that displays colorful explosions on the screen.
32 Fireworks,
33 /// Creates a balloons effect that sends balloons floating up from the bottom of the screen.
34 Balloons,
35 /// Creates a heart effect that displays a large heart on the screen.
36 Heart,
37 /// Creates a laser light show effect across the screen.
38 Lasers,
39 /// Creates a shooting star effect that moves across the screen.
40 ShootingStar,
41 /// Creates a sparkle effect that twinkles across the screen.
42 Sparkles,
43 /// Creates a spotlight effect that highlights the message.
44 Spotlight,
45}
46
47/// Expressive effect container.
48///
49/// Read more about expressive messages [here](https://www.imore.com/how-to-use-bubble-and-screen-effects-imessage-iphone-ipad).
50///
51/// Bubble:
52/// - `com.apple.MobileSMS.expressivesend.gentle`
53/// - `com.apple.MobileSMS.expressivesend.impact`
54/// - `com.apple.MobileSMS.expressivesend.invisibleink`
55/// - `com.apple.MobileSMS.expressivesend.loud`
56///
57/// Screen:
58/// - `com.apple.messages.effect.CKConfettiEffect`
59/// - `com.apple.messages.effect.CKEchoEffect`
60/// - `com.apple.messages.effect.CKFireworksEffect`
61/// - `com.apple.messages.effect.CKHappyBirthdayEffect`
62/// - `com.apple.messages.effect.CKHeartEffect`
63/// - `com.apple.messages.effect.CKLasersEffect`
64/// - `com.apple.messages.effect.CKShootingStarEffect`
65/// - `com.apple.messages.effect.CKSparklesEffect`
66/// - `com.apple.messages.effect.CKSpotlightEffect`
67#[derive(Debug, PartialEq, Eq, Clone, Copy)]
68pub enum Expressive<'a> {
69 /// Effects that use the entire screen
70 Screen(ScreenEffect),
71 /// Effects that display on a single bubble
72 Bubble(BubbleEffect),
73 /// Container for new or unknown effects. The string is the raw `expressive_send_style_id` value.
74 Unknown(&'a str),
75 /// Message is not an expressive
76 None,
77}
78
79impl fmt::Display for Expressive<'_> {
80 /// Render the canonical user-facing label for this expressive (e.g. `Sent
81 /// with Confetti`). `None` renders to the empty string; `Unknown` renders
82 /// to the raw style id so unrecognized values still surface.
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 match self {
85 Self::Screen(ScreenEffect::Confetti) => f.write_str("Sent with Confetti"),
86 Self::Screen(ScreenEffect::Echo) => f.write_str("Sent with Echo"),
87 Self::Screen(ScreenEffect::Fireworks) => f.write_str("Sent with Fireworks"),
88 Self::Screen(ScreenEffect::Balloons) => f.write_str("Sent with Balloons"),
89 Self::Screen(ScreenEffect::Heart) => f.write_str("Sent with Heart"),
90 Self::Screen(ScreenEffect::Lasers) => f.write_str("Sent with Lasers"),
91 Self::Screen(ScreenEffect::ShootingStar) => f.write_str("Sent with Shooting Star"),
92 Self::Screen(ScreenEffect::Sparkles) => f.write_str("Sent with Sparkles"),
93 Self::Screen(ScreenEffect::Spotlight) => f.write_str("Sent with Spotlight"),
94 Self::Bubble(BubbleEffect::Slam) => f.write_str("Sent with Slam"),
95 Self::Bubble(BubbleEffect::Loud) => f.write_str("Sent with Loud"),
96 Self::Bubble(BubbleEffect::Gentle) => f.write_str("Sent with Gentle"),
97 Self::Bubble(BubbleEffect::InvisibleInk) => f.write_str("Sent with Invisible Ink"),
98 Self::Unknown(raw) => f.write_str(raw),
99 Self::None => Ok(()),
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn display_none_is_empty() {
110 assert_eq!(Expressive::None.to_string(), "");
111 }
112
113 #[test]
114 fn display_unknown_returns_raw_id() {
115 assert_eq!(Expressive::Unknown("custom.id").to_string(), "custom.id");
116 }
117
118 #[test]
119 fn display_screen_effects() {
120 let cases = [
121 (ScreenEffect::Confetti, "Sent with Confetti"),
122 (ScreenEffect::Echo, "Sent with Echo"),
123 (ScreenEffect::Fireworks, "Sent with Fireworks"),
124 (ScreenEffect::Balloons, "Sent with Balloons"),
125 (ScreenEffect::Heart, "Sent with Heart"),
126 (ScreenEffect::Lasers, "Sent with Lasers"),
127 (ScreenEffect::ShootingStar, "Sent with Shooting Star"),
128 (ScreenEffect::Sparkles, "Sent with Sparkles"),
129 (ScreenEffect::Spotlight, "Sent with Spotlight"),
130 ];
131 for (effect, expected) in cases {
132 assert_eq!(Expressive::Screen(effect).to_string(), expected);
133 }
134 }
135
136 #[test]
137 fn display_bubble_effects() {
138 let cases = [
139 (BubbleEffect::Slam, "Sent with Slam"),
140 (BubbleEffect::Loud, "Sent with Loud"),
141 (BubbleEffect::Gentle, "Sent with Gentle"),
142 (BubbleEffect::InvisibleInk, "Sent with Invisible Ink"),
143 ];
144 for (effect, expected) in cases {
145 assert_eq!(Expressive::Bubble(effect).to_string(), expected);
146 }
147 }
148}