Skip to content

Commit 1485720

Browse files
committed
emoji [nfc]: Factor out UnicodeEmojiWidget
1 parent ecd3138 commit 1485720

File tree

2 files changed

+81
-42
lines changed

2 files changed

+81
-42
lines changed

lib/widgets/emoji.dart

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,82 @@ import 'package:flutter/widgets.dart';
44
import '../model/emoji.dart';
55
import 'content.dart';
66

7+
class UnicodeEmojiWidget extends StatelessWidget {
8+
const UnicodeEmojiWidget({
9+
super.key,
10+
required this.emojiDisplay,
11+
required this.size,
12+
required this.notoColorEmojiTextSize,
13+
this.textScaler = TextScaler.noScaling,
14+
});
15+
16+
final UnicodeEmojiDisplay emojiDisplay;
17+
18+
/// The base width and height to use for the emoji.
19+
///
20+
/// This will be scaled by [textScaler].
21+
final double size;
22+
23+
/// A font size that, with Noto Color Emoji and our line-height config,
24+
/// causes a Unicode emoji to occupy a square of size [size] in the layout.
25+
///
26+
/// This has to be determined experimentally, as far as we know.
27+
final double notoColorEmojiTextSize;
28+
29+
/// The text scaler to apply to [size].
30+
///
31+
/// Defaults to [TextScaler.noScaling].
32+
final TextScaler textScaler;
33+
34+
@override
35+
Widget build(BuildContext context) {
36+
switch (defaultTargetPlatform) {
37+
case TargetPlatform.android:
38+
case TargetPlatform.fuchsia:
39+
case TargetPlatform.linux:
40+
case TargetPlatform.windows:
41+
return Text(
42+
textScaler: textScaler,
43+
style: TextStyle(
44+
fontFamily: 'Noto Color Emoji',
45+
fontSize: notoColorEmojiTextSize,
46+
),
47+
strutStyle: StrutStyle(
48+
fontSize: notoColorEmojiTextSize, forceStrutHeight: true),
49+
emojiDisplay.emojiUnicode);
50+
51+
case TargetPlatform.iOS:
52+
case TargetPlatform.macOS:
53+
// We expect the font "Apple Color Emoji" to be used. There are some
54+
// surprises in how Flutter ends up rendering emojis in this font:
55+
// - With a font size of 17px, the emoji visually seems to be about 17px
56+
// square. (Unlike on Android, with Noto Color Emoji, where a 14.5px font
57+
// size gives an emoji that looks 17px square.) See:
58+
// <https://github.com/flutter/flutter/issues/28894>
59+
// - The emoji doesn't fill the space taken by the [Text] in the layout.
60+
// There's whitespace above, below, and on the right. See:
61+
// <https://github.com/flutter/flutter/issues/119623>
62+
//
63+
// That extra space would be problematic, except we've used a [Stack] to
64+
// make the [Text] "positioned" so the space doesn't add margins around the
65+
// visible part. Key points that enable the [Stack] workaround:
66+
// - The emoji seems approximately vertically centered (this is
67+
// accomplished with help from a [StrutStyle]; see below).
68+
// - There seems to be approximately no space on its left.
69+
final boxSize = textScaler.scale(size);
70+
return Stack(alignment: Alignment.centerLeft, clipBehavior: Clip.none, children: [
71+
SizedBox(height: boxSize, width: boxSize),
72+
PositionedDirectional(start: 0, child: Text(
73+
textScaler: textScaler,
74+
style: TextStyle(fontSize: size),
75+
strutStyle: StrutStyle(fontSize: size, forceStrutHeight: true),
76+
emojiDisplay.emojiUnicode)),
77+
]);
78+
}
79+
}
80+
}
81+
82+
783
class ImageEmojiWidget extends StatelessWidget {
884
const ImageEmojiWidget({
985
super.key,

lib/widgets/emoji_reaction.dart

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import 'package:flutter/foundation.dart';
21
import 'package:flutter/material.dart';
32

43
import '../api/model/model.dart';
@@ -304,47 +303,11 @@ class _UnicodeEmoji extends StatelessWidget {
304303

305304
@override
306305
Widget build(BuildContext context) {
307-
switch (defaultTargetPlatform) {
308-
case TargetPlatform.android:
309-
case TargetPlatform.fuchsia:
310-
case TargetPlatform.linux:
311-
case TargetPlatform.windows:
312-
return Text(
313-
textScaler: _squareEmojiScalerClamped(context),
314-
style: const TextStyle(
315-
fontFamily: 'Noto Color Emoji',
316-
fontSize: _notoColorEmojiTextSize,
317-
),
318-
strutStyle: const StrutStyle(fontSize: _notoColorEmojiTextSize, forceStrutHeight: true),
319-
emojiDisplay.emojiUnicode);
320-
case TargetPlatform.iOS:
321-
case TargetPlatform.macOS:
322-
// We expect the font "Apple Color Emoji" to be used. There are some
323-
// surprises in how Flutter ends up rendering emojis in this font:
324-
// - With a font size of 17px, the emoji visually seems to be about 17px
325-
// square. (Unlike on Android, with Noto Color Emoji, where a 14.5px font
326-
// size gives an emoji that looks 17px square.) See:
327-
// <https://github.com/flutter/flutter/issues/28894>
328-
// - The emoji doesn't fill the space taken by the [Text] in the layout.
329-
// There's whitespace above, below, and on the right. See:
330-
// <https://github.com/flutter/flutter/issues/119623>
331-
//
332-
// That extra space would be problematic, except we've used a [Stack] to
333-
// make the [Text] "positioned" so the space doesn't add margins around the
334-
// visible part. Key points that enable the [Stack] workaround:
335-
// - The emoji seems approximately vertically centered (this is
336-
// accomplished with help from a [StrutStyle]; see below).
337-
// - There seems to be approximately no space on its left.
338-
final boxSize = _squareEmojiScalerClamped(context).scale(_squareEmojiSize);
339-
return Stack(alignment: Alignment.centerLeft, clipBehavior: Clip.none, children: [
340-
SizedBox(height: boxSize, width: boxSize),
341-
PositionedDirectional(start: 0, child: Text(
342-
textScaler: _squareEmojiScalerClamped(context),
343-
style: const TextStyle(fontSize: _squareEmojiSize),
344-
strutStyle: const StrutStyle(fontSize: _squareEmojiSize, forceStrutHeight: true),
345-
emojiDisplay.emojiUnicode)),
346-
]);
347-
}
306+
return UnicodeEmojiWidget(
307+
size: _squareEmojiSize,
308+
notoColorEmojiTextSize: _notoColorEmojiTextSize,
309+
textScaler: _squareEmojiScalerClamped(context),
310+
emojiDisplay: emojiDisplay);
348311
}
349312
}
350313

0 commit comments

Comments
 (0)