From b0ad9c673e79a3025da278b569f301659a1f1f6b Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Fri, 16 Oct 2020 12:03:04 +0200 Subject: [PATCH] fix reaction modal ui --- example/ios/Flutter/.last_build_id | 2 +- example/ios/Podfile.lock | 8 +- example/pubspec.yaml | 2 +- lib/src/channel_bottom_sheet.dart | 2 +- lib/src/message_actions_modal.dart | 1 + lib/src/message_reactions_modal.dart | 178 +++++++++++++++++---------- lib/src/message_widget.dart | 1 + lib/src/reaction_picker.dart | 93 ++++++++------ 8 files changed, 175 insertions(+), 112 deletions(-) diff --git a/example/ios/Flutter/.last_build_id b/example/ios/Flutter/.last_build_id index e3266027..171fde31 100644 --- a/example/ios/Flutter/.last_build_id +++ b/example/ios/Flutter/.last_build_id @@ -1 +1 @@ -06fe8d0d3d89937a6d33b1033e75ae96 \ No newline at end of file +0289cdadbd29bab804f275e3c5907d07 \ No newline at end of file diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index f289e1b7..23f0045b 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -38,10 +38,10 @@ PODS: - Firebase/Messaging (6.26.0): - Firebase/CoreOnly - FirebaseMessaging (~> 4.4.1) - - firebase_core (0.5.0): + - firebase_core (0.5.0-1): - Firebase/CoreOnly (~> 6.26.0) - Flutter - - firebase_messaging (7.0.2): + - firebase_messaging (7.0.3): - Firebase/CoreOnly (~> 6.26.0) - Firebase/Messaging (~> 6.26.0) - firebase_core @@ -233,8 +233,8 @@ SPEC CHECKSUMS: DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1 Firebase: 7cf5f9c67f03cb3b606d1d6535286e1080e57eb6 - firebase_core: 3134fe79d257d430f163b558caf52a10a87efe8a - firebase_messaging: 2844c37f9ce87c0904b38fe435223161b1a71528 + firebase_core: 00e54a4744164a6b5a250b96dd1ad5afaba7a342 + firebase_messaging: 666d9994651b1ecf8c582b52dd913f3fa58c17ef FirebaseAnalyticsInterop: 3f86269c38ae41f47afeb43ebf32a001f58fcdae FirebaseCore: f42e5e5f382cdcf6b617ed737bf6c871a6947b17 FirebaseCoreDiagnostics: 770ac5958e1372ce67959ae4b4f31d8e127c3ac1 diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 457e72e4..a5a2f73f 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,7 +1,7 @@ name: example description: A new Flutter project. -version: 1.0.29+31 +version: 1.0.30+32 environment: sdk: ">=2.2.2 <3.0.0" diff --git a/lib/src/channel_bottom_sheet.dart b/lib/src/channel_bottom_sheet.dart index 187fc6a9..0de24270 100644 --- a/lib/src/channel_bottom_sheet.dart +++ b/lib/src/channel_bottom_sheet.dart @@ -154,7 +154,7 @@ class ChannelBottomSheet extends StatelessWidget { height: 83, child: ListView( padding: EdgeInsets.only( - left: (MediaQuery.of(context).size.width / 2) - 48, + left: (MediaQuery.of(context).size.width / 2) - 80, ), scrollDirection: Axis.horizontal, children: snapshot.data.map((m) { diff --git a/lib/src/message_actions_modal.dart b/lib/src/message_actions_modal.dart index 31086885..012a2c9f 100644 --- a/lib/src/message_actions_modal.dart +++ b/lib/src/message_actions_modal.dart @@ -1,5 +1,6 @@ import 'dart:ui'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat_flutter/src/reaction_picker.dart'; diff --git a/lib/src/message_reactions_modal.dart b/lib/src/message_reactions_modal.dart index 538fbd92..90e1fb97 100644 --- a/lib/src/message_reactions_modal.dart +++ b/lib/src/message_reactions_modal.dart @@ -22,6 +22,7 @@ class MessageReactionsModal extends StatelessWidget { final bool showReply; final bool reverse; final ShapeBorder messageShape; + final void Function(User) onUserAvatarTap; const MessageReactionsModal({ Key key, @@ -35,6 +36,7 @@ class MessageReactionsModal extends StatelessWidget { this.editMessageInputBuilder, this.messageShape, this.reverse, + this.onUserAvatarTap, }) : super(key: key); @override @@ -87,79 +89,119 @@ class MessageReactionsModal extends StatelessWidget { ), ), SizedBox( - height: 8, + height: 16, ), if (message.latestReactions.isNotEmpty) - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - ), - child: Card( - clipBehavior: Clip.hardEdge, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - child: GridView.builder( - shrinkWrap: true, - padding: const EdgeInsets.all(16.0), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 4, - crossAxisSpacing: 16, - childAspectRatio: 0.8, - mainAxisSpacing: 22, - ), - itemCount: message.latestReactions.length, - itemBuilder: (context, i) { - final reaction = message.latestReactions[i]; - final isCurrentUser = - reaction.user.id == StreamChat.of(context).user.id; - return Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Stack( - children: [ - UserAvatar( - user: reaction.user, - constraints: BoxConstraints.tightFor( - height: 64, - width: 64, - ), - borderRadius: BorderRadius.circular(32), - ), - Positioned( - child: ReactionBubble( - reactions: [reaction], - borderColor: isCurrentUser - ? messageTheme.ownReactionsBorderColor - : messageTheme.otherReactionsBorderColor, - backgroundColor: isCurrentUser - ? messageTheme.ownReactionsBackgroundColor - : messageTheme - .otherReactionsBackgroundColor, - flipTail: !isCurrentUser, - ), - bottom: 0, - left: isCurrentUser ? 0 : null, - right: isCurrentUser ? 0 : null, - ), - ], - ), - Text( - reaction.user.name, - style: Theme.of(context).textTheme.subtitle2, - textAlign: TextAlign.center, - ), - ], - ); - }, - ), - ), - ) + Container( + constraints: BoxConstraints.loose(Size.fromHeight(400)), + child: _buildReactionCard(context), + ), ], ), ], ); } + + Padding _buildReactionCard(BuildContext context) { + final currentUser = StreamChat.of(context).user; + return Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + ), + child: Card( + clipBehavior: Clip.hardEdge, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.all(16.0), + child: Text( + 'Message Reactions', + style: Theme.of(context).textTheme.headline6, + ), + ), + Flexible( + child: Padding( + padding: const EdgeInsets.only( + left: 16.0, + right: 16, + bottom: 16, + ), + child: GridView.builder( + shrinkWrap: true, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + crossAxisSpacing: 16, + childAspectRatio: 0.75, + mainAxisSpacing: 22, + ), + itemCount: message.latestReactions.length, + itemBuilder: (context, i) { + final reaction = message.latestReactions[i]; + + return _buildReaction( + reaction, + currentUser, + context, + ); + }, + ), + ), + ), + ], + ), + ), + ); + } + + Column _buildReaction( + Reaction reaction, + User currentUser, + BuildContext context, + ) { + final isCurrentUser = reaction.user.id == currentUser.id; + return Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Stack( + children: [ + UserAvatar( + onTap: onUserAvatarTap, + user: reaction.user, + constraints: BoxConstraints.tightFor( + height: 64, + width: 64, + ), + borderRadius: BorderRadius.circular(32), + ), + Positioned( + child: ReactionBubble( + reactions: [reaction], + borderColor: isCurrentUser + ? messageTheme.ownReactionsBorderColor + : messageTheme.otherReactionsBorderColor, + backgroundColor: isCurrentUser + ? messageTheme.ownReactionsBackgroundColor + : messageTheme.otherReactionsBackgroundColor, + flipTail: !isCurrentUser, + ), + bottom: 0, + left: isCurrentUser ? 0 : null, + right: isCurrentUser ? 0 : null, + ), + ], + ), + Text( + reaction.user.name, + style: Theme.of(context).textTheme.subtitle2, + textAlign: TextAlign.center, + ), + ], + ); + } } diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index fccaa1e4..ef4eba2d 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -485,6 +485,7 @@ class _MessageWidgetState extends State { return StreamChannel( channel: channel, child: MessageReactionsModal( + onUserAvatarTap: widget.onUserAvatarTap, messageTheme: widget.messageTheme, messageShape: widget.shape ?? _getDefaultShape(context), reverse: widget.reverse, diff --git a/lib/src/reaction_picker.dart b/lib/src/reaction_picker.dart index 3b890230..ddeb6ad5 100644 --- a/lib/src/reaction_picker.dart +++ b/lib/src/reaction_picker.dart @@ -1,4 +1,7 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; +import 'package:stream_chat_flutter/src/reaction_bubble.dart'; import '../stream_chat_flutter.dart'; @@ -23,44 +26,60 @@ class ReactionPicker extends StatelessWidget { @override Widget build(BuildContext context) { final reactionAssets = StreamChatTheme.of(context).reactionIcons; - return Material( - color: messageTheme.ownReactionsBackgroundColor, - clipBehavior: Clip.hardEdge, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(24), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.min, - children: reactionAssets.map((reactionIcon) { - final ownReactionIndex = message.ownReactions?.indexWhere( - (reaction) => reaction.type == reactionIcon.type) ?? - -1; - return IconButton( - iconSize: 24, - icon: Icon( - reactionIcon.iconData, - color: ownReactionIndex != -1 - ? StreamChatTheme.of(context).accentColor - : Theme.of(context).iconTheme.color, + return Stack( + fit: StackFit.passthrough, + children: [ + Material( + color: messageTheme.ownReactionsBackgroundColor, + clipBehavior: Clip.hardEdge, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: reactionAssets.map((reactionIcon) { + final ownReactionIndex = message.ownReactions?.indexWhere( + (reaction) => reaction.type == reactionIcon.type) ?? + -1; + return IconButton( + iconSize: 24, + icon: Icon( + reactionIcon.iconData, + color: ownReactionIndex != -1 + ? StreamChatTheme.of(context).accentColor + : Theme.of(context).iconTheme.color, + ), + onPressed: () { + if (ownReactionIndex != -1) { + removeReaction( + context, + message.ownReactions[ownReactionIndex], + ); + } else { + sendReaction( + context, + reactionIcon.type, + ); + } + }, + ); + }).toList(), + ), + ), + Positioned( + right: 14, + bottom: 0, + child: CustomPaint( + painter: ReactionBubblePainter( + messageTheme.ownReactionsBackgroundColor, + messageTheme.ownReactionsBorderColor, + 2, ), - onPressed: () { - if (ownReactionIndex != -1) { - removeReaction( - context, - message.ownReactions[ownReactionIndex], - ); - } else { - sendReaction( - context, - reactionIcon.type, - ); - } - }, - ); - }).toList(), - ), + ), + ), + ], ); }