Skip to content

Commit f7421bf

Browse files
committed
content: Use emoji font to show emoji nodes
For emoji like ❤ U+2764 HEAVY BLACK HEART, this causes us to show a colorful, larger glyph like ❤️ from the emoji font, instead of a glyph like ❤︎ that comes from a plain-text font and has the color and size of plain text. Fixes: zulip#1104
1 parent 9391867 commit f7421bf

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

lib/widgets/content.dart

+14-1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
5454
textStylePlainParagraph: _plainParagraphCommon(context).copyWith(
5555
color: const HSLColor.fromAHSL(1, 0, 0, 0.15).toColor(),
5656
debugLabel: 'ContentTheme.textStylePlainParagraph'),
57+
textStyleEmoji: TextStyle(
58+
fontFamily: emojiFontFamily, fontFamilyFallback: const []),
5759
codeBlockTextStyles: CodeBlockTextStyles.light(context),
5860
textStyleError: const TextStyle(fontSize: kBaseFontSize, color: Colors.red)
5961
.merge(weightVariableTextStyle(context, wght: 700)),
@@ -85,6 +87,8 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
8587
textStylePlainParagraph: _plainParagraphCommon(context).copyWith(
8688
color: const HSLColor.fromAHSL(1, 0, 0, 0.85).toColor(),
8789
debugLabel: 'ContentTheme.textStylePlainParagraph'),
90+
textStyleEmoji: TextStyle(
91+
fontFamily: emojiFontFamily, fontFamilyFallback: const []),
8892
codeBlockTextStyles: CodeBlockTextStyles.dark(context),
8993
textStyleError: const TextStyle(fontSize: kBaseFontSize, color: Colors.red)
9094
.merge(weightVariableTextStyle(context, wght: 700)),
@@ -113,6 +117,7 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
113117
required this.colorTableHeaderBackground,
114118
required this.colorThematicBreak,
115119
required this.textStylePlainParagraph,
120+
required this.textStyleEmoji,
116121
required this.codeBlockTextStyles,
117122
required this.textStyleError,
118123
required this.textStyleErrorCode,
@@ -152,6 +157,9 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
152157
/// should not need styles from other sources, such as Material defaults.
153158
final TextStyle textStylePlainParagraph;
154159

160+
/// The [TextStyle] to use for Unicode emoji.
161+
final TextStyle textStyleEmoji;
162+
155163
final CodeBlockTextStyles codeBlockTextStyles;
156164
final TextStyle textStyleError;
157165
final TextStyle textStyleErrorCode;
@@ -201,6 +209,7 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
201209
Color? colorTableHeaderBackground,
202210
Color? colorThematicBreak,
203211
TextStyle? textStylePlainParagraph,
212+
TextStyle? textStyleEmoji,
204213
CodeBlockTextStyles? codeBlockTextStyles,
205214
TextStyle? textStyleError,
206215
TextStyle? textStyleErrorCode,
@@ -222,6 +231,7 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
222231
colorTableHeaderBackground: colorTableHeaderBackground ?? this.colorTableHeaderBackground,
223232
colorThematicBreak: colorThematicBreak ?? this.colorThematicBreak,
224233
textStylePlainParagraph: textStylePlainParagraph ?? this.textStylePlainParagraph,
234+
textStyleEmoji: textStyleEmoji ?? this.textStyleEmoji,
225235
codeBlockTextStyles: codeBlockTextStyles ?? this.codeBlockTextStyles,
226236
textStyleError: textStyleError ?? this.textStyleError,
227237
textStyleErrorCode: textStyleErrorCode ?? this.textStyleErrorCode,
@@ -250,6 +260,7 @@ class ContentTheme extends ThemeExtension<ContentTheme> {
250260
colorTableHeaderBackground: Color.lerp(colorTableHeaderBackground, other.colorTableHeaderBackground, t)!,
251261
colorThematicBreak: Color.lerp(colorThematicBreak, other.colorThematicBreak, t)!,
252262
textStylePlainParagraph: TextStyle.lerp(textStylePlainParagraph, other.textStylePlainParagraph, t)!,
263+
textStyleEmoji: TextStyle.lerp(textStyleEmoji, other.textStyleEmoji, t)!,
253264
codeBlockTextStyles: CodeBlockTextStyles.lerp(codeBlockTextStyles, other.codeBlockTextStyles, t),
254265
textStyleError: TextStyle.lerp(textStyleError, other.textStyleError, t)!,
255266
textStyleErrorCode: TextStyle.lerp(textStyleErrorCode, other.textStyleErrorCode, t)!,
@@ -1031,7 +1042,9 @@ class _InlineContentBuilder {
10311042
child: UserMention(ambientTextStyle: widget.style, node: node));
10321043

10331044
case UnicodeEmojiNode():
1034-
return TextSpan(text: node.emojiUnicode, recognizer: _recognizer);
1045+
return TextSpan(text: node.emojiUnicode, recognizer: _recognizer,
1046+
style: widget.style
1047+
.merge(ContentTheme.of(_context!).textStyleEmoji));
10351048

10361049
case ImageEmojiNode():
10371050
return WidgetSpan(alignment: PlaceholderAlignment.middle,

lib/widgets/text.dart

+5-1
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,13 @@ const kDefaultFontFamily = 'Source Sans 3';
153153

154154
/// The [TextStyle.fontFamilyFallback] for use with [kDefaultFontFamily].
155155
List<String> get defaultFontFamilyFallback => [
156-
_useAppleEmoji ? 'Apple Color Emoji' : 'Noto Color Emoji',
156+
emojiFontFamily,
157157
];
158158

159+
String get emojiFontFamily {
160+
return _useAppleEmoji ? 'Apple Color Emoji' : 'Noto Color Emoji';
161+
}
162+
159163
/// Whether to use the Apple Color Emoji font for showing emoji.
160164
///
161165
/// When false, we use Noto Color Emoji instead.

test/widgets/content_test.dart

+13
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,19 @@ void main() {
877877
testContentSmoke(ContentExample.emojiUnicode);
878878
testContentSmoke(ContentExample.emojiUnicodeMultiCodepoint);
879879
testContentSmoke(ContentExample.emojiUnicodeLiteral);
880+
881+
testWidgets('use emoji font', (tester) async {
882+
// Compare [ContentExample.emojiUnicode].
883+
const emojiHeartHtml =
884+
'<p><span aria-label="heart" class="emoji emoji-2764" role="img" title="heart">:heart:</span></p>';
885+
await prepareContent(tester, plainContent(emojiHeartHtml));
886+
check(mergedStyleOf(tester, '\u{2764}')).isNotNull()
887+
.fontFamily.equals(switch (defaultTargetPlatform) {
888+
TargetPlatform.android => 'Noto Color Emoji',
889+
TargetPlatform.iOS => 'Apple Color Emoji',
890+
_ => throw StateError('unexpected platform in test'),
891+
});
892+
}, variant: const TargetPlatformVariant({TargetPlatform.android, TargetPlatform.iOS}));
880893
});
881894

882895
group('inline math', () {

0 commit comments

Comments
 (0)