diff --git a/lib/widgets/inbox.dart b/lib/widgets/inbox.dart index dcbd1acdb2..0f84a4373d 100644 --- a/lib/widgets/inbox.dart +++ b/lib/widgets/inbox.dart @@ -291,7 +291,7 @@ abstract class _HeaderItem extends StatelessWidget { overflow: TextOverflow.ellipsis, title))), const SizedBox(width: 12), - if (hasMention) const _AtMentionMarker(), + if (hasMention) const _IconMarker(icon: ZulipIcons.at_sign), Padding(padding: const EdgeInsetsDirectional.only(end: 16), child: UnreadCountBadge( backgroundColor: unreadCountBadgeBackgroundColor(context), @@ -414,7 +414,7 @@ class _DmItem extends StatelessWidget { overflow: TextOverflow.ellipsis, title))), const SizedBox(width: 12), - if (hasMention) const _AtMentionMarker(), + if (hasMention) const _IconMarker(icon: ZulipIcons.at_sign), Padding(padding: const EdgeInsetsDirectional.only(end: 16), child: UnreadCountBadge(backgroundColor: null, count: count)), @@ -539,7 +539,7 @@ class _TopicItem extends StatelessWidget { overflow: TextOverflow.ellipsis, topic))), const SizedBox(width: 12), - if (hasMention) const _AtMentionMarker(), + if (hasMention) const _IconMarker(icon: ZulipIcons.at_sign), Padding(padding: const EdgeInsetsDirectional.only(end: 16), child: UnreadCountBadge( backgroundColor: colorSwatchFor(context, subscription), @@ -548,16 +548,20 @@ class _TopicItem extends StatelessWidget { } } -class _AtMentionMarker extends StatelessWidget { - const _AtMentionMarker(); +class _IconMarker extends StatelessWidget { + const _IconMarker({required this.icon}); + + final IconData icon; @override Widget build(BuildContext context) { final designVariables = DesignVariables.of(context); - // Design for at-mention marker based on Figma screen: + // Design for icon markers based on Figma screen: // https://www.figma.com/file/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?type=design&node-id=224-16386&mode=design&t=JsNndFQ8fKFH0SjS-0 return Padding( padding: const EdgeInsetsDirectional.only(end: 4), - child: Icon(ZulipIcons.at_sign, size: 14, color: designVariables.atMentionMarker)); + // This color comes from the Figma screen for the "@" marker, but not + // the topic visibility markers. + child: Icon(icon, size: 14, color: designVariables.inboxItemIconMarker)); } } diff --git a/lib/widgets/theme.dart b/lib/widgets/theme.dart index 9dbb340d56..282decd473 100644 --- a/lib/widgets/theme.dart +++ b/lib/widgets/theme.dart @@ -135,13 +135,13 @@ class DesignVariables extends ThemeExtension { textInput: const Color(0xff000000), title: const Color(0xff1a1a1a), channelColorSwatches: ChannelColorSwatches.light, - atMentionMarker: const HSLColor.fromAHSL(0.5, 0, 0, 0.2).toColor(), colorMessageHeaderIconInteractive: Colors.black.withValues(alpha: 0.2), contextMenuCancelBg: const Color(0xff797986).withValues(alpha: 0.15), contextMenuCancelPressedBg: const Color(0xff797986).withValues(alpha: 0.20), dmHeaderBg: const HSLColor.fromAHSL(1, 46, 0.35, 0.93).toColor(), groupDmConversationIcon: Colors.black.withValues(alpha: 0.5), groupDmConversationIconBg: const Color(0x33808080), + inboxItemIconMarker: const HSLColor.fromAHSL(0.5, 0, 0, 0.2).toColor(), loginOrDivider: const Color(0xffdedede), loginOrDividerText: const Color(0xff575757), modalBarrierColor: const Color(0xff000000).withValues(alpha: 0.3), @@ -180,13 +180,13 @@ class DesignVariables extends ThemeExtension { contextMenuCancelBg: const Color(0xff797986).withValues(alpha: 0.15), // the same as the light mode in Figma contextMenuCancelPressedBg: const Color(0xff797986).withValues(alpha: 0.20), // the same as the light mode in Figma // TODO(design-dark) need proper dark-theme color (this is ad hoc) - atMentionMarker: const HSLColor.fromAHSL(0.4, 0, 0, 1).toColor(), colorMessageHeaderIconInteractive: Colors.white.withValues(alpha: 0.2), dmHeaderBg: const HSLColor.fromAHSL(1, 46, 0.15, 0.2).toColor(), // TODO(design-dark) need proper dark-theme color (this is ad hoc) groupDmConversationIcon: Colors.white.withValues(alpha: 0.5), // TODO(design-dark) need proper dark-theme color (this is ad hoc) groupDmConversationIconBg: const Color(0x33cccccc), + inboxItemIconMarker: const HSLColor.fromAHSL(0.4, 0, 0, 1).toColor(), loginOrDivider: const Color(0xff424242), loginOrDividerText: const Color(0xffa8a8a8), modalBarrierColor: const Color(0xff000000).withValues(alpha: 0.5), @@ -226,13 +226,13 @@ class DesignVariables extends ThemeExtension { required this.textInput, required this.title, required this.channelColorSwatches, - required this.atMentionMarker, required this.colorMessageHeaderIconInteractive, required this.contextMenuCancelBg, required this.contextMenuCancelPressedBg, required this.dmHeaderBg, required this.groupDmConversationIcon, required this.groupDmConversationIconBg, + required this.inboxItemIconMarker, required this.loginOrDivider, required this.loginOrDividerText, required this.modalBarrierColor, @@ -280,13 +280,13 @@ class DesignVariables extends ThemeExtension { final ChannelColorSwatches channelColorSwatches; // Not named variables in Figma; taken from older Figma drafts, or elsewhere. - final Color atMentionMarker; final Color colorMessageHeaderIconInteractive; final Color contextMenuCancelBg; // In Figma, but unnamed. final Color contextMenuCancelPressedBg; // In Figma, but unnamed. final Color dmHeaderBg; final Color groupDmConversationIcon; final Color groupDmConversationIconBg; + final Color inboxItemIconMarker; final Color loginOrDivider; // TODO(design-dark) need proper dark-theme color (this is ad hoc) final Color loginOrDividerText; // TODO(design-dark) need proper dark-theme color (this is ad hoc) final Color modalBarrierColor; @@ -321,13 +321,13 @@ class DesignVariables extends ThemeExtension { Color? textInput, Color? title, ChannelColorSwatches? channelColorSwatches, - Color? atMentionMarker, Color? colorMessageHeaderIconInteractive, Color? contextMenuCancelBg, Color? contextMenuCancelPressedBg, Color? dmHeaderBg, Color? groupDmConversationIcon, Color? groupDmConversationIconBg, + Color? inboxItemIconMarker, Color? loginOrDivider, Color? loginOrDividerText, Color? modalBarrierColor, @@ -361,13 +361,13 @@ class DesignVariables extends ThemeExtension { textInput: textInput ?? this.textInput, title: title ?? this.title, channelColorSwatches: channelColorSwatches ?? this.channelColorSwatches, - atMentionMarker: atMentionMarker ?? this.atMentionMarker, colorMessageHeaderIconInteractive: colorMessageHeaderIconInteractive ?? this.colorMessageHeaderIconInteractive, contextMenuCancelBg: contextMenuCancelBg ?? this.contextMenuCancelBg, contextMenuCancelPressedBg: contextMenuCancelPressedBg ?? this.contextMenuCancelPressedBg, dmHeaderBg: dmHeaderBg ?? this.dmHeaderBg, groupDmConversationIcon: groupDmConversationIcon ?? this.groupDmConversationIcon, groupDmConversationIconBg: groupDmConversationIconBg ?? this.groupDmConversationIconBg, + inboxItemIconMarker: inboxItemIconMarker ?? this.inboxItemIconMarker, loginOrDivider: loginOrDivider ?? this.loginOrDivider, loginOrDividerText: loginOrDividerText ?? this.loginOrDividerText, modalBarrierColor: modalBarrierColor ?? this.modalBarrierColor, @@ -408,13 +408,13 @@ class DesignVariables extends ThemeExtension { textInput: Color.lerp(textInput, other.textInput, t)!, title: Color.lerp(title, other.title, t)!, channelColorSwatches: ChannelColorSwatches.lerp(channelColorSwatches, other.channelColorSwatches, t), - atMentionMarker: Color.lerp(atMentionMarker, other.atMentionMarker, t)!, colorMessageHeaderIconInteractive: Color.lerp(colorMessageHeaderIconInteractive, other.colorMessageHeaderIconInteractive, t)!, contextMenuCancelBg: Color.lerp(contextMenuCancelBg, other.contextMenuCancelBg, t)!, contextMenuCancelPressedBg: Color.lerp(contextMenuCancelPressedBg, other.contextMenuCancelPressedBg, t)!, dmHeaderBg: Color.lerp(dmHeaderBg, other.dmHeaderBg, t)!, groupDmConversationIcon: Color.lerp(groupDmConversationIcon, other.groupDmConversationIcon, t)!, groupDmConversationIconBg: Color.lerp(groupDmConversationIconBg, other.groupDmConversationIconBg, t)!, + inboxItemIconMarker: Color.lerp(inboxItemIconMarker, other.inboxItemIconMarker, t)!, loginOrDivider: Color.lerp(loginOrDivider, other.loginOrDivider, t)!, loginOrDividerText: Color.lerp(loginOrDividerText, other.loginOrDividerText, t)!, modalBarrierColor: Color.lerp(modalBarrierColor, other.modalBarrierColor, t)!, diff --git a/test/widgets/inbox_test.dart b/test/widgets/inbox_test.dart index 12e2c78800..82cc216189 100644 --- a/test/widgets/inbox_test.dart +++ b/test/widgets/inbox_test.dart @@ -182,6 +182,17 @@ void main() { )); } + bool hasIcon(WidgetTester tester, { + required Widget? parent, + required IconData icon, + }) { + check(parent).isNotNull(); + return tester.widgetList(find.descendant( + of: find.byWidget(parent!), + matching: find.byIcon(icon), + )).isNotEmpty; + } + group('InboxPage', () { testWidgets('page builds; empty', (tester) async { await setupPage(tester, unreadMessages: []); @@ -246,13 +257,8 @@ void main() { final subscription = eg.subscription(stream); const topic = 'lunch'; - bool hasAtSign(WidgetTester tester, Widget? parent) { - check(parent).isNotNull(); - return tester.widgetList(find.descendant( - of: find.byWidget(parent!), - matching: find.byIcon(ZulipIcons.at_sign), - )).isNotEmpty; - } + bool hasAtSign(WidgetTester tester, Widget? parent) => + hasIcon(tester, parent: parent, icon: ZulipIcons.at_sign); testWidgets('topic with a mention', (tester) async { await setupPage(tester,