@@ -8,6 +8,102 @@ 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
+ EmojiReactionTheme .light () :
14
+ this ._(
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
+ EmojiReactionTheme .dark () :
37
+ this ._(
38
+ bgSelected: Colors .black.withOpacity (0.8 ),
39
+ bgUnselected: Colors .black.withOpacity (0.3 ),
40
+ borderSelected: Colors .white.withOpacity (0.75 ),
41
+ borderUnselected: Colors .white.withOpacity (0.15 ),
42
+ textSelected: Colors .white.withOpacity (0.85 ),
43
+ textUnselected: Colors .white.withOpacity (0.75 ),
44
+ );
45
+
46
+ EmojiReactionTheme ._({
47
+ required this .bgSelected,
48
+ required this .bgUnselected,
49
+ required this .borderSelected,
50
+ required this .borderUnselected,
51
+ required this .textSelected,
52
+ required this .textUnselected,
53
+ });
54
+
55
+ /// The [EmojiReactionTheme] from the context's active theme.
56
+ ///
57
+ /// The [ThemeData] must include [EmojiReactionTheme] in [ThemeData.extensions] .
58
+ static EmojiReactionTheme of (BuildContext context) {
59
+ final theme = Theme .of (context);
60
+ final extension = theme.extension < EmojiReactionTheme > ();
61
+ assert (extension != null );
62
+ return extension ! ;
63
+ }
64
+
65
+ final Color bgSelected;
66
+ final Color bgUnselected;
67
+ final Color borderSelected;
68
+ final Color borderUnselected;
69
+ final Color textSelected;
70
+ final Color textUnselected;
71
+
72
+ @override
73
+ EmojiReactionTheme copyWith ({
74
+ Color ? bgSelected,
75
+ Color ? bgUnselected,
76
+ Color ? borderSelected,
77
+ Color ? borderUnselected,
78
+ Color ? textSelected,
79
+ Color ? textUnselected,
80
+ }) {
81
+ return EmojiReactionTheme ._(
82
+ bgSelected: bgSelected ?? this .bgSelected,
83
+ bgUnselected: bgUnselected ?? this .bgUnselected,
84
+ borderSelected: borderSelected ?? this .borderSelected,
85
+ borderUnselected: borderUnselected ?? this .borderUnselected,
86
+ textSelected: textSelected ?? this .textSelected,
87
+ textUnselected: textUnselected ?? this .textUnselected,
88
+ );
89
+ }
90
+
91
+ @override
92
+ EmojiReactionTheme lerp (EmojiReactionTheme other, double t) {
93
+ if (identical (this , other)) {
94
+ return this ;
95
+ }
96
+ return EmojiReactionTheme ._(
97
+ bgSelected: Color .lerp (bgSelected, other.bgSelected, t)! ,
98
+ bgUnselected: Color .lerp (bgUnselected, other.bgUnselected, t)! ,
99
+ borderSelected: Color .lerp (borderSelected, other.borderSelected, t)! ,
100
+ borderUnselected: Color .lerp (borderUnselected, other.borderUnselected, t)! ,
101
+ textSelected: Color .lerp (textSelected, other.textSelected, t)! ,
102
+ textUnselected: Color .lerp (textUnselected, other.textUnselected, t)! ,
103
+ );
104
+ }
105
+ }
106
+
11
107
class ReactionChipsList extends StatelessWidget {
12
108
const ReactionChipsList ({
13
109
super .key,
@@ -32,24 +128,6 @@ class ReactionChipsList extends StatelessWidget {
32
128
}
33
129
}
34
130
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
131
class ReactionChip extends StatelessWidget {
54
132
final bool showName;
55
133
final int messageId;
@@ -85,10 +163,11 @@ class ReactionChip extends StatelessWidget {
85
163
}).join (', ' )
86
164
: userIds.length.toString ();
87
165
88
- final borderColor = selfVoted ? _borderColorSelected : _borderColorUnselected;
89
- final labelColor = selfVoted ? _textColorSelected : _textColorUnselected;
90
- final backgroundColor = selfVoted ? _backgroundColorSelected : _backgroundColorUnselected;
91
- final splashColor = selfVoted ? _backgroundColorUnselected : _backgroundColorSelected;
166
+ final reactionTheme = EmojiReactionTheme .of (context);
167
+ final borderColor = selfVoted ? reactionTheme.borderSelected : reactionTheme.borderUnselected;
168
+ final labelColor = selfVoted ? reactionTheme.textSelected : reactionTheme.textUnselected;
169
+ final backgroundColor = selfVoted ? reactionTheme.bgSelected : reactionTheme.bgUnselected;
170
+ final splashColor = selfVoted ? reactionTheme.bgUnselected : reactionTheme.bgSelected;
92
171
final highlightColor = splashColor.withOpacity (0.5 );
93
172
94
173
final borderSide = BorderSide (
@@ -349,14 +428,15 @@ class _TextEmoji extends StatelessWidget {
349
428
350
429
@override
351
430
Widget build (BuildContext context) {
431
+ final reactionTheme = EmojiReactionTheme .of (context);
352
432
return Text (
353
433
textAlign: TextAlign .end,
354
434
textScaler: _textEmojiScalerClamped (context),
355
435
textWidthBasis: TextWidthBasis .longestLine,
356
436
style: TextStyle (
357
437
fontSize: 14 * 0.8 ,
358
438
height: 1 , // to be denser when we have to wrap
359
- color: selected ? _textColorSelected : _textColorUnselected ,
439
+ color: selected ? reactionTheme.textSelected : reactionTheme.textUnselected ,
360
440
).merge (weightVariableTextStyle (context,
361
441
wght: selected ? 600 : null )),
362
442
// Encourage line breaks before "_" (common in these), but try not
0 commit comments