From 4044e1bcdc9ce94283054eb1a952dca994d3f379 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 18 Jan 2021 12:26:48 +0100 Subject: [PATCH 1/7] hide overlay on delete message --- .../lib/src/message_actions_modal.dart | 296 +++++++++--------- 1 file changed, 154 insertions(+), 142 deletions(-) diff --git a/packages/flutter_widgets/lib/src/message_actions_modal.dart b/packages/flutter_widgets/lib/src/message_actions_modal.dart index c45c351d..923378de 100644 --- a/packages/flutter_widgets/lib/src/message_actions_modal.dart +++ b/packages/flutter_widgets/lib/src/message_actions_modal.dart @@ -61,6 +61,8 @@ class MessageActionsModal extends StatefulWidget { } class _MessageActionsModalState extends State { + bool _showActions = true; + @override Widget build(BuildContext context) { return _showMessageOptionsModal(); @@ -87,160 +89,163 @@ class _MessageActionsModalState extends State { ? 1 : (roughSentenceSize == 0 ? 1 : (roughSentenceSize / roughMaxSize)); - return TweenAnimationBuilder( - tween: Tween(begin: 0.0, end: 1.0), - duration: Duration(milliseconds: 300), - curve: Curves.easeInOutBack, - builder: (context, val, snapshot) { - final hasFileAttachment = - widget.message.attachments?.any((it) => it.type == 'file') == true; - return GestureDetector( - behavior: HitTestBehavior.translucent, - onTap: () => Navigator.maybePop(context), - child: Stack( - children: [ - Positioned.fill( - child: BackdropFilter( - filter: ImageFilter.blur( - sigmaX: 10, - sigmaY: 10, - ), - child: Container( - color: StreamChatTheme.of(context).colorTheme.overlay, - ), - ), + final hasFileAttachment = + widget.message.attachments?.any((it) => it.type == 'file') == true; + + return GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () => Navigator.maybePop(context), + child: Stack( + children: [ + Positioned.fill( + child: BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 10, + sigmaY: 10, ), - Transform.scale( - scale: val, - child: Center( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: widget.reverse - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: [ - if (widget.showReactions && - (widget.message.status == - MessageSendingStatus.SENT || - widget.message.status == null)) - Align( - alignment: Alignment( - user.id == widget.message.user.id - ? (divFactor > 1.0 - ? 0.0 - : (1.0 - divFactor)) - : (divFactor > 1.0 - ? 0.0 - : -(1.0 - divFactor)), - 0.0), - child: ReactionPicker( - message: widget.message, - messageTheme: widget.messageTheme, - ), - ), - SizedBox(height: 8), - IgnorePointer( - child: MessageWidget( - key: Key('MessageWidget'), - reverse: widget.reverse, - message: widget.message.copyWith( - text: widget.message.text.length > 200 - ? '${widget.message.text.substring(0, 200)}...' - : widget.message.text, - ), - messageTheme: widget.messageTheme, - showReactions: false, - showUsername: false, - showThreadReplyIndicator: false, - showReplyMessage: false, - showUserAvatar: widget.showUserAvatar, - attachmentPadding: EdgeInsets.all( - hasFileAttachment ? 4 : 2, - ), - showTimestamp: false, - translateUserAvatar: false, - padding: const EdgeInsets.all(0), - textPadding: EdgeInsets.symmetric( - vertical: 8.0, - horizontal: - widget.message.text.isOnlyEmoji ? 0 : 16.0, - ), - showReactionPickerIndicator: - widget.showReactions && - (widget.message.status == - MessageSendingStatus.SENT || - widget.message.status == null), - showInChannelIndicator: false, - showSendingIndicator: false, - shape: widget.messageShape, - attachmentShape: widget.attachmentShape, - ), - ), - SizedBox(height: 8), - Padding( - padding: EdgeInsets.only( - left: widget.reverse ? 0 : 40, - ), - child: SizedBox( - width: MediaQuery.of(context).size.width * 0.75, - child: Material( - color: StreamChatTheme.of(context) - .colorTheme - .whiteSnow, - clipBehavior: Clip.hardEdge, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), + child: Container( + color: StreamChatTheme.of(context).colorTheme.overlay, + ), + ), + ), + if (_showActions) + TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: 1.0), + duration: Duration(milliseconds: 300), + curve: Curves.easeInOutBack, + builder: (context, val, snapshot) { + return Transform.scale( + scale: val, + child: Center( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: widget.reverse + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: [ + if (widget.showReactions && + (widget.message.status == + MessageSendingStatus.SENT || + widget.message.status == null)) + Align( + alignment: Alignment( + user.id == widget.message.user.id + ? (divFactor > 1.0 + ? 0.0 + : (1.0 - divFactor)) + : (divFactor > 1.0 + ? 0.0 + : -(1.0 - divFactor)), + 0.0), + child: ReactionPicker( + message: widget.message, + messageTheme: widget.messageTheme, ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - if (widget.showReplyMessage && + ), + SizedBox(height: 8), + IgnorePointer( + child: MessageWidget( + key: Key('MessageWidget'), + reverse: widget.reverse, + message: widget.message.copyWith( + text: widget.message.text.length > 200 + ? '${widget.message.text.substring(0, 200)}...' + : widget.message.text, + ), + messageTheme: widget.messageTheme, + showReactions: false, + showUsername: false, + showThreadReplyIndicator: false, + showReplyMessage: false, + showUserAvatar: widget.showUserAvatar, + attachmentPadding: EdgeInsets.all( + hasFileAttachment ? 4 : 2, + ), + showTimestamp: false, + translateUserAvatar: false, + padding: const EdgeInsets.all(0), + textPadding: EdgeInsets.symmetric( + vertical: 8.0, + horizontal: widget.message.text.isOnlyEmoji + ? 0 + : 16.0, + ), + showReactionPickerIndicator: + widget.showReactions && (widget.message.status == MessageSendingStatus.SENT || - widget.message.status == null) && - widget.message.parentId == null) - _buildReplyButton(context), - if (widget.showThreadReplyMessage && - (widget.message.status == - MessageSendingStatus.SENT || - widget.message.status == null) && - widget.message.parentId == null) - _buildThreadReplyButton(context), - if (widget.showResendMessage) - _buildResendMessage(context), - if (widget.showEditMessage) - _buildEditMessage(context), - if (widget.showCopyMessage) - _buildCopyButton(context), - if (widget.showFlagButton) - _buildFlagButton(context), - if (widget.showDeleteMessage) - _buildDeleteButton(context), - ].insertBetween( - Container( - height: 1, - color: StreamChatTheme.of(context) - .colorTheme - .greyWhisper, + widget.message.status == null), + showInChannelIndicator: false, + showSendingIndicator: false, + shape: widget.messageShape, + attachmentShape: widget.attachmentShape, + ), + ), + SizedBox(height: 8), + Padding( + padding: EdgeInsets.only( + left: widget.reverse ? 0 : 40, + ), + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.75, + child: Material( + color: StreamChatTheme.of(context) + .colorTheme + .whiteSnow, + clipBehavior: Clip.hardEdge, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + if (widget.showReplyMessage && + (widget.message.status == + MessageSendingStatus.SENT || + widget.message.status == null) && + widget.message.parentId == null) + _buildReplyButton(context), + if (widget.showThreadReplyMessage && + (widget.message.status == + MessageSendingStatus.SENT || + widget.message.status == null) && + widget.message.parentId == null) + _buildThreadReplyButton(context), + if (widget.showResendMessage) + _buildResendMessage(context), + if (widget.showEditMessage) + _buildEditMessage(context), + if (widget.showCopyMessage) + _buildCopyButton(context), + if (widget.showFlagButton) + _buildFlagButton(context), + if (widget.showDeleteMessage) + _buildDeleteButton(context), + ].insertBetween( + Container( + height: 1, + color: StreamChatTheme.of(context) + .colorTheme + .greyWhisper, + ), ), ), ), ), ), - ), - ], + ], + ), ), ), ), - ), - ), - ], - ), - ); - }, + ); + }, + ), + ], + ), ); } @@ -273,6 +278,9 @@ class _MessageActionsModalState extends State { } void _showDeleteDialog() async { + setState(() { + _showActions = false; + }); var answer = await showConfirmationDialog(context, title: 'Delete message', icon: StreamSvgIcon.flag( @@ -293,6 +301,10 @@ class _MessageActionsModalState extends State { } catch (err) { _showErrorAlert(); } + } else { + setState(() { + _showActions = true; + }); } } From afec7122fb5930574f1896864b2d173a7e9bb745 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 18 Jan 2021 12:47:30 +0100 Subject: [PATCH 2/7] workaround for a weird error while uploading the image for the first time --- packages/flutter_widgets/lib/src/message_input.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/flutter_widgets/lib/src/message_input.dart b/packages/flutter_widgets/lib/src/message_input.dart index 6fafb5d8..80ccbf71 100644 --- a/packages/flutter_widgets/lib/src/message_input.dart +++ b/packages/flutter_widgets/lib/src/message_input.dart @@ -1029,7 +1029,11 @@ class MessageInputState extends State { setState(() { _attachments.add(attachment); }); - final mediaFile = await medium.originFile; + + final mediaFile = await medium.originFile.timeout( + Duration(seconds: 5), + onTimeout: () => medium.originFile, + ); var file = PlatformFile( path: mediaFile.path, From d3206253eab61e3ec11708814a00191dcf0d1c44 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 18 Jan 2021 12:52:03 +0100 Subject: [PATCH 3/7] fix textfield options --- packages/flutter_widgets/lib/src/stream_chat.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/flutter_widgets/lib/src/stream_chat.dart b/packages/flutter_widgets/lib/src/stream_chat.dart index 3ebdf6e9..5d1b7484 100644 --- a/packages/flutter_widgets/lib/src/stream_chat.dart +++ b/packages/flutter_widgets/lib/src/stream_chat.dart @@ -80,7 +80,6 @@ class StreamChatState extends State with WidgetsBindingObserver { primaryIconTheme: streamTheme.primaryIconTheme, accentColor: streamTheme.colorTheme.accentBlue, scaffoldBackgroundColor: streamTheme.colorTheme.white, - buttonTheme: streamTheme.buttonTheme, ), child: widget.child, ); From 024ed66154fbc5c0edc9c185a08e6d1782234555 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Mon, 18 Jan 2021 12:55:13 +0100 Subject: [PATCH 4/7] fix error status --- packages/flutter_widgets/lib/src/message_widget.dart | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/flutter_widgets/lib/src/message_widget.dart b/packages/flutter_widgets/lib/src/message_widget.dart index 65817823..070aa271 100644 --- a/packages/flutter_widgets/lib/src/message_widget.dart +++ b/packages/flutter_widgets/lib/src/message_widget.dart @@ -453,16 +453,10 @@ class _MessageWidgetState extends State { ), if (isFailedState) Positioned( - left: widget.reverse ? -3 : null, + left: widget.reverse ? -9 : null, right: widget.reverse ? null : -9, - bottom: showBottomRow ? 20 : 0, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - child: StreamSvgIcon.error(size: 20), - ), + bottom: showBottomRow ? 18 : -2, + child: StreamSvgIcon.error(size: 20), ), ], ), From feac47d4e063682dcb89e6062ac16cca11a557d8 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 19 Jan 2021 09:58:02 +0100 Subject: [PATCH 5/7] hide chat info modal on delete --- .../lib/src/channel_bottom_sheet.dart | 308 ++++++++++-------- 1 file changed, 165 insertions(+), 143 deletions(-) diff --git a/packages/flutter_widgets/lib/src/channel_bottom_sheet.dart b/packages/flutter_widgets/lib/src/channel_bottom_sheet.dart index 6b3e4658..3ae7e948 100644 --- a/packages/flutter_widgets/lib/src/channel_bottom_sheet.dart +++ b/packages/flutter_widgets/lib/src/channel_bottom_sheet.dart @@ -14,6 +14,8 @@ class ChannelBottomSheet extends StatefulWidget { } class _ChannelBottomSheetState extends State { + bool _showActions = true; + @override Widget build(BuildContext context) { var channel = StreamChannel.of(context).channel; @@ -33,157 +35,177 @@ class _ChannelBottomSheetState extends State { topRight: Radius.circular(16.0), ), ), - child: ListView( - shrinkWrap: true, - children: [ - SizedBox( - height: 24.0, - ), - Center( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: ChannelName( - textStyle: StreamChatTheme.of(context).textTheme.headlineBold, - ), - ), - ), - SizedBox( - height: 5.0, - ), - Center( - child: ChannelInfo( - showTypingIndicator: false, - channel: StreamChannel.of(context).channel, - textStyle: - StreamChatTheme.of(context).channelPreviewTheme.subtitle, - ), - ), - SizedBox( - height: 17.0, - ), - if (channel.isDistinct && channel.memberCount == 2) - Column( + child: !_showActions + ? SizedBox() + : ListView( + shrinkWrap: true, children: [ - UserAvatar( - user: members - .firstWhere((e) => e.user.id != userAsMember.user.id) - .user, - constraints: BoxConstraints( - maxHeight: 64.0, - maxWidth: 64.0, + SizedBox( + height: 24.0, + ), + Center( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: ChannelName( + textStyle: + StreamChatTheme.of(context).textTheme.headlineBold, + ), ), - borderRadius: BorderRadius.circular(32.0), - onlineIndicatorConstraints: - BoxConstraints.tight(Size(12.0, 12.0)), ), SizedBox( - height: 6.0, + height: 5.0, ), - Text( - members - .firstWhere((e) => e.user.id != userAsMember.user.id) - .user - .name, - style: StreamChatTheme.of(context).textTheme.footnoteBold, - maxLines: 1, - overflow: TextOverflow.ellipsis, + Center( + child: ChannelInfo( + showTypingIndicator: false, + channel: StreamChannel.of(context).channel, + textStyle: StreamChatTheme.of(context) + .channelPreviewTheme + .subtitle, + ), + ), + SizedBox( + height: 17.0, + ), + if (channel.isDistinct && channel.memberCount == 2) + Column( + children: [ + UserAvatar( + user: members + .firstWhere( + (e) => e.user.id != userAsMember.user.id) + .user, + constraints: BoxConstraints( + maxHeight: 64.0, + maxWidth: 64.0, + ), + borderRadius: BorderRadius.circular(32.0), + onlineIndicatorConstraints: + BoxConstraints.tight(Size(12.0, 12.0)), + ), + SizedBox( + height: 6.0, + ), + Text( + members + .firstWhere( + (e) => e.user.id != userAsMember.user.id) + .user + .name, + style: + StreamChatTheme.of(context).textTheme.footnoteBold, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + if (!(channel.isDistinct && channel.memberCount == 2)) + Container( + height: 94.0, + alignment: Alignment.center, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: members.length, + shrinkWrap: true, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: Column( + children: [ + UserAvatar( + user: members[index].user, + constraints: BoxConstraints( + maxHeight: 64.0, + maxWidth: 64.0, + ), + borderRadius: BorderRadius.circular(32.0), + onlineIndicatorConstraints: + BoxConstraints.tight(Size(12.0, 12.0)), + ), + SizedBox( + height: 6.0, + ), + Text( + members[index].user.name, + style: StreamChatTheme.of(context) + .textTheme + .footnoteBold, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ); + }, + ), + ), + SizedBox( + height: 24.0, + ), + OptionListTile( + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.user( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + ), + title: 'View Info', + onTap: widget.onViewInfoTap, + ), + if (!channel.isDistinct) + OptionListTile( + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.userRemove( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + ), + title: 'Leave Group', + onTap: () async { + setState(() { + _showActions = false; + }); + await _showLeaveDialog(); + setState(() { + _showActions = true; + }); + }, + ), + if (isOwner) + OptionListTile( + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.delete( + color: StreamChatTheme.of(context).colorTheme.accentRed, + ), + ), + title: 'Delete Conversation', + titleColor: + StreamChatTheme.of(context).colorTheme.accentRed, + onTap: () async { + setState(() { + _showActions = false; + }); + await _showDeleteDialog(); + setState(() { + _showActions = true; + }); + }, + ), + OptionListTile( + leading: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: StreamSvgIcon.close_small( + color: StreamChatTheme.of(context).colorTheme.grey, + ), + ), + title: 'Cancel', + onTap: () { + Navigator.pop(context); + }, ), ], ), - if (!(channel.isDistinct && channel.memberCount == 2)) - Container( - height: 94.0, - alignment: Alignment.center, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: members.length, - shrinkWrap: true, - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Column( - children: [ - UserAvatar( - user: members[index].user, - constraints: BoxConstraints( - maxHeight: 64.0, - maxWidth: 64.0, - ), - borderRadius: BorderRadius.circular(32.0), - onlineIndicatorConstraints: - BoxConstraints.tight(Size(12.0, 12.0)), - ), - SizedBox( - height: 6.0, - ), - Text( - members[index].user.name, - style: StreamChatTheme.of(context) - .textTheme - .footnoteBold, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ], - ), - ); - }, - ), - ), - SizedBox( - height: 24.0, - ), - OptionListTile( - leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.user( - color: StreamChatTheme.of(context).colorTheme.grey, - ), - ), - title: 'View Info', - onTap: widget.onViewInfoTap, - ), - if (!channel.isDistinct) - OptionListTile( - leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.userRemove( - color: StreamChatTheme.of(context).colorTheme.grey, - ), - ), - title: 'Leave Group', - onTap: () async { - _showLeaveDialog(); - }, - ), - if (isOwner) - OptionListTile( - leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.delete( - color: StreamChatTheme.of(context).colorTheme.accentRed, - ), - ), - title: 'Delete Conversation', - titleColor: StreamChatTheme.of(context).colorTheme.accentRed, - onTap: () async { - _showDeleteDialog(); - }, - ), - OptionListTile( - leading: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: StreamSvgIcon.close_small( - color: StreamChatTheme.of(context).colorTheme.grey, - ), - ), - title: 'Cancel', - onTap: () { - Navigator.pop(context); - }, - ), - ], - ), ); } From 48f9897c6337525779b4d306dbfccf596a434b59 Mon Sep 17 00:00:00 2001 From: Salvatore Giordano Date: Tue, 19 Jan 2021 10:10:57 +0100 Subject: [PATCH 6/7] fix readlist filter --- packages/flutter_widgets/lib/src/message_list_view.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/flutter_widgets/lib/src/message_list_view.dart b/packages/flutter_widgets/lib/src/message_list_view.dart index a0b5a60d..97434934 100644 --- a/packages/flutter_widgets/lib/src/message_list_view.dart +++ b/packages/flutter_widgets/lib/src/message_list_view.dart @@ -813,9 +813,7 @@ class _MessageListViewState extends State { final readList = channel.state?.read?.where((read) { if (read.user.id == userId) return false; return (read.lastRead.isAfter(message.createdAt) || - read.lastRead.isAtSameMomentAs(message.createdAt)) && - (index == 0 || - read.lastRead.isBefore(messages[index - 1].createdAt)); + read.lastRead.isAtSameMomentAs(message.createdAt)); })?.toList() ?? []; From 1785ade1b071a0e8e174e3e6b3a7e2b31082828d Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Tue, 19 Jan 2021 15:46:23 +0530 Subject: [PATCH 7/7] fix: Added correct paddings for error --- packages/flutter_widgets/lib/src/message_widget.dart | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/flutter_widgets/lib/src/message_widget.dart b/packages/flutter_widgets/lib/src/message_widget.dart index 070aa271..226f6f56 100644 --- a/packages/flutter_widgets/lib/src/message_widget.dart +++ b/packages/flutter_widgets/lib/src/message_widget.dart @@ -381,12 +381,14 @@ class _MessageWidgetState extends State { clipBehavior: Clip.antiAlias, elevation: 0.0, margin: EdgeInsets.symmetric( - horizontal: - widget.showUserAvatar == + horizontal: (isFailedState + ? 15.0 + : 0.0) + + (widget.showUserAvatar == DisplayWidget .gone ? 0 - : 4.0, + : 4.0), ), shape: widget.shape ?? RoundedRectangleBorder( @@ -453,8 +455,8 @@ class _MessageWidgetState extends State { ), if (isFailedState) Positioned( - left: widget.reverse ? -9 : null, - right: widget.reverse ? null : -9, + left: widget.reverse ? 0 : null, + right: widget.reverse ? null : 0, bottom: showBottomRow ? 18 : -2, child: StreamSvgIcon.error(size: 20), ),