Skip to content

Commit a76c664

Browse files
committed
color [nfc]: Add ColorExtension.withFadedAlpha
And use it everywhere we were using `.withValues(alpha:` to fade a color variable, except for one place in `lib/widgets/emoji_reaction.dart` where the variable is semi-transparent in dark mode to begin with. We'll do that as a non-NFC change in a later commit. Signed-off-by: Zixuan James Li <[email protected]>
1 parent e3d29f2 commit a76c664

File tree

5 files changed

+46
-9
lines changed

5 files changed

+46
-9
lines changed

lib/widgets/action_sheet.dart

+5-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import '../model/internal_link.dart';
1313
import '../model/narrow.dart';
1414
import 'actions.dart';
1515
import 'clipboard.dart';
16+
import 'color.dart';
1617
import 'dialog.dart';
1718
import 'icons.dart';
1819
import 'inset_shadow.dart';
@@ -145,8 +146,8 @@ abstract class MessageActionSheetMenuItemButton extends StatelessWidget {
145146
foregroundColor: designVariables.contextMenuItemText,
146147
splashFactory: NoSplash.splashFactory,
147148
).copyWith(backgroundColor: WidgetStateColor.resolveWith((states) =>
148-
designVariables.contextMenuItemBg.withValues(
149-
alpha: states.contains(WidgetState.pressed) ? 0.20 : 0.12))),
149+
designVariables.contextMenuItemBg.withFadedAlpha(
150+
states.contains(WidgetState.pressed) ? 0.20 : 0.12))),
150151
onPressed: () => _handlePressed(context),
151152
child: Text(label(zulipLocalizations),
152153
style: const TextStyle(fontSize: 20, height: 24 / 20)
@@ -168,8 +169,8 @@ class MessageActionSheetCancelButton extends StatelessWidget {
168169
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(7)),
169170
splashFactory: NoSplash.splashFactory,
170171
).copyWith(backgroundColor: WidgetStateColor.resolveWith((states) =>
171-
designVariables.contextMenuCancelBg.withValues(
172-
alpha: states.contains(WidgetState.pressed) ? 0.20 : 0.15))),
172+
designVariables.contextMenuCancelBg.withFadedAlpha(
173+
states.contains(WidgetState.pressed) ? 0.20 : 0.15))),
173174
onPressed: () {
174175
Navigator.pop(context);
175176
},

lib/widgets/color.dart

+17
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,21 @@ extension ColorExtension on Color {
3838
((g * 255.0).round() & 0xff) << 8 |
3939
((b * 255.0).round() & 0xff) << 0;
4040
}
41+
42+
/// Makes a copy of this color with [a] multiplied by `factor`.
43+
///
44+
/// `factor` must not be less than 0 or greater than 1.
45+
///
46+
/// To fade a color variable from [DesignVariables], [ContentTheme], etc.,
47+
/// use this instead of calling [withValues] with `factor` passed as `alpha`,
48+
/// which simply replaces the color's [a] instead of multiplying by it.
49+
/// Using [withValues] gives the same result for an opaque color,
50+
/// but a wrong result for a semi-transparent color,
51+
/// and we want our color variables to be free to change
52+
/// without breaking things.
53+
Color withFadedAlpha(double factor) {
54+
assert(factor >= 0);
55+
assert(factor <= 1);
56+
return withValues(alpha: a * factor);
57+
}
4158
}

lib/widgets/compose_box.dart

+3-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import '../model/compose.dart';
1414
import '../model/narrow.dart';
1515
import '../model/store.dart';
1616
import 'autocomplete.dart';
17+
import 'color.dart';
1718
import 'dialog.dart';
1819
import 'icons.dart';
1920
import 'store.dart';
@@ -663,7 +664,7 @@ abstract class _AttachUploadsButton extends StatelessWidget {
663664
return SizedBox(
664665
width: _composeButtonWidth,
665666
child: IconButton(
666-
icon: Icon(icon, color: designVariables.foreground.withValues(alpha: 0.5)),
667+
icon: Icon(icon, color: designVariables.foreground.withFadedAlpha(0.5)),
667668
tooltip: tooltip(zulipLocalizations),
668669
onPressed: () => _handlePress(context)));
669670
}
@@ -933,7 +934,7 @@ class _SendButtonState extends State<_SendButton> {
933934
final zulipLocalizations = ZulipLocalizations.of(context);
934935

935936
final iconColor = _hasValidationErrors
936-
? designVariables.icon.withValues(alpha: 0.5)
937+
? designVariables.icon.withFadedAlpha(0.5)
937938
: designVariables.icon;
938939

939940
return SizedBox(

test/widgets/color_test.dart

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import 'dart:ui';
2-
31
import 'package:checks/checks.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_checks/flutter_checks.dart';
44
import 'package:test/scaffolding.dart';
55
import 'package:zulip/widgets/color.dart';
66

@@ -14,5 +14,22 @@ void main() {
1414
check(Color(testCase).argbInt).equals(testCase);
1515
}
1616
});
17+
18+
test('withFadedAlpha smoke', () {
19+
const color = Color.fromRGBO(100, 200, 100, 0.5);
20+
21+
check(color.withFadedAlpha(0.5))
22+
.isSameColorAs(color.withValues(alpha: 0.25));
23+
24+
check(() => color.withFadedAlpha(1.1)).throws<AssertionError>();
25+
check(() => color.withFadedAlpha(-0.1)).throws<AssertionError>();
26+
});
27+
28+
test('withFadedAlpha opaque color', () {
29+
const color = Colors.black;
30+
31+
check(color.withFadedAlpha(0.5))
32+
.isSameColorAs(color.withValues(alpha: 0.5));
33+
});
1734
});
1835
}

test/widgets/compose_box_test.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import 'package:zulip/model/narrow.dart';
1717
import 'package:zulip/model/store.dart';
1818
import 'package:zulip/model/typing_status.dart';
1919
import 'package:zulip/widgets/app.dart';
20+
import 'package:zulip/widgets/color.dart';
2021
import 'package:zulip/widgets/compose_box.dart';
2122
import 'package:zulip/widgets/page.dart';
2223
import 'package:zulip/widgets/icons.dart';
@@ -439,7 +440,7 @@ void main() {
439440
final sendButtonWidget = sendButtonElement.widget as IconButton;
440441
final designVariables = DesignVariables.of(sendButtonElement);
441442
final expectedIconColor = expected
442-
? designVariables.icon.withValues(alpha: 0.5)
443+
? designVariables.icon.withFadedAlpha(0.5)
443444
: designVariables.icon;
444445
check(sendButtonWidget.icon)
445446
.isA<Icon>().color.isNotNull().isSameColorAs(expectedIconColor);

0 commit comments

Comments
 (0)