From 28e01a89d440c1b1f8749b0d5ef06f288b78ad7d Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Tue, 5 Jan 2021 18:10:16 +0530 Subject: [PATCH] [MessageWidget] Show thread participants in case of thread. Signed-off-by: Sahil Kumar --- lib/src/extension.dart | 2 +- lib/src/message_widget.dart | 128 +++++++++++++++++---------------- lib/src/stream_chat_theme.dart | 20 +++--- pubspec.yaml | 3 +- 4 files changed, 78 insertions(+), 75 deletions(-) diff --git a/lib/src/extension.dart b/lib/src/extension.dart index f49c574f..71edefe6 100644 --- a/lib/src/extension.dart +++ b/lib/src/extension.dart @@ -5,7 +5,7 @@ extension StringExtension on String { } /// List extension -extension ListX on List { +extension IterableX on Iterable { /// Insert any item inBetween the list items List insertBetween(T item) => expand((e) sync* { yield item; diff --git a/lib/src/message_widget.dart b/lib/src/message_widget.dart index bc6646c5..8ce09579 100644 --- a/lib/src/message_widget.dart +++ b/lib/src/message_widget.dart @@ -252,7 +252,7 @@ class _MessageWidgetState extends State { bool get showInChannel => widget.showInChannelIndicator && widget.message?.showInChannel == true; - bool get _hasQuotedMessage => widget.message?.quotedMessage != null; + bool get hasQuotedMessage => widget.message?.quotedMessage != null; bool get isSendFailed => widget.message.status == MessageSendingStatus.FAILED; @@ -264,6 +264,10 @@ class _MessageWidgetState extends State { bool get isFailedState => isSendFailed || isUpdateFailed || isDeleteFailed; + bool get isGiphy => + widget.message.attachments?.any((element) => element.type == 'giphy') == + true; + bool get showBottomRow => showThreadReplyIndicator || showUsername || @@ -272,13 +276,9 @@ class _MessageWidgetState extends State { @override Widget build(BuildContext context) { - var leftPadding = widget.showUserAvatar != DisplayWidget.gone - ? widget.messageTheme.avatarTheme.constraints.maxWidth + 14.5 - : 6.0; - - final isGiphy = - widget.message.attachments?.any((element) => element.type == 'giphy') == - true; + final avatarWidth = widget.messageTheme.avatarTheme.constraints.maxWidth; + var leftPadding = + widget.showUserAvatar != DisplayWidget.gone ? avatarWidth + 8.5 : 4.5; final isOnlyEmoji = widget.message.text.characters.every((c) => Emoji.byChar(c) != null); @@ -319,15 +319,13 @@ class _MessageWidgetState extends State { crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ - if (widget.showUserAvatar == DisplayWidget.show) + if (widget.showUserAvatar == + DisplayWidget.show) ...[ _buildUserAvatar(), - SizedBox(width: 6), + SizedBox(width: 4), + ], if (widget.showUserAvatar == DisplayWidget.hide) - SizedBox( - width: widget.messageTheme.avatarTheme - .constraints.maxWidth + - 8, - ), + SizedBox(width: avatarWidth + 4), Flexible( child: PortalEntry( portal: Container( @@ -380,22 +378,9 @@ class _MessageWidgetState extends State { ? BorderSide.none : widget.borderSide ?? BorderSide( - color: Theme.of(context) - .brightness == - Brightness - .dark - ? StreamChatTheme.of( - context) - .colorTheme - .white - .withAlpha( - 24) - : StreamChatTheme.of( - context) - .colorTheme - .black - .withAlpha( - 24), + color: widget + .messageTheme + .messageBorderColor, ), borderRadius: widget .borderRadiusGeometry ?? @@ -412,7 +397,7 @@ class _MessageWidgetState extends State { mainAxisSize: MainAxisSize.min, children: [ - if (_hasQuotedMessage) + if (hasQuotedMessage) _buildQuotedMessage(), ..._parseAttachments( context), @@ -542,6 +527,8 @@ class _MessageWidgetState extends State { } else { final showSendingIndicator = widget.showSendingIndicator == DisplayWidget.show; + final threadParticipants = widget.message.threadParticipants; + final showThreadParticipants = threadParticipants?.isNotEmpty == true; final replyCount = widget.message.replyCount; final msg = replyCount != 0 ? '$replyCount ${replyCount > 1 ? 'Thread Replies' : 'Thread Reply'}' @@ -554,19 +541,17 @@ class _MessageWidgetState extends State { children.addAll([ if (showSendingIndicator) _buildSendingIndicator(), - // if (showReadList) - // SizedBox.fromSize( - // size: Size((widget.readList.length * 10.0) + 10, 17), - // child: Padding( - // padding: const EdgeInsets.only(left: 4.0), - // child: _buildReadIndicator(), - // ), - // ), - if (showThreadReplyIndicator) + if (showThreadReplyIndicator) ...[ + if (showThreadParticipants) + SizedBox.fromSize( + size: Size((threadParticipants.length * 8.0) + 10, 16), + child: _buildThreadParticipantsIndicator(), + ), InkWell( onTap: widget.onThreadTap != null ? onThreadTap : null, child: Text(msg, style: widget.messageTheme?.replies), ), + ], if (showUsername) Text( widget.message.user.name, @@ -596,7 +581,7 @@ class _MessageWidgetState extends State { size: const Size(16, 32), painter: _ThreadReplyPainter( context: context, - color: widget.messageTheme.replyThreadColor, + color: widget.messageTheme.messageBorderColor, ), ), ), @@ -604,7 +589,7 @@ class _MessageWidgetState extends State { (child) => Transform( transform: Matrix4.rotationY(widget.reverse ? pi : 0), alignment: Alignment.center, - child: child, + child: Container(height: 16, child: Center(child: child)), ), ), ].insertBetween(const SizedBox(width: 8.0)), @@ -630,9 +615,29 @@ class _MessageWidgetState extends State { ); } - bool get isGiphy => - widget.message.attachments?.any((element) => element.type == 'giphy') == - true; + Widget _buildThreadParticipantsIndicator() { + var padding = 0.0; + return Stack( + children: widget.message.threadParticipants.map((user) { + padding += 10.0; + return Positioned( + left: padding - 10, + bottom: 0, + top: 0, + child: Material( + color: Colors.white, + clipBehavior: Clip.antiAlias, + shape: CircleBorder(), + child: UserAvatar( + user: user, + constraints: BoxConstraints.loose(Size.fromRadius(8)), + showOnlineStatus: false, + ), + ), + ); + }).toList(), + ); + } Widget _buildReactionIndicator( BuildContext context, @@ -866,21 +871,18 @@ class _MessageWidgetState extends State { Widget _buildUserAvatar() => Transform( transform: Matrix4.rotationY(widget.reverse ? pi : 0), alignment: Alignment.center, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4.0), - child: Transform.translate( - offset: Offset( - 0, - widget.translateUserAvatar - ? widget.messageTheme.avatarTheme.constraints.maxHeight / 2 - : 0, - ), - child: UserAvatar( - user: widget.message.user, - onTap: widget.onUserAvatarTap, - constraints: widget.messageTheme.avatarTheme.constraints, - showOnlineStatus: false, - ), + child: Transform.translate( + offset: Offset( + 0, + widget.translateUserAvatar + ? widget.messageTheme.avatarTheme.constraints.maxHeight / 2 + : 0, + ), + child: UserAvatar( + user: widget.message.user, + onTap: widget.onUserAvatarTap, + constraints: widget.messageTheme.avatarTheme.constraints, + showOnlineStatus: false, ), ), ); @@ -912,7 +914,7 @@ class _MessageWidgetState extends State { if (widget.message.attachments ?.any((element) => element.ogScrapeUrl != null) == true && - !_hasQuotedMessage) + !hasQuotedMessage) _buildUrlAttachment(), ], ), @@ -924,7 +926,7 @@ class _MessageWidgetState extends State { widget.message.text.characters.every((c) => Emoji.byChar(c) != null); Color _getBackgroundColor() { - if (_hasQuotedMessage) { + if (hasQuotedMessage) { return widget.messageTheme.messageBackgroundColor; } diff --git a/lib/src/stream_chat_theme.dart b/lib/src/stream_chat_theme.dart index 02abd25c..246459c6 100644 --- a/lib/src/stream_chat_theme.dart +++ b/lib/src/stream_chat_theme.dart @@ -181,8 +181,8 @@ class StreamChatThemeData { this.ownMessageTheme.messageBackgroundColor, avatarTheme: ownMessageTheme?.avatarTheme ?? this.ownMessageTheme.avatarTheme, - replyThreadColor: ownMessageTheme?.replyThreadColor ?? - this.ownMessageTheme.replyThreadColor, + messageBorderColor: ownMessageTheme?.messageBorderColor ?? + this.ownMessageTheme.messageBorderColor, ) ?? this.ownMessageTheme, otherMessageTheme: otherMessageTheme?.copyWith( @@ -199,10 +199,10 @@ class StreamChatThemeData { messageBackgroundColor: otherMessageTheme?.messageBackgroundColor ?? this.otherMessageTheme.messageBackgroundColor, + messageBorderColor: otherMessageTheme?.messageBorderColor ?? + this.otherMessageTheme.messageBorderColor, avatarTheme: otherMessageTheme?.avatarTheme ?? this.otherMessageTheme.avatarTheme, - replyThreadColor: ownMessageTheme?.replyThreadColor ?? - this.ownMessageTheme.replyThreadColor, ) ?? this.otherMessageTheme, reactionIcons: reactionIcons ?? this.reactionIcons, @@ -284,7 +284,7 @@ class StreamChatThemeData { messageBackgroundColor: colorTheme.greyGainsboro, reactionsBackgroundColor: colorTheme.white, reactionsBorderColor: colorTheme.greyWhisper, - replyThreadColor: colorTheme.greyWhisper, + messageBorderColor: colorTheme.greyGainsboro, avatarTheme: AvatarTheme( borderRadius: BorderRadius.circular(20), constraints: BoxConstraints.tightFor( @@ -316,7 +316,7 @@ class StreamChatThemeData { color: accentColor, ), messageBackgroundColor: colorTheme.white, - replyThreadColor: colorTheme.black.withAlpha(24), + messageBorderColor: colorTheme.greyWhisper, avatarTheme: AvatarTheme( borderRadius: BorderRadius.circular(20), constraints: BoxConstraints.tightFor( @@ -646,9 +646,9 @@ class MessageTheme { final TextStyle createdAt; final TextStyle replies; final Color messageBackgroundColor; + final Color messageBorderColor; final Color reactionsBackgroundColor; final Color reactionsBorderColor; - final Color replyThreadColor; final AvatarTheme avatarTheme; const MessageTheme({ @@ -657,9 +657,9 @@ class MessageTheme { this.messageAuthor, this.messageLinks, this.messageBackgroundColor, + this.messageBorderColor, this.reactionsBackgroundColor, this.reactionsBorderColor, - this.replyThreadColor, this.avatarTheme, this.createdAt, }); @@ -671,10 +671,10 @@ class MessageTheme { TextStyle createdAt, TextStyle replies, Color messageBackgroundColor, + Color messageBorderColor, AvatarTheme avatarTheme, Color reactionsBackgroundColor, Color reactionsBorderColor, - Color replyThreadColor, }) => MessageTheme( messageText: messageText ?? this.messageText, @@ -683,12 +683,12 @@ class MessageTheme { createdAt: createdAt ?? this.createdAt, messageBackgroundColor: messageBackgroundColor ?? this.messageBackgroundColor, + messageBorderColor: messageBorderColor ?? this.messageBorderColor, avatarTheme: avatarTheme ?? this.avatarTheme, replies: replies ?? this.replies, reactionsBackgroundColor: reactionsBackgroundColor ?? this.reactionsBackgroundColor, reactionsBorderColor: reactionsBorderColor ?? this.reactionsBorderColor, - replyThreadColor: replyThreadColor ?? this.replyThreadColor, ); } diff --git a/pubspec.yaml b/pubspec.yaml index 9fa13141..1c99b03b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,7 +28,8 @@ dependencies: file_picker: ^2.0.12 image_picker: ^0.6.7+2 flutter_keyboard_visibility: ^3.3.0 - stream_chat: ^0.2.22 + stream_chat: + path: ../stream-chat-dart mime: ^0.9.6+3 video_compress: ^2.1.1 visibility_detector: ^0.1.5