@@ -5,6 +5,97 @@ import '../api/model/model.dart';
55import '../model/emoji.dart' ;
66import 'content.dart' ;
77
8+ /// A widget showing an emoji.
9+ class EmojiWidget extends StatelessWidget {
10+ const EmojiWidget ({
11+ super .key,
12+ required this .emojiDisplay,
13+ required this .squareDimension,
14+ this .squareDimensionScaler = TextScaler .noScaling,
15+ this .imagePlaceholderStyle = EmojiImagePlaceholderStyle .square,
16+ this .neverAnimateImage = false ,
17+ this .buildCustomTextEmoji,
18+ });
19+
20+ final EmojiDisplay emojiDisplay;
21+
22+ /// The base width and height to use for the emoji square.
23+ ///
24+ /// This will be scaled by [squareDimensionScaler] .
25+ ///
26+ /// This is ignored when using the plain-text emoji style.
27+ final double squareDimension;
28+
29+ /// A [TextScaler] to apply to [squareDimension] .
30+ ///
31+ /// Defaults to [TextScaler.noScaling] .
32+ ///
33+ /// This is ignored when using the plain-text emoji style.
34+ final TextScaler squareDimensionScaler;
35+
36+ final EmojiImagePlaceholderStyle imagePlaceholderStyle;
37+
38+ /// Whether to show an animated emoji in its still (non-animated) variant
39+ /// only, even if device settings permit animation.
40+ ///
41+ /// Defaults to false.
42+ final bool neverAnimateImage;
43+
44+ /// An optional callback to specify a custom plain-text emoji style.
45+ ///
46+ /// If this is not passed, a simple [Text] widget with no added styling
47+ /// is used.
48+ final Widget Function ()? buildCustomTextEmoji;
49+
50+ Widget _buildTextEmoji () {
51+ return buildCustomTextEmoji? .call ()
52+ ?? Text (textEmojiForEmojiName (emojiDisplay.emojiName));
53+ }
54+
55+ ImageErrorWidgetBuilder _getImageErrorBuilder (double effectiveSize) {
56+ return (_, _, _) => switch (imagePlaceholderStyle) {
57+ EmojiImagePlaceholderStyle .square => SizedBox .square (dimension: effectiveSize),
58+ EmojiImagePlaceholderStyle .nothing => SizedBox .shrink (),
59+ EmojiImagePlaceholderStyle .text => _buildTextEmoji (),
60+ };
61+ }
62+
63+ @override
64+ Widget build (BuildContext context) {
65+ final effectiveSquareDimension = squareDimensionScaler.scale (squareDimension);
66+
67+ final emojiDisplay = this .emojiDisplay;
68+ return switch (emojiDisplay) {
69+ ImageEmojiDisplay () => ImageEmojiWidget (
70+ emojiDisplay: emojiDisplay,
71+ size: squareDimension,
72+ textScaler: squareDimensionScaler,
73+ errorBuilder: _getImageErrorBuilder (effectiveSquareDimension),
74+ neverAnimate: neverAnimateImage),
75+ UnicodeEmojiDisplay () => UnicodeEmojiWidget (
76+ size: squareDimension,
77+ emojiDisplay: emojiDisplay),
78+ TextEmojiDisplay () => _buildTextEmoji (),
79+ };
80+ }
81+ }
82+
83+ /// In [EmojiWidget] , how to present an image emoji when we don't have the image.
84+ enum EmojiImagePlaceholderStyle {
85+ /// A square of [EmojiWidget.squareDimension]
86+ /// scaled by [EmojiWidget.squareDimensionScaler] .
87+ square,
88+
89+ /// A [SizedBox.shrink] .
90+ nothing,
91+
92+ /// A plain-text emoji.
93+ ///
94+ /// See [EmojiWidget.buildCustomTextEmoji] for how plain-text emojis are
95+ /// styled.
96+ text,
97+ }
98+
899class UnicodeEmojiWidget extends StatelessWidget {
9100 const UnicodeEmojiWidget ({
10101 super .key,
@@ -91,7 +182,6 @@ class UnicodeEmojiWidget extends StatelessWidget {
91182 }
92183}
93184
94-
95185class ImageEmojiWidget extends StatelessWidget {
96186 const ImageEmojiWidget ({
97187 super .key,
0 commit comments