Skip to content

Commit

Permalink
action_sheet: Redesign bottom sheet
Browse files Browse the repository at this point in the history
Fixes: #90
  • Loading branch information
sm-sayedi committed Aug 2, 2024
1 parent c6abaf9 commit 3444df5
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 14 deletions.
80 changes: 66 additions & 14 deletions lib/widgets/action_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import '../model/narrow.dart';
import 'clipboard.dart';
import 'compose_box.dart';
import 'dialog.dart';
import 'draggable_scrollable_modal_bottom_sheet.dart';
import 'icons.dart';
import 'message_list.dart';
import 'store.dart';
import 'theme.dart';

/// Show a sheet of actions you can take on a message in the message list.
///
Expand All @@ -36,20 +36,46 @@ void showMessageActionSheet({required BuildContext context, required Message mes
&& reactionWithVotes.userIds.contains(store.selfUserId))
?? false;

showDraggableScrollableModalBottomSheet<void>(
final designVariables = DesignVariables.of(context);
showModalBottomSheet<void>(
context: context,
clipBehavior: Clip.antiAlias,
backgroundColor: designVariables.actionSheetBackground,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20.0))),
useSafeArea: true,
isScrollControlled: true,
builder: (BuildContext _) {
return Column(children: [
if (!hasThumbsUpReactionVote) AddThumbsUpButton(message: message, messageListContext: context),
StarButton(message: message, messageListContext: context),
if (isComposeBoxOffered) QuoteAndReplyButton(
message: message,
messageListContext: context,
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
// TODO(#217): show message text
Flexible(
child: SingleChildScrollView(
child: ClipRRect(
borderRadius: BorderRadius.circular(7),
child: Column(children: [
if (!hasThumbsUpReactionVote) AddThumbsUpButton(message: message, messageListContext: context),
StarButton(message: message, messageListContext: context),
if (isComposeBoxOffered) QuoteAndReplyButton(
message: message,
messageListContext: context,
),
CopyMessageTextButton(message: message, messageListContext: context),
CopyMessageLinkButton(message: message, messageListContext: context),
ShareButton(message: message, messageListContext: context),
// TODO: The following line could be replaced by the [spacing]
// property when https://github.com/flutter/flutter/issues/55378 is fixed.
].expand((item) => [const SizedBox(height: 1), item]).skip(1).toList()),
),
),
),
const MessageActionSheetCancelButton(),
],
),
CopyMessageTextButton(message: message, messageListContext: context),
CopyMessageLinkButton(message: message, messageListContext: context),
ShareButton(message: message, messageListContext: context),
]);
);
});
}

Expand All @@ -69,11 +95,16 @@ abstract class MessageActionSheetMenuItemButton extends StatelessWidget {

@override
Widget build(BuildContext context) {
final designVariables = DesignVariables.of(context);
final zulipLocalizations = ZulipLocalizations.of(context);
return MenuItemButton(
leadingIcon: Icon(icon),
trailingIcon: Icon(icon, color: designVariables.actionSheetMenuButtonForeground),
style: MenuItemButton.styleFrom(
backgroundColor: designVariables.actionSheetMenuButtonBackground,
foregroundColor: designVariables.actionSheetMenuButtonForeground,
),
onPressed: () => onPressed(context),
child: Text(label(zulipLocalizations)));
child: Text(label(zulipLocalizations), style: const TextStyle(fontSize: 16)));
}
}

Expand Down Expand Up @@ -402,3 +433,24 @@ class ShareButton extends MessageActionSheetMenuItemButton {
}
}
}

class MessageActionSheetCancelButton extends StatelessWidget {
const MessageActionSheetCancelButton({super.key});

@override
Widget build(BuildContext context) {
final designVariables = DesignVariables.of(context);
return ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 0,
backgroundColor: designVariables.actionSheetCancelButtonBackground,
foregroundColor: designVariables.actionSheetCancelButtonForeground,
shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(7)),
),
onPressed: () => Navigator.pop(context),
child: Text(ZulipLocalizations.of(context).dialogCancel,
style: const TextStyle(fontSize: 16)),
);
}
}
35 changes: 35 additions & 0 deletions lib/widgets/theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
mainBackground: const Color(0xfff0f0f0),
title: const Color(0xff1a1a1a),
channelColorSwatches: ChannelColorSwatches.light,
actionSheetBackground: const HSLColor.fromAHSL(1, 0, 0, 0.94).toColor(),
actionSheetCancelButtonBackground: const HSLColor.fromAHSL(0.15, 240, 0.05, 0.50).toColor(),
actionSheetCancelButtonForeground: const HSLColor.fromAHSL(1, 0, 0, 0.13).toColor(),
actionSheetMenuButtonBackground: const HSLColor.fromAHSL(0.12, 243.53, 0.69, 0.61).toColor(),
actionSheetMenuButtonForeground: const HSLColor.fromAHSL(1, 251.74, 0.70, 0.38).toColor(),
atMentionMarker: const HSLColor.fromAHSL(0.5, 0, 0, 0.2).toColor(),
dmHeaderBg: const HSLColor.fromAHSL(1, 46, 0.35, 0.93).toColor(),
loginOrDivider: const Color(0xffdedede),
Expand All @@ -160,6 +165,11 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
mainBackground: const Color(0xff1d1d1d),
title: const Color(0xffffffff),
channelColorSwatches: ChannelColorSwatches.dark,
actionSheetBackground: const HSLColor.fromAHSL(1, 0, 0, 0.14).toColor(),
actionSheetCancelButtonBackground: const HSLColor.fromAHSL(0.15, 240, 0.05, 0.50).toColor(),
actionSheetCancelButtonForeground: const HSLColor.fromAHSL(0.75, 0, 0, 1).toColor(),
actionSheetMenuButtonBackground: const HSLColor.fromAHSL(0.12, 240.89, 0.98, 0.73).toColor(),
actionSheetMenuButtonForeground: const HSLColor.fromAHSL(1, 237.17, 0.96, 0.78).toColor(),
// TODO(#95) need proper dark-theme color (this is ad hoc)
atMentionMarker: const HSLColor.fromAHSL(0.4, 0, 0, 1).toColor(),
dmHeaderBg: const HSLColor.fromAHSL(1, 46, 0.15, 0.2).toColor(),
Expand All @@ -183,6 +193,11 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
required this.mainBackground,
required this.title,
required this.channelColorSwatches,
required this.actionSheetBackground,
required this.actionSheetCancelButtonBackground,
required this.actionSheetCancelButtonForeground,
required this.actionSheetMenuButtonBackground,
required this.actionSheetMenuButtonForeground,
required this.atMentionMarker,
required this.dmHeaderBg,
required this.loginOrDivider,
Expand Down Expand Up @@ -216,6 +231,11 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
final ChannelColorSwatches channelColorSwatches;

// Not named variables in Figma; taken from older Figma drafts, or elsewhere.
final Color actionSheetBackground;
final Color actionSheetCancelButtonBackground;
final Color actionSheetCancelButtonForeground;
final Color actionSheetMenuButtonBackground;
final Color actionSheetMenuButtonForeground;
final Color atMentionMarker;
final Color dmHeaderBg;
final Color loginOrDivider; // TODO(#95) need proper dark-theme color (this is ad hoc)
Expand All @@ -236,6 +256,11 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
Color? mainBackground,
Color? title,
ChannelColorSwatches? channelColorSwatches,
Color? actionSheetBackground,
Color? actionSheetCancelButtonBackground,
Color? actionSheetCancelButtonForeground,
Color? actionSheetMenuButtonBackground,
Color? actionSheetMenuButtonForeground,
Color? atMentionMarker,
Color? dmHeaderBg,
Color? loginOrDivider,
Expand All @@ -255,6 +280,11 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
mainBackground: mainBackground ?? this.mainBackground,
title: title ?? this.title,
channelColorSwatches: channelColorSwatches ?? this.channelColorSwatches,
actionSheetBackground: actionSheetBackground ?? this.actionSheetBackground,
actionSheetCancelButtonBackground: actionSheetCancelButtonBackground ?? this.actionSheetCancelButtonBackground,
actionSheetCancelButtonForeground: actionSheetCancelButtonForeground ?? this.actionSheetCancelButtonForeground,
actionSheetMenuButtonBackground: actionSheetMenuButtonBackground ?? this.actionSheetMenuButtonBackground,
actionSheetMenuButtonForeground: actionSheetMenuButtonForeground ?? this.actionSheetMenuButtonBackground,
atMentionMarker: atMentionMarker ?? this.atMentionMarker,
dmHeaderBg: dmHeaderBg ?? this.dmHeaderBg,
loginOrDivider: loginOrDivider ?? this.loginOrDivider,
Expand All @@ -281,6 +311,11 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
mainBackground: Color.lerp(mainBackground, other.mainBackground, t)!,
title: Color.lerp(title, other.title, t)!,
channelColorSwatches: ChannelColorSwatches.lerp(channelColorSwatches, other.channelColorSwatches, t),
actionSheetBackground: Color.lerp(actionSheetBackground, other.actionSheetBackground, t)!,
actionSheetCancelButtonBackground: Color.lerp(actionSheetCancelButtonBackground, other.actionSheetCancelButtonBackground, t)!,
actionSheetCancelButtonForeground: Color.lerp(actionSheetCancelButtonForeground, other.actionSheetCancelButtonForeground, t)!,
actionSheetMenuButtonBackground: Color.lerp(actionSheetMenuButtonBackground, other.actionSheetMenuButtonBackground, t)!,
actionSheetMenuButtonForeground: Color.lerp(actionSheetMenuButtonForeground, other.actionSheetMenuButtonBackground, t)!,
atMentionMarker: Color.lerp(atMentionMarker, other.atMentionMarker, t)!,
dmHeaderBg: Color.lerp(dmHeaderBg, other.dmHeaderBg, t)!,
loginOrDivider: Color.lerp(loginOrDivider, other.loginOrDivider, t)!,
Expand Down
33 changes: 33 additions & 0 deletions test/widgets/action_sheet_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -542,4 +542,37 @@ void main() {
check(mockSharePlus.sharedString).isNull();
});
});

group('MessageActionSheetCancelButton', () {
final zulipLocalizations = GlobalLocalizations.zulipLocalizations;

Finder cancelButtonFinder() => find.text(zulipLocalizations.dialogCancel);

void checkActionSheet(WidgetTester tester, {required bool isShown}) {
// TODO(i18n) skip translation for now
check(find.text('React with 👍').evaluate().length).equals(isShown ? 1 : 0);
check(find.text(zulipLocalizations.actionSheetOptionStarMessage)
.evaluate().length).equals(isShown ? 1 : 0);
check(find.text(zulipLocalizations.actionSheetOptionQuoteAndReply)
.evaluate().length).equals(isShown ? 1 : 0);
check(find.text(zulipLocalizations.actionSheetOptionCopyMessageText)
.evaluate().length).equals(isShown ? 1 : 0);
check(find.text(zulipLocalizations.actionSheetOptionCopyMessageLink)
.evaluate().length).equals(isShown ? 1 : 0);
check(find.text(zulipLocalizations.actionSheetOptionShare)
.evaluate().length).equals(isShown ? 1 : 0);

check(cancelButtonFinder().evaluate().length).equals(isShown ? 1 : 0);
}

testWidgets('pressing the button dismisses the action sheet', (tester) async {
final message = eg.streamMessage();
await setupToMessageActionSheet(tester, message: message, narrow: TopicNarrow.ofMessage(message));
checkActionSheet(tester, isShown: true);

await tester.tap(cancelButtonFinder());
await tester.pumpAndSettle();
checkActionSheet(tester, isShown: false);
});
});
}

0 comments on commit 3444df5

Please sign in to comment.