fix reaction bubble ui

This commit is contained in:
Salvatore Giordano
2020-05-14 11:36:05 +02:00
parent cb284f773b
commit 121f5c3d21
2 changed files with 187 additions and 139 deletions
+26 -26
View File
@@ -237,13 +237,13 @@
0BC14C4C242B5A7A0028DE94 = { 0BC14C4C242B5A7A0028DE94 = {
CreatedOnToolsVersion = 11.4; CreatedOnToolsVersion = 11.4;
DevelopmentTeam = EHV7XZLAHA; DevelopmentTeam = EHV7XZLAHA;
ProvisioningStyle = Manual; ProvisioningStyle = Automatic;
}; };
97C146ED1CF9000F007C117D = { 97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1; CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = EHV7XZLAHA; DevelopmentTeam = EHV7XZLAHA;
LastSwiftMigration = 1100; LastSwiftMigration = 1100;
ProvisioningStyle = Manual; ProvisioningStyle = Automatic;
}; };
}; };
}; };
@@ -412,9 +412,9 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = EHV7XZLAHA; DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = Notifications/Info.plist; INFOPLIST_FILE = Notifications/Info.plist;
@@ -424,7 +424,7 @@
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "flutter example notifications"; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -442,9 +442,9 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = EHV7XZLAHA; DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = Notifications/Info.plist; INFOPLIST_FILE = Notifications/Info.plist;
@@ -453,7 +453,7 @@
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "flutter example notifications"; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
@@ -469,9 +469,9 @@
CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements; CODE_SIGN_ENTITLEMENTS = Notifications/Notifications.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = EHV7XZLAHA; DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = Notifications/Info.plist; INFOPLIST_FILE = Notifications/Info.plist;
@@ -480,7 +480,7 @@
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications; PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter.Notifications;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "flutter example notifications"; PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
@@ -546,10 +546,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = EHV7XZLAHA; DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -564,7 +564,7 @@
); );
PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "flutter example"; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
@@ -687,10 +687,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = EHV7XZLAHA; DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -705,7 +705,7 @@
); );
PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "flutter example"; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -721,10 +721,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = EHV7XZLAHA; DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = ( FRAMEWORK_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -739,7 +739,7 @@
); );
PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter; PRODUCT_BUNDLE_IDENTIFIER = io.getstream.flutter;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "flutter example"; PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
+161 -113
View File
@@ -34,7 +34,7 @@ enum DisplayWidget {
/// ///
/// The widget components render the ui based on the first ancestor of type [StreamChatTheme]. /// The widget components render the ui based on the first ancestor of type [StreamChatTheme].
/// Modify it to change the widget appearance. /// Modify it to change the widget appearance.
class MessageWidget extends StatelessWidget { class MessageWidget extends StatefulWidget {
/// Function called on mention tap /// Function called on mention tap
final void Function(User) onMentionTap; final void Function(User) onMentionTap;
@@ -104,15 +104,6 @@ class MessageWidget extends StatelessWidget {
final bool showEditMessage; final bool showEditMessage;
final Map<String, AttachmentBuilder> attachmentBuilders; final Map<String, AttachmentBuilder> attachmentBuilders;
final Map<String, String> _reactionToEmoji = {
'love': '❤️',
'haha': '😂',
'like': '👍',
'sad': '😕',
'angry': '😡',
'wow': '😲',
};
MessageWidget({ MessageWidget({
Key key, Key key,
@required this.message, @required this.message,
@@ -186,20 +177,37 @@ class MessageWidget extends StatelessWidget {
}..addAll(customAttachmentBuilders ?? {}), }..addAll(customAttachmentBuilders ?? {}),
super(key: key); super(key: key);
@override
_MessageWidgetState createState() => _MessageWidgetState();
}
class _MessageWidgetState extends State<MessageWidget> {
final Map<String, String> _reactionToEmoji = {
'love': '❤️',
'haha': '😂',
'like': '👍',
'sad': '😕',
'angry': '😡',
'wow': '😲',
};
final GlobalKey _reactionPickerKey = GlobalKey();
double _reactionPadding = 0;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var leftPadding = showUserAvatar != DisplayWidget.gone var leftPadding = widget.showUserAvatar != DisplayWidget.gone
? messageTheme.avatarTheme.constraints.maxWidth + 23.0 ? widget.messageTheme.avatarTheme.constraints.maxWidth + 23.0
: 12.0; : 12.0;
if (showSendingIndicator == DisplayWidget.gone) { if (widget.showSendingIndicator == DisplayWidget.gone) {
leftPadding -= 7; leftPadding -= 7;
} }
return Portal( return Portal(
child: Padding( child: Padding(
padding: padding ?? EdgeInsets.all(8), padding: widget.padding ?? EdgeInsets.all(8),
child: Transform( child: Transform(
alignment: Alignment.center, alignment: Alignment.center,
transform: Matrix4.rotationY(reverse ? pi : 0), transform: Matrix4.rotationY(widget.reverse ? pi : 0),
child: Container( child: Container(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Container( child: Container(
@@ -220,31 +228,31 @@ class MessageWidget extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
if (showSendingIndicator == DisplayWidget.show) if (widget.showSendingIndicator ==
DisplayWidget.show)
_buildSendingIndicator(), _buildSendingIndicator(),
SizedBox( SizedBox(
width: 2, width: 2,
), ),
if (showSendingIndicator == DisplayWidget.hide) if (widget.showSendingIndicator ==
DisplayWidget.hide)
SizedBox( SizedBox(
width: 6, width: 6,
), ),
if (showUserAvatar == DisplayWidget.show) if (widget.showUserAvatar == DisplayWidget.show)
_buildUserAvatar(), _buildUserAvatar(),
SizedBox( SizedBox(
width: 6, width: 6,
), ),
if (showUserAvatar == DisplayWidget.hide) if (widget.showUserAvatar == DisplayWidget.hide)
SizedBox( SizedBox(
width: messageTheme width: widget.messageTheme.avatarTheme
.avatarTheme.constraints.maxWidth + .constraints.maxWidth +
8, 8,
), ),
Flexible( Flexible(
child: Padding( child: Padding(
padding: (message.reactionCounts?.isNotEmpty == padding: widget.showReactions
true &&
showReactions)
? EdgeInsets.only( ? EdgeInsets.only(
top: _getReactionsTopPadding(), top: _getReactionsTopPadding(),
) )
@@ -253,16 +261,16 @@ class MessageWidget extends StatelessWidget {
portalAnchor: Alignment(0, 1), portalAnchor: Alignment(0, 1),
childAnchor: Alignment.topRight, childAnchor: Alignment.topRight,
portal: _buildReactionIndicator(context), portal: _buildReactionIndicator(context),
child: (message.isDeleted && child: (widget.message.isDeleted &&
message.status != widget.message.status !=
MessageSendingStatus MessageSendingStatus
.FAILED_DELETE) .FAILED_DELETE)
? Transform( ? Transform(
alignment: Alignment.center, alignment: Alignment.center,
transform: Matrix4.rotationY( transform: Matrix4.rotationY(
reverse ? pi : 0), widget.reverse ? pi : 0),
child: DeletedMessage( child: DeletedMessage(
messageTheme: messageTheme, messageTheme: widget.messageTheme,
), ),
) )
: Column( : Column(
@@ -270,7 +278,9 @@ class MessageWidget extends StatelessWidget {
CrossAxisAlignment.start, CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
..._parseAttachments(context), ..._parseAttachments(context),
if (message.text.trim().isNotEmpty) if (widget.message.text
.trim()
.isNotEmpty)
_buildTextBubble(context), _buildTextBubble(context),
], ],
), ),
@@ -279,13 +289,15 @@ class MessageWidget extends StatelessWidget {
), ),
], ],
), ),
if (showReplyIndicator && message.replyCount > 0) if (widget.showReplyIndicator &&
widget.message.replyCount > 0)
_buildReplyIndicator(leftPadding), _buildReplyIndicator(leftPadding),
], ],
), ),
), ),
if ((message.createdAt != null && showTimestamp) || if ((widget.message.createdAt != null &&
showUsername) widget.showTimestamp) ||
widget.showUsername)
_buildUsernameAndTimestamp(leftPadding), _buildUsernameAndTimestamp(leftPadding),
], ],
), ),
@@ -297,18 +309,49 @@ class MessageWidget extends StatelessWidget {
} }
double _getReactionsTopPadding() { double _getReactionsTopPadding() {
return _reactionPadding;
return 36.0 * return 36.0 *
((message.reactionCounts.values ((widget.message.reactionCounts.values
.where((element) => element > 0) .where((element) => element > 0)
.length ~/ .length ~/
5) + 5) +
1); 1);
} }
@override
void didUpdateWidget(MessageWidget oldWidget) {
super.didUpdateWidget(oldWidget);
_updateReactionPadding();
}
@override
void initState() {
super.initState();
_updateReactionPadding();
}
void _updateReactionPadding() {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (_reactionPickerKey.currentContext != null &&
widget.message.reactionCounts.values
.where((element) => element > 0)
.length >
0) {
setState(() {
_reactionPadding = _reactionPickerKey.currentContext.size.height;
});
} else {
setState(() {
_reactionPadding = 0;
});
}
});
}
Widget _buildReactionsTail(BuildContext context) { Widget _buildReactionsTail(BuildContext context) {
return AnimatedSwitcher( return AnimatedSwitcher(
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
child: message.reactionCounts?.isNotEmpty == true child: widget.message.reactionCounts?.isNotEmpty == true
? Transform.translate( ? Transform.translate(
offset: Offset(4, 0), offset: Offset(4, 0),
child: CustomPaint( child: CustomPaint(
@@ -331,19 +374,20 @@ class MessageWidget extends StatelessWidget {
), ),
child: Transform( child: Transform(
alignment: Alignment.center, alignment: Alignment.center,
transform: Matrix4.rotationY(reverse ? pi : 0), transform: Matrix4.rotationY(widget.reverse ? pi : 0),
child: RichText( child: RichText(
text: TextSpan( text: TextSpan(
style: messageTheme.createdAt, style: widget.messageTheme.createdAt,
children: <TextSpan>[ children: <TextSpan>[
if (showUsername) if (widget.showUsername)
TextSpan( TextSpan(
text: message.user.name, text: widget.message.user.name,
style: TextStyle(fontWeight: FontWeight.bold), style: TextStyle(fontWeight: FontWeight.bold),
), ),
if (message.createdAt != null && showTimestamp) if (widget.message.createdAt != null && widget.showTimestamp)
TextSpan( TextSpan(
text: Jiffy(message.createdAt.toLocal()).format(' HH:mm'), text: Jiffy(widget.message.createdAt.toLocal())
.format(' HH:mm'),
), ),
], ],
), ),
@@ -354,10 +398,11 @@ class MessageWidget extends StatelessWidget {
Widget _buildReactionIndicator(BuildContext context) { Widget _buildReactionIndicator(BuildContext context) {
return AnimatedSwitcher( return AnimatedSwitcher(
key: _reactionPickerKey,
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
child: (showReactions && child: (widget.showReactions &&
message.reactionCounts?.isNotEmpty == true && widget.message.reactionCounts?.isNotEmpty == true &&
!message.isDeleted) !widget.message.isDeleted)
? Container( ? Container(
child: GestureDetector( child: GestureDetector(
onTap: () => onLongPress(context), onTap: () => onLongPress(context),
@@ -371,7 +416,7 @@ class MessageWidget extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
Transform( Transform(
transform: Matrix4.rotationY(reverse ? pi : 0), transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center, alignment: Alignment.center,
child: Container( child: Container(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
@@ -397,10 +442,10 @@ class MessageWidget extends StatelessWidget {
Text _buildReactionsText(BuildContext context) { Text _buildReactionsText(BuildContext context) {
return Text( return Text(
message.reactionCounts.keys.map((reactionType) { widget.message.reactionCounts.keys.map((reactionType) {
return _reactionToEmoji[reactionType] ?? '?'; return _reactionToEmoji[reactionType] ?? '?';
}).join(' ') + }).join(' ') +
' ${message.reactionCounts.values.fold(0, (t, v) => v + t).toString()}', ' ${widget.message.reactionCounts.values.fold(0, (t, v) => v + t).toString()}',
style: TextStyle( style: TextStyle(
color: Theme.of(context).brightness == Brightness.dark color: Theme.of(context).brightness == Brightness.dark
? Colors.black ? Colors.black
@@ -425,21 +470,22 @@ class MessageWidget extends StatelessWidget {
return StreamChannel( return StreamChannel(
channel: channel, channel: channel,
child: MessageActionsBottomSheet( child: MessageActionsBottomSheet(
showDeleteMessage: showDeleteMessage, showDeleteMessage: widget.showDeleteMessage,
message: message, message: widget.message,
editMessageInputBuilder: editMessageInputBuilder, editMessageInputBuilder: widget.editMessageInputBuilder,
onThreadTap: onThreadTap, onThreadTap: widget.onThreadTap,
showEditMessage: showEditMessage, showEditMessage: widget.showEditMessage,
showReactions: showReactions, showReactions: widget.showReactions,
showReply: showReplyIndicator && onThreadTap != null, showReply:
widget.showReplyIndicator && widget.onThreadTap != null,
), ),
); );
}); });
} }
List<Widget> _parseAttachments(BuildContext context) { List<Widget> _parseAttachments(BuildContext context) {
return message.attachments?.map((attachment) { return widget.message.attachments?.map((attachment) {
final attachmentBuilder = attachmentBuilders[attachment.type]; final attachmentBuilder = widget.attachmentBuilders[attachment.type];
if (attachmentBuilder == null) { if (attachmentBuilder == null) {
return SizedBox(); return SizedBox();
@@ -455,27 +501,28 @@ class MessageWidget extends StatelessWidget {
child: Material( child: Material(
color: _getBackgroundColor(), color: _getBackgroundColor(),
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
shape: attachmentShape ?? shape: widget.attachmentShape ??
shape ?? widget.shape ??
ContinuousRectangleBorder( ContinuousRectangleBorder(
side: attachmentBorderSide ?? side: widget.attachmentBorderSide ??
borderSide ?? widget.borderSide ??
BorderSide( BorderSide(
color: color:
Theme.of(context).brightness == Brightness.dark Theme.of(context).brightness == Brightness.dark
? Colors.white.withAlpha(24) ? Colors.white.withAlpha(24)
: Colors.black.withAlpha(24), : Colors.black.withAlpha(24),
), ),
borderRadius: attachmentBorderRadiusGeometry ?? borderRadius: widget.attachmentBorderRadiusGeometry ??
borderRadiusGeometry ?? widget.borderRadiusGeometry ??
BorderRadius.zero, BorderRadius.zero,
), ),
child: Padding( child: Padding(
padding: attachmentPadding, padding: widget.attachmentPadding,
child: Transform( child: Transform(
transform: Matrix4.rotationY(reverse ? pi : 0), transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center, alignment: Alignment.center,
child: Column( child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[ children: <Widget>[
getFailedMessageWidget( getFailedMessageWidget(
@@ -484,7 +531,7 @@ class MessageWidget extends StatelessWidget {
), ),
attachmentBuilder( attachmentBuilder(
context, context,
message, widget.message,
attachment, attachment,
), ),
], ],
@@ -499,12 +546,13 @@ class MessageWidget extends StatelessWidget {
} }
void onLongPress(BuildContext context) { void onLongPress(BuildContext context) {
if (message.isEphemeral || message.status == MessageSendingStatus.SENDING) { if (widget.message.isEphemeral ||
widget.message.status == MessageSendingStatus.SENDING) {
return; return;
} }
if (onMessageActions != null) { if (widget.onMessageActions != null) {
onMessageActions(context, message); widget.onMessageActions(context, widget.message);
} else { } else {
_showMessageBottomSheet(context); _showMessageBottomSheet(context);
} }
@@ -517,15 +565,15 @@ class MessageWidget extends StatelessWidget {
left: leftPadding, left: leftPadding,
), ),
child: Transform( child: Transform(
transform: Matrix4.rotationY(reverse ? pi : 0), transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center, alignment: Alignment.center,
child: ReplyIndicator( child: ReplyIndicator(
message: message, message: widget.message,
reversed: reverse, reversed: widget.reverse,
messageTheme: messageTheme, messageTheme: widget.messageTheme,
onTap: onThreadTap != null onTap: widget.onThreadTap != null
? () { ? () {
onThreadTap(message); widget.onThreadTap(widget.message);
} }
: null, : null,
), ),
@@ -540,27 +588,27 @@ class MessageWidget extends StatelessWidget {
4, 4,
), ),
child: Transform( child: Transform(
transform: Matrix4.rotationY(reverse ? pi : 0), transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center, alignment: Alignment.center,
child: SendingIndicator( child: SendingIndicator(
message: message, message: widget.message,
), ),
), ),
); );
} }
Widget _buildUserAvatar() => Transform( Widget _buildUserAvatar() => Transform(
transform: Matrix4.rotationY(reverse ? pi : 0), transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center, alignment: Alignment.center,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0), padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: Transform.translate( child: Transform.translate(
offset: offset: Offset(
Offset(0, messageTheme.avatarTheme.constraints.maxHeight / 2), 0, widget.messageTheme.avatarTheme.constraints.maxHeight / 2),
child: UserAvatar( child: UserAvatar(
user: message.user, user: widget.message.user,
onTap: onUserAvatarTap, onTap: widget.onUserAvatarTap,
constraints: messageTheme.avatarTheme.constraints, constraints: widget.messageTheme.avatarTheme.constraints,
), ),
), ),
), ),
@@ -570,31 +618,31 @@ class MessageWidget extends StatelessWidget {
BuildContext context, { BuildContext context, {
EdgeInsetsGeometry padding, EdgeInsetsGeometry padding,
}) { }) {
Widget widget; Widget failedWidget;
if (message.status == MessageSendingStatus.FAILED) if (widget.message.status == MessageSendingStatus.FAILED)
widget = Text( failedWidget = Text(
'MESSAGE FAILED · CLICK TO TRY AGAIN', 'MESSAGE FAILED · CLICK TO TRY AGAIN',
style: messageTheme.messageText.copyWith( style: widget.messageTheme.messageText.copyWith(
color: Theme.of(context).brightness == Brightness.dark color: Theme.of(context).brightness == Brightness.dark
? Colors.white.withOpacity(.5) ? Colors.white.withOpacity(.5)
: Colors.black.withOpacity(.5), : Colors.black.withOpacity(.5),
fontSize: 11, fontSize: 11,
), ),
); );
if (message.status == MessageSendingStatus.FAILED_UPDATE) if (widget.message.status == MessageSendingStatus.FAILED_UPDATE)
widget = Text( failedWidget = Text(
'MESSAGE UPDATE FAILED · CLICK TO TRY AGAIN', 'MESSAGE UPDATE FAILED · CLICK TO TRY AGAIN',
style: messageTheme.messageText.copyWith( style: widget.messageTheme.messageText.copyWith(
color: Theme.of(context).brightness == Brightness.dark color: Theme.of(context).brightness == Brightness.dark
? Colors.white.withOpacity(.5) ? Colors.white.withOpacity(.5)
: Colors.black.withOpacity(.5), : Colors.black.withOpacity(.5),
fontSize: 11, fontSize: 11,
), ),
); );
if (message.status == MessageSendingStatus.FAILED_DELETE) if (widget.message.status == MessageSendingStatus.FAILED_DELETE)
widget = Text( failedWidget = Text(
'MESSAGE DELETE FAILED · CLICK TO TRY AGAIN', 'MESSAGE DELETE FAILED · CLICK TO TRY AGAIN',
style: messageTheme.messageText.copyWith( style: widget.messageTheme.messageText.copyWith(
color: Theme.of(context).brightness == Brightness.dark color: Theme.of(context).brightness == Brightness.dark
? Colors.white.withOpacity(.5) ? Colors.white.withOpacity(.5)
: Colors.black.withOpacity(.5), : Colors.black.withOpacity(.5),
@@ -602,10 +650,10 @@ class MessageWidget extends StatelessWidget {
), ),
); );
if (widget != null) { if (failedWidget != null) {
return Padding( return Padding(
padding: padding ?? EdgeInsets.zero, padding: padding ?? EdgeInsets.zero,
child: widget, child: failedWidget,
); );
} }
@@ -617,22 +665,22 @@ class MessageWidget extends StatelessWidget {
onTap: () => retryMessage(context), onTap: () => retryMessage(context),
onLongPress: () => onLongPress(context), onLongPress: () => onLongPress(context),
child: Material( child: Material(
shape: shape ?? shape: widget.shape ??
ContinuousRectangleBorder( ContinuousRectangleBorder(
side: borderSide ?? side: widget.borderSide ??
BorderSide( BorderSide(
color: Theme.of(context).brightness == Brightness.dark color: Theme.of(context).brightness == Brightness.dark
? Colors.white.withAlpha(24) ? Colors.white.withAlpha(24)
: Colors.black.withAlpha(24), : Colors.black.withAlpha(24),
), ),
borderRadius: borderRadiusGeometry ?? BorderRadius.zero, borderRadius: widget.borderRadiusGeometry ?? BorderRadius.zero,
), ),
color: _getBackgroundColor(), color: _getBackgroundColor(),
child: Transform( child: Transform(
transform: Matrix4.rotationY(reverse ? pi : 0), transform: Matrix4.rotationY(widget.reverse ? pi : 0),
alignment: Alignment.center, alignment: Alignment.center,
child: Padding( child: Padding(
padding: textPadding, padding: widget.textPadding,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
@@ -647,30 +695,30 @@ class MessageWidget extends StatelessWidget {
} }
Color _getBackgroundColor() { Color _getBackgroundColor() {
return (message.status == MessageSendingStatus.FAILED || return (widget.message.status == MessageSendingStatus.FAILED ||
message.status == MessageSendingStatus.FAILED_UPDATE || widget.message.status == MessageSendingStatus.FAILED_UPDATE ||
message.status == MessageSendingStatus.FAILED_DELETE) widget.message.status == MessageSendingStatus.FAILED_DELETE)
? Color(0xffd0021B).withOpacity(.1) ? Color(0xffd0021B).withOpacity(.1)
: messageTheme.messageBackgroundColor; : widget.messageTheme.messageBackgroundColor;
} }
void retryMessage(BuildContext context) { void retryMessage(BuildContext context) {
final channel = StreamChannel.of(context).channel; final channel = StreamChannel.of(context).channel;
if (message.status == MessageSendingStatus.FAILED) { if (widget.message.status == MessageSendingStatus.FAILED) {
channel.sendMessage(message); channel.sendMessage(widget.message);
return; return;
} }
if (message.status == MessageSendingStatus.FAILED_UPDATE) { if (widget.message.status == MessageSendingStatus.FAILED_UPDATE) {
StreamChat.of(context).client.updateMessage( StreamChat.of(context).client.updateMessage(
message, widget.message,
channel.cid, channel.cid,
); );
return; return;
} }
if (message.status == MessageSendingStatus.FAILED_DELETE) { if (widget.message.status == MessageSendingStatus.FAILED_DELETE) {
StreamChat.of(context).client.deleteMessage( StreamChat.of(context).client.deleteMessage(
message, widget.message,
channel.cid, channel.cid,
); );
return; return;
@@ -678,12 +726,12 @@ class MessageWidget extends StatelessWidget {
} }
Widget _buildText(BuildContext context) { Widget _buildText(BuildContext context) {
return textBuilder != null return widget.textBuilder != null
? textBuilder(context, message) ? widget.textBuilder(context, widget.message)
: MessageText( : MessageText(
message: message, message: widget.message,
onMentionTap: onMentionTap, onMentionTap: widget.onMentionTap,
messageTheme: messageTheme, messageTheme: widget.messageTheme,
); );
} }
} }