@@ -8,6 +8,104 @@ import 'content.dart';
8
8
import 'store.dart' ;
9
9
import 'text.dart' ;
10
10
11
+ /// Emoji-reaction styles that differ between light and dark themes.
12
+ class EmojiReactionTheme extends ThemeExtension <EmojiReactionTheme > {
13
+ factory EmojiReactionTheme .light () {
14
+ return EmojiReactionTheme ._(
15
+ bgSelected: Colors .white,
16
+
17
+ // TODO shadow effect, following web, which uses `box-shadow: inset`:
18
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow#inset
19
+ // Needs Flutter support for something like that:
20
+ // https://github.com/flutter/flutter/issues/18636
21
+ // https://github.com/flutter/flutter/issues/52999
22
+ // Until then use a solid color; a much-lightened version of the shadow color.
23
+ // Also adapt by making [borderUnselected] more transparent, so we'll
24
+ // want to check that against web when implementing the shadow.
25
+ bgUnselected: const HSLColor .fromAHSL (0.08 , 210 , 0.50 , 0.875 ).toColor (),
26
+
27
+ borderSelected: Colors .black.withOpacity (0.45 ),
28
+
29
+ // TODO see TODO on [bgUnselected] about shadow effect
30
+ borderUnselected: Colors .black.withOpacity (0.05 ),
31
+
32
+ textSelected: const HSLColor .fromAHSL (1 , 210 , 0.20 , 0.20 ).toColor (),
33
+ textUnselected: const HSLColor .fromAHSL (1 , 210 , 0.20 , 0.25 ).toColor (),
34
+ );
35
+ }
36
+
37
+ factory EmojiReactionTheme .dark () {
38
+ return EmojiReactionTheme ._(
39
+ bgSelected: Colors .black.withOpacity (0.8 ),
40
+ bgUnselected: Colors .black.withOpacity (0.3 ),
41
+ borderSelected: Colors .white.withOpacity (0.75 ),
42
+ borderUnselected: Colors .white.withOpacity (0.15 ),
43
+ textSelected: Colors .white.withOpacity (0.85 ),
44
+ textUnselected: Colors .white.withOpacity (0.75 ),
45
+ );
46
+ }
47
+
48
+ EmojiReactionTheme ._({
49
+ required this .bgSelected,
50
+ required this .bgUnselected,
51
+ required this .borderSelected,
52
+ required this .borderUnselected,
53
+ required this .textSelected,
54
+ required this .textUnselected,
55
+ });
56
+
57
+ /// The [EmojiReactionTheme] from the context's active theme.
58
+ ///
59
+ /// The [ThemeData] must include [EmojiReactionTheme] in [ThemeData.extensions] .
60
+ static EmojiReactionTheme of (BuildContext context) {
61
+ final theme = Theme .of (context);
62
+ final extension = theme.extension < EmojiReactionTheme > ();
63
+ assert (extension != null );
64
+ return extension ! ;
65
+ }
66
+
67
+ final Color bgSelected;
68
+ final Color bgUnselected;
69
+ final Color borderSelected;
70
+ final Color borderUnselected;
71
+ final Color textSelected;
72
+ final Color textUnselected;
73
+
74
+ @override
75
+ EmojiReactionTheme copyWith ({
76
+ Color ? bgSelected,
77
+ Color ? bgUnselected,
78
+ Color ? borderSelected,
79
+ Color ? borderUnselected,
80
+ Color ? textSelected,
81
+ Color ? textUnselected,
82
+ }) {
83
+ return EmojiReactionTheme ._(
84
+ bgSelected: bgSelected ?? this .bgSelected,
85
+ bgUnselected: bgUnselected ?? this .bgUnselected,
86
+ borderSelected: borderSelected ?? this .borderSelected,
87
+ borderUnselected: borderUnselected ?? this .borderUnselected,
88
+ textSelected: textSelected ?? this .textSelected,
89
+ textUnselected: textUnselected ?? this .textUnselected,
90
+ );
91
+ }
92
+
93
+ @override
94
+ EmojiReactionTheme lerp (EmojiReactionTheme other, double t) {
95
+ if (identical (this , other)) {
96
+ return this ;
97
+ }
98
+ return EmojiReactionTheme ._(
99
+ bgSelected: Color .lerp (bgSelected, other.bgSelected, t)! ,
100
+ bgUnselected: Color .lerp (bgUnselected, other.bgUnselected, t)! ,
101
+ borderSelected: Color .lerp (borderSelected, other.borderSelected, t)! ,
102
+ borderUnselected: Color .lerp (borderUnselected, other.borderUnselected, t)! ,
103
+ textSelected: Color .lerp (textSelected, other.textSelected, t)! ,
104
+ textUnselected: Color .lerp (textUnselected, other.textUnselected, t)! ,
105
+ );
106
+ }
107
+ }
108
+
11
109
class ReactionChipsList extends StatelessWidget {
12
110
const ReactionChipsList ({
13
111
super .key,
@@ -32,24 +130,6 @@ class ReactionChipsList extends StatelessWidget {
32
130
}
33
131
}
34
132
35
- final _textColorSelected = const HSLColor .fromAHSL (1 , 210 , 0.20 , 0.20 ).toColor ();
36
- final _textColorUnselected = const HSLColor .fromAHSL (1 , 210 , 0.20 , 0.25 ).toColor ();
37
-
38
- const _backgroundColorSelected = Colors .white;
39
- // TODO shadow effect, following web, which uses `box-shadow: inset`:
40
- // https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow#inset
41
- // Needs Flutter support for something like that:
42
- // https://github.com/flutter/flutter/issues/18636
43
- // https://github.com/flutter/flutter/issues/52999
44
- // Until then use a solid color; a much-lightened version of the shadow color.
45
- // Also adapt by making [_borderColorUnselected] more transparent, so we'll
46
- // want to check that against web when implementing the shadow.
47
- final _backgroundColorUnselected = const HSLColor .fromAHSL (0.08 , 210 , 0.50 , 0.875 ).toColor ();
48
-
49
- final _borderColorSelected = Colors .black.withOpacity (0.45 );
50
- // TODO see TODO on [_backgroundColorUnselected] about shadow effect
51
- final _borderColorUnselected = Colors .black.withOpacity (0.05 );
52
-
53
133
class ReactionChip extends StatelessWidget {
54
134
final bool showName;
55
135
final int messageId;
@@ -85,10 +165,11 @@ class ReactionChip extends StatelessWidget {
85
165
}).join (', ' )
86
166
: userIds.length.toString ();
87
167
88
- final borderColor = selfVoted ? _borderColorSelected : _borderColorUnselected;
89
- final labelColor = selfVoted ? _textColorSelected : _textColorUnselected;
90
- final backgroundColor = selfVoted ? _backgroundColorSelected : _backgroundColorUnselected;
91
- final splashColor = selfVoted ? _backgroundColorUnselected : _backgroundColorSelected;
168
+ final reactionTheme = EmojiReactionTheme .of (context);
169
+ final borderColor = selfVoted ? reactionTheme.borderSelected : reactionTheme.borderUnselected;
170
+ final labelColor = selfVoted ? reactionTheme.textSelected : reactionTheme.textUnselected;
171
+ final backgroundColor = selfVoted ? reactionTheme.bgSelected : reactionTheme.bgUnselected;
172
+ final splashColor = selfVoted ? reactionTheme.bgUnselected : reactionTheme.bgSelected;
92
173
final highlightColor = splashColor.withOpacity (0.5 );
93
174
94
175
final borderSide = BorderSide (
@@ -349,14 +430,15 @@ class _TextEmoji extends StatelessWidget {
349
430
350
431
@override
351
432
Widget build (BuildContext context) {
433
+ final reactionTheme = EmojiReactionTheme .of (context);
352
434
return Text (
353
435
textAlign: TextAlign .end,
354
436
textScaler: _textEmojiScalerClamped (context),
355
437
textWidthBasis: TextWidthBasis .longestLine,
356
438
style: TextStyle (
357
439
fontSize: 14 * 0.8 ,
358
440
height: 1 , // to be denser when we have to wrap
359
- color: selected ? _textColorSelected : _textColorUnselected ,
441
+ color: selected ? reactionTheme.textSelected : reactionTheme.textUnselected ,
360
442
).merge (weightVariableTextStyle (context,
361
443
wght: selected ? 600 : null )),
362
444
// Encourage line breaks before "_" (common in these), but try not
0 commit comments