Skip to content

Make {MessageList,EmojiReaction}Theme.{light,dark} static final fields #1276

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 30 additions & 32 deletions lib/widgets/emoji_reaction.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,36 @@ import 'theme.dart';

/// Emoji-reaction styles that differ between light and dark themes.
class EmojiReactionTheme extends ThemeExtension<EmojiReactionTheme> {
EmojiReactionTheme.light() :
this._(
bgSelected: Colors.white,

// TODO shadow effect, following web, which uses `box-shadow: inset`:
// https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow#inset
// Needs Flutter support for something like that:
// https://github.com/flutter/flutter/issues/18636
// https://github.com/flutter/flutter/issues/52999
// Until then use a solid color; a much-lightened version of the shadow color.
// Also adapt by making [borderUnselected] more transparent, so we'll
// want to check that against web when implementing the shadow.
bgUnselected: const HSLColor.fromAHSL(0.08, 210, 0.50, 0.875).toColor(),

borderSelected: Colors.black.withValues(alpha: 0.45),

// TODO see TODO on [bgUnselected] about shadow effect
borderUnselected: Colors.black.withValues(alpha: 0.05),

textSelected: const HSLColor.fromAHSL(1, 210, 0.20, 0.20).toColor(),
textUnselected: const HSLColor.fromAHSL(1, 210, 0.20, 0.25).toColor(),
);

EmojiReactionTheme.dark() :
this._(
bgSelected: Colors.black.withValues(alpha: 0.8),
bgUnselected: Colors.black.withValues(alpha: 0.3),
borderSelected: Colors.white.withValues(alpha: 0.75),
borderUnselected: Colors.white.withValues(alpha: 0.15),
textSelected: Colors.white.withValues(alpha: 0.85),
textUnselected: Colors.white.withValues(alpha: 0.75),
);
static final light = EmojiReactionTheme._(
bgSelected: Colors.white,

// TODO shadow effect, following web, which uses `box-shadow: inset`:
// https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow#inset
// Needs Flutter support for something like that:
// https://github.com/flutter/flutter/issues/18636
// https://github.com/flutter/flutter/issues/52999
// Until then use a solid color; a much-lightened version of the shadow color.
// Also adapt by making [borderUnselected] more transparent, so we'll
// want to check that against web when implementing the shadow.
bgUnselected: const HSLColor.fromAHSL(0.08, 210, 0.50, 0.875).toColor(),

borderSelected: Colors.black.withValues(alpha: 0.45),

// TODO see TODO on [bgUnselected] about shadow effect
borderUnselected: Colors.black.withValues(alpha: 0.05),

textSelected: const HSLColor.fromAHSL(1, 210, 0.20, 0.20).toColor(),
textUnselected: const HSLColor.fromAHSL(1, 210, 0.20, 0.25).toColor(),
);

static final dark = EmojiReactionTheme._(
bgSelected: Colors.black.withValues(alpha: 0.8),
bgUnselected: Colors.black.withValues(alpha: 0.3),
borderSelected: Colors.white.withValues(alpha: 0.75),
borderUnselected: Colors.white.withValues(alpha: 0.15),
textSelected: Colors.white.withValues(alpha: 0.85),
textUnselected: Colors.white.withValues(alpha: 0.75),
);

EmojiReactionTheme._({
required this.bgSelected,
Expand Down
98 changes: 48 additions & 50 deletions lib/widgets/message_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,56 +27,54 @@ import 'theme.dart';

/// Message-list styles that differ between light and dark themes.
class MessageListTheme extends ThemeExtension<MessageListTheme> {
MessageListTheme.light() :
this._(
dateSeparator: Colors.black,
dateSeparatorText: const HSLColor.fromAHSL(0.75, 0, 0, 0.15).toColor(),
dmRecipientHeaderBg: const HSLColor.fromAHSL(1, 46, 0.35, 0.93).toColor(),
messageTimestamp: const HSLColor.fromAHSL(0.8, 0, 0, 0.2).toColor(),
recipientHeaderText: const HSLColor.fromAHSL(1, 0, 0, 0.15).toColor(),
senderBotIcon: const HSLColor.fromAHSL(1, 180, 0.08, 0.65).toColor(),
senderName: const HSLColor.fromAHSL(1, 0, 0, 0.2).toColor(),
streamMessageBgDefault: Colors.white,
streamRecipientHeaderChevronRight: Colors.black.withValues(alpha: 0.3),

// From the Figma mockup at:
// https://www.figma.com/file/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=132-9684
// See discussion about design at:
// https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/flutter.3A.20unread.20marker/near/1658008
// (Web uses a left-to-right gradient from hsl(217deg 64% 59%) to transparent,
// in both light and dark theme.)
unreadMarker: const HSLColor.fromAHSL(1, 227, 0.78, 0.59).toColor(),

unreadMarkerGap: Colors.white.withValues(alpha: 0.6),

// TODO(design) this seems ad-hoc; is there a better color?
unsubscribedStreamRecipientHeaderBg: const Color(0xfff5f5f5),
);

MessageListTheme.dark() :
this._(
dateSeparator: Colors.white,
dateSeparatorText: const HSLColor.fromAHSL(0.75, 0, 0, 1).toColor(),
dmRecipientHeaderBg: const HSLColor.fromAHSL(1, 46, 0.15, 0.2).toColor(),
messageTimestamp: const HSLColor.fromAHSL(0.8, 0, 0, 0.85).toColor(),
recipientHeaderText: const HSLColor.fromAHSL(0.8, 0, 0, 1).toColor(),
senderBotIcon: const HSLColor.fromAHSL(1, 180, 0.05, 0.5).toColor(),
senderName: const HSLColor.fromAHSL(0.85, 0, 0, 1).toColor(),
streamMessageBgDefault: const HSLColor.fromAHSL(1, 0, 0, 0.15).toColor(),
streamRecipientHeaderChevronRight: Colors.white.withValues(alpha: 0.3),

// 0.75 opacity from here:
// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=807-33998&m=dev
// Discussion, some weeks after the discussion linked on the light variant:
// https://github.com/zulip/zulip-flutter/pull/317#issuecomment-1784311663
// where Vlad includes screenshots that look like they're from there.
unreadMarker: const HSLColor.fromAHSL(0.75, 227, 0.78, 0.59).toColor(),

unreadMarkerGap: Colors.transparent,

// TODO(design) this is ad-hoc and untested; is there a better color?
unsubscribedStreamRecipientHeaderBg: const Color(0xff0a0a0a),
);
static final light = MessageListTheme._(
dateSeparator: Colors.black,
dateSeparatorText: const HSLColor.fromAHSL(0.75, 0, 0, 0.15).toColor(),
dmRecipientHeaderBg: const HSLColor.fromAHSL(1, 46, 0.35, 0.93).toColor(),
messageTimestamp: const HSLColor.fromAHSL(0.8, 0, 0, 0.2).toColor(),
recipientHeaderText: const HSLColor.fromAHSL(1, 0, 0, 0.15).toColor(),
senderBotIcon: const HSLColor.fromAHSL(1, 180, 0.08, 0.65).toColor(),
senderName: const HSLColor.fromAHSL(1, 0, 0, 0.2).toColor(),
streamMessageBgDefault: Colors.white,
streamRecipientHeaderChevronRight: Colors.black.withValues(alpha: 0.3),

// From the Figma mockup at:
// https://www.figma.com/file/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=132-9684
// See discussion about design at:
// https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/flutter.3A.20unread.20marker/near/1658008
// (Web uses a left-to-right gradient from hsl(217deg 64% 59%) to transparent,
// in both light and dark theme.)
unreadMarker: const HSLColor.fromAHSL(1, 227, 0.78, 0.59).toColor(),

unreadMarkerGap: Colors.white.withValues(alpha: 0.6),

// TODO(design) this seems ad-hoc; is there a better color?
unsubscribedStreamRecipientHeaderBg: const Color(0xfff5f5f5),
);

static final dark = MessageListTheme._(
dateSeparator: Colors.white,
dateSeparatorText: const HSLColor.fromAHSL(0.75, 0, 0, 1).toColor(),
dmRecipientHeaderBg: const HSLColor.fromAHSL(1, 46, 0.15, 0.2).toColor(),
messageTimestamp: const HSLColor.fromAHSL(0.8, 0, 0, 0.85).toColor(),
recipientHeaderText: const HSLColor.fromAHSL(0.8, 0, 0, 1).toColor(),
senderBotIcon: const HSLColor.fromAHSL(1, 180, 0.05, 0.5).toColor(),
senderName: const HSLColor.fromAHSL(0.85, 0, 0, 1).toColor(),
streamMessageBgDefault: const HSLColor.fromAHSL(1, 0, 0, 0.15).toColor(),
streamRecipientHeaderChevronRight: Colors.white.withValues(alpha: 0.3),

// 0.75 opacity from here:
// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=807-33998&m=dev
// Discussion, some weeks after the discussion linked on the light variant:
// https://github.com/zulip/zulip-flutter/pull/317#issuecomment-1784311663
// where Vlad includes screenshots that look like they're from there.
unreadMarker: const HSLColor.fromAHSL(0.75, 227, 0.78, 0.59).toColor(),

unreadMarkerGap: Colors.transparent,

// TODO(design) this is ad-hoc and untested; is there a better color?
unsubscribedStreamRecipientHeaderBg: const Color(0xff0a0a0a),
);

MessageListTheme._({
required this.dateSeparator,
Expand Down
8 changes: 4 additions & 4 deletions lib/widgets/theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ ThemeData zulipThemeData(BuildContext context) {
themeExtensions = [
ContentTheme.light(context),
designVariables,
EmojiReactionTheme.light(),
MessageListTheme.light(),
EmojiReactionTheme.light,
MessageListTheme.light,
];
}
case Brightness.dark: {
designVariables = DesignVariables.dark;
themeExtensions = [
ContentTheme.dark(context),
designVariables,
EmojiReactionTheme.dark(),
MessageListTheme.dark(),
EmojiReactionTheme.dark,
MessageListTheme.dark,
];
}
}
Expand Down
10 changes: 5 additions & 5 deletions test/widgets/emoji_reaction_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -251,25 +251,25 @@ void main() {
}

check(backgroundColor('smile')).isNotNull()
.isSameColorAs(EmojiReactionTheme.light().bgSelected);
.isSameColorAs(EmojiReactionTheme.light.bgSelected);
check(backgroundColor('tada')).isNotNull()
.isSameColorAs(EmojiReactionTheme.light().bgUnselected);
.isSameColorAs(EmojiReactionTheme.light.bgUnselected);

tester.platformDispatcher.platformBrightnessTestValue = Brightness.dark;
await tester.pump();

await tester.pump(kThemeAnimationDuration * 0.4);
final expectedLerped = EmojiReactionTheme.light().lerp(EmojiReactionTheme.dark(), 0.4);
final expectedLerped = EmojiReactionTheme.light.lerp(EmojiReactionTheme.dark, 0.4);
check(backgroundColor('smile')).isNotNull()
.isSameColorAs(expectedLerped.bgSelected);
check(backgroundColor('tada')).isNotNull()
.isSameColorAs(expectedLerped.bgUnselected);

await tester.pump(kThemeAnimationDuration * 0.6);
check(backgroundColor('smile')).isNotNull()
.isSameColorAs(EmojiReactionTheme.dark().bgSelected);
.isSameColorAs(EmojiReactionTheme.dark.bgSelected);
check(backgroundColor('tada')).isNotNull()
.isSameColorAs(EmojiReactionTheme.dark().bgUnselected);
.isSameColorAs(EmojiReactionTheme.dark.bgUnselected);
});

testWidgets('use emoji font', (tester) async {
Expand Down
6 changes: 3 additions & 3 deletions test/widgets/message_list_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -207,17 +207,17 @@ void main() {
return widget.color;
}

check(backgroundColor()).isSameColorAs(MessageListTheme.light().streamMessageBgDefault);
check(backgroundColor()).isSameColorAs(MessageListTheme.light.streamMessageBgDefault);

tester.platformDispatcher.platformBrightnessTestValue = Brightness.dark;
await tester.pump();

await tester.pump(kThemeAnimationDuration * 0.4);
final expectedLerped = MessageListTheme.light().lerp(MessageListTheme.dark(), 0.4);
final expectedLerped = MessageListTheme.light.lerp(MessageListTheme.dark, 0.4);
check(backgroundColor()).isSameColorAs(expectedLerped.streamMessageBgDefault);

await tester.pump(kThemeAnimationDuration * 0.6);
check(backgroundColor()).isSameColorAs(MessageListTheme.dark().streamMessageBgDefault);
check(backgroundColor()).isSameColorAs(MessageListTheme.dark.streamMessageBgDefault);
});

group('fetch older messages on scroll', () {
Expand Down