From 9cc330a7bad45abab25cdb0b4a9070af18e7cd9f Mon Sep 17 00:00:00 2001 From: Vatsal Tanna Date: Sun, 30 Jun 2024 22:56:53 +0530 Subject: [PATCH] fix: :bug: fixed y position of reaction popup --- CHANGELOG.md | 13 +- lib/src/widgets/chat_list_widget.dart | 25 +- lib/src/widgets/chat_view.dart | 223 ++++++++++-------- .../widgets/chat_view_inherited_widget.dart | 4 + lib/src/widgets/message_view.dart | 2 +- lib/src/widgets/reaction_popup.dart | 12 +- 6 files changed, 155 insertions(+), 124 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee1fdb58..de7f721f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,13 @@ +## [2.0.1] + +* **Fix**: [217](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/217) fixed y + position of reaction popup + ## [2.0.0] -* **Breaking**: [203](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/203) Dart +* **Breaking**: [203](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/203) Dart Minimum Version 3.2.0. -* **Breaking**: [202](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/202) +* **Breaking**: [202](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/202) Message copyWith id value fix. * **Breaking**: [173](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/173) Added callback to sort message in chat. @@ -25,7 +30,7 @@ for configuring the audio recording quality. * **Feat**: [93](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/93) Added support that provide date pattern to change chat separation. -* **Fix**: [200](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/200) ChatView +* **Fix**: [200](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/200) ChatView iOS Padding Issue Fix * **Fix**: [139](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/139) Added support to customize view for the reply of any message. @@ -60,7 +65,7 @@ send to closed socket or animate on `ScrollController` without clients. * **Fix**: [194](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/194) Dispose all `ValueNotifier`s and `ScrollController`s in `ChatController`. -* **chore**: [168](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/168) Update +* **chore**: [168](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/168) Update intl to version 0.19.0. ## [1.3.1] diff --git a/lib/src/widgets/chat_list_widget.dart b/lib/src/widgets/chat_list_widget.dart index 87278c3c..ace0d23d 100644 --- a/lib/src/widgets/chat_list_widget.dart +++ b/lib/src/widgets/chat_list_widget.dart @@ -28,7 +28,6 @@ import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/material.dart'; import '../../chatview.dart'; -import 'reaction_popup.dart'; import 'reply_popup_widget.dart'; class ChatListWidget extends StatefulWidget { @@ -73,8 +72,6 @@ class ChatListWidget extends StatefulWidget { class _ChatListWidgetState extends State with SingleTickerProviderStateMixin { final ValueNotifier _isNextPageLoading = ValueNotifier(false); - ValueNotifier showPopUp = ValueNotifier(false); - final GlobalKey _reactionPopupKey = GlobalKey(); ChatController get chatController => widget.chatController; @@ -136,7 +133,7 @@ class _ChatListWidgetState extends State ), Expanded( child: ValueListenableBuilder( - valueListenable: showPopUp, + valueListenable: chatViewIW!.showPopUp, builder: (_, showPopupValue, child) { return Stack( children: [ @@ -149,14 +146,12 @@ class _ChatListWidgetState extends State replyMessage: widget.replyMessage, onChatBubbleLongPress: (yCoordinate, xCoordinate, message) { if (featureActiveConfig?.enableReactionPopup ?? false) { - _reactionPopupKey.currentState?.refreshWidget( + chatViewIW?.reactionPopupKey.currentState?.refreshWidget( message: message, xCoordinate: xCoordinate, - yCoordinate: yCoordinate < 0 - ? -(yCoordinate) - 5 - : yCoordinate, + yCoordinate: yCoordinate, ); - showPopUp.value = true; + chatViewIW?.showPopUp.value = true; } if (featureActiveConfig?.enableReplySnackBar ?? false) { _showReplyPopup( @@ -167,12 +162,7 @@ class _ChatListWidgetState extends State }, onChatListTap: _onChatListTap, ), - if (featureActiveConfig?.enableReactionPopup ?? false) - ReactionPopup( - key: _reactionPopupKey, - onTap: _onChatListTap, - showPopUp: showPopupValue, - ), + ], ); }, @@ -230,7 +220,7 @@ class _ChatListWidgetState extends State onReplyTap: () { widget.assignReplyMessage(message); if (featureActiveConfig?.enableReactionPopup ?? false) { - showPopUp.value = false; + chatViewIW?.showPopUp.value = false; } ScaffoldMessenger.of(context).hideCurrentSnackBar(); if (replyPopup?.onReplyTap != null) { @@ -250,7 +240,7 @@ class _ChatListWidgetState extends State if (!kIsWeb && (Platform.isIOS || Platform.isAndroid)) { FocusScope.of(context).unfocus(); } - showPopUp.value = false; + chatViewIW?.showPopUp.value = false; ScaffoldMessenger.of(context).hideCurrentSnackBar(); } @@ -259,7 +249,6 @@ class _ChatListWidgetState extends State chatViewIW?.chatController.messageStreamController.close(); scrollController.dispose(); _isNextPageLoading.dispose(); - showPopUp.dispose(); super.dispose(); } } diff --git a/lib/src/widgets/chat_view.dart b/lib/src/widgets/chat_view.dart index 0cffe786..5a9e5ece 100644 --- a/lib/src/widgets/chat_view.dart +++ b/lib/src/widgets/chat_view.dart @@ -19,13 +19,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ +import 'dart:io'; + import 'package:chatview/chatview.dart'; import 'package:chatview/src/extensions/extensions.dart'; import 'package:chatview/src/inherited_widgets/configurations_inherited_widgets.dart'; import 'package:chatview/src/widgets/chat_list_widget.dart'; import 'package:chatview/src/widgets/chat_view_inherited_widget.dart'; import 'package:chatview/src/widgets/chatview_state_widget.dart'; +import 'package:chatview/src/widgets/reaction_popup.dart'; import 'package:chatview/src/widgets/suggestions/suggestions_config_inherited_widget.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:timeago/timeago.dart'; import '../values/custom_time_messages.dart'; @@ -191,111 +195,135 @@ class _ChatViewState extends State child: SuggestionsConfigIW( suggestionsConfig: widget.replySuggestionsConfig, child: Builder(builder: (context) { - return Container( - height: chatBackgroundConfig.height ?? - MediaQuery.of(context).size.height, - width: - chatBackgroundConfig.width ?? MediaQuery.of(context).size.width, - decoration: BoxDecoration( - color: chatBackgroundConfig.backgroundColor ?? Colors.white, - image: chatBackgroundConfig.backgroundImage != null - ? DecorationImage( - fit: BoxFit.fill, - image: - NetworkImage(chatBackgroundConfig.backgroundImage!), - ) - : null, - ), - padding: chatBackgroundConfig.padding, - margin: chatBackgroundConfig.margin, - child: Column( - children: [ - if (widget.appBar != null) widget.appBar!, - Expanded( - child: ConfigurationsInheritedWidget( - chatBackgroundConfig: widget.chatBackgroundConfig, - reactionPopupConfig: widget.reactionPopupConfig, - typeIndicatorConfig: widget.typeIndicatorConfig, - chatBubbleConfig: widget.chatBubbleConfig, - replyPopupConfig: widget.replyPopupConfig, - messageConfig: widget.messageConfig, - profileCircleConfig: widget.profileCircleConfig, - repliedMessageConfig: widget.repliedMessageConfig, - swipeToReplyConfig: widget.swipeToReplyConfig, - emojiPickerSheetConfig: widget.emojiPickerSheetConfig, - child: Stack( - children: [ - if (chatViewState.isLoading) - ChatViewStateWidget( - chatViewStateWidgetConfig: - chatViewStateConfig?.loadingWidgetConfig, - chatViewState: chatViewState, - ) - else if (chatViewState.noMessages) - ChatViewStateWidget( - chatViewStateWidgetConfig: - chatViewStateConfig?.noMessageWidgetConfig, - chatViewState: chatViewState, - onReloadButtonTap: - chatViewStateConfig?.onReloadButtonTap, - ) - else if (chatViewState.isError) - ChatViewStateWidget( - chatViewStateWidgetConfig: - chatViewStateConfig?.errorWidgetConfig, - chatViewState: chatViewState, - onReloadButtonTap: - chatViewStateConfig?.onReloadButtonTap, - ) - else if (chatViewState.hasMessages) - ValueListenableBuilder( - valueListenable: replyMessage, - builder: (_, state, child) { - return ChatListWidget( - replyMessage: state, - chatController: widget.chatController, - loadMoreData: widget.loadMoreData, - isLastPage: widget.isLastPage, - loadingWidget: widget.loadingWidget, - onChatListTap: widget.onChatListTap, - assignReplyMessage: (message) => _sendMessageKey - .currentState - ?.assignReplyMessage(message), - ); - }, - ), - if (featureActiveConfig.enableTextField) - SendMessageWidget( - key: _sendMessageKey, - sendMessageBuilder: widget.sendMessageBuilder, - sendMessageConfig: widget.sendMessageConfig, - onSendTap: (message, replyMessage, messageType) { - if (context.suggestionsConfig - ?.autoDismissOnSelection ?? - true) { - chatController.removeReplySuggestions(); - } - _onSendTap(message, replyMessage, messageType); - }, - onReplyCallback: (reply) => - replyMessage.value = reply, - onReplyCloseCallback: () => - replyMessage.value = const ReplyMessage(), - messageConfig: widget.messageConfig, - replyMessageBuilder: widget.replyMessageBuilder, - ), - ], + return Stack( + children: [ + Container( + height: chatBackgroundConfig.height ?? + MediaQuery.of(context).size.height, + width: + chatBackgroundConfig.width ?? MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: chatBackgroundConfig.backgroundColor ?? Colors.white, + image: chatBackgroundConfig.backgroundImage != null + ? DecorationImage( + fit: BoxFit.fill, + image: + NetworkImage(chatBackgroundConfig.backgroundImage!), + ) + : null, + ), + padding: chatBackgroundConfig.padding, + margin: chatBackgroundConfig.margin, + child: Column( + children: [ + if (widget.appBar != null) widget.appBar!, + Expanded( + child: ConfigurationsInheritedWidget( + chatBackgroundConfig: widget.chatBackgroundConfig, + reactionPopupConfig: widget.reactionPopupConfig, + typeIndicatorConfig: widget.typeIndicatorConfig, + chatBubbleConfig: widget.chatBubbleConfig, + replyPopupConfig: widget.replyPopupConfig, + messageConfig: widget.messageConfig, + profileCircleConfig: widget.profileCircleConfig, + repliedMessageConfig: widget.repliedMessageConfig, + swipeToReplyConfig: widget.swipeToReplyConfig, + emojiPickerSheetConfig: widget.emojiPickerSheetConfig, + child: Stack( + children: [ + if (chatViewState.isLoading) + ChatViewStateWidget( + chatViewStateWidgetConfig: + chatViewStateConfig?.loadingWidgetConfig, + chatViewState: chatViewState, + ) + else if (chatViewState.noMessages) + ChatViewStateWidget( + chatViewStateWidgetConfig: + chatViewStateConfig?.noMessageWidgetConfig, + chatViewState: chatViewState, + onReloadButtonTap: + chatViewStateConfig?.onReloadButtonTap, + ) + else if (chatViewState.isError) + ChatViewStateWidget( + chatViewStateWidgetConfig: + chatViewStateConfig?.errorWidgetConfig, + chatViewState: chatViewState, + onReloadButtonTap: + chatViewStateConfig?.onReloadButtonTap, + ) + else if (chatViewState.hasMessages) + ValueListenableBuilder( + valueListenable: replyMessage, + builder: (_, state, child) { + return ChatListWidget( + replyMessage: state, + chatController: widget.chatController, + loadMoreData: widget.loadMoreData, + isLastPage: widget.isLastPage, + loadingWidget: widget.loadingWidget, + onChatListTap: widget.onChatListTap, + assignReplyMessage: (message) => _sendMessageKey + .currentState + ?.assignReplyMessage(message), + ); + }, + ), + if (featureActiveConfig.enableTextField) + SendMessageWidget( + key: _sendMessageKey, + sendMessageBuilder: widget.sendMessageBuilder, + sendMessageConfig: widget.sendMessageConfig, + onSendTap: (message, replyMessage, messageType) { + if (context.suggestionsConfig + ?.autoDismissOnSelection ?? + true) { + chatController.removeReplySuggestions(); + } + _onSendTap(message, replyMessage, messageType); + }, + onReplyCallback: (reply) => + replyMessage.value = reply, + onReplyCloseCallback: () => + replyMessage.value = const ReplyMessage(), + messageConfig: widget.messageConfig, + replyMessageBuilder: widget.replyMessageBuilder, + ), + ], + ), + ), ), - ), + ], + ), + ), + if (featureActiveConfig.enableReactionPopup) + ValueListenableBuilder( + valueListenable: context.chatViewIW!.showPopUp, + builder: (_, showPopupValue, child) { + return ReactionPopup( + key: context.chatViewIW!.reactionPopupKey, + onTap: () => _onChatListTap(context), + showPopUp: showPopupValue, + ); + }, ), - ], - ), + ], ); }), ), ); } + void _onChatListTap(BuildContext context) { + widget.onChatListTap?.call(); + if (!kIsWeb && (Platform.isIOS || Platform.isAndroid)) { + FocusScope.of(context).unfocus(); + } + context.chatViewIW?.showPopUp.value = false; + ScaffoldMessenger.of(context).hideCurrentSnackBar(); + } + void _onSendTap( String message, ReplyMessage replyMessage, @@ -321,6 +349,7 @@ class _ChatViewState extends State @override void dispose() { replyMessage.dispose(); + chatViewIW?.showPopUp.dispose(); super.dispose(); } } diff --git a/lib/src/widgets/chat_view_inherited_widget.dart b/lib/src/widgets/chat_view_inherited_widget.dart index e9a1ff1c..92e86f22 100644 --- a/lib/src/widgets/chat_view_inherited_widget.dart +++ b/lib/src/widgets/chat_view_inherited_widget.dart @@ -1,3 +1,4 @@ +import 'package:chatview/src/widgets/reaction_popup.dart'; import 'package:flutter/material.dart'; import 'package:chatview/chatview.dart'; @@ -15,6 +16,9 @@ class ChatViewInheritedWidget extends InheritedWidget { final ProfileCircleConfiguration? profileCircleConfiguration; final ChatController chatController; final GlobalKey chatTextFieldViewKey = GlobalKey(); + final ValueNotifier showPopUp = ValueNotifier(false); + final GlobalKey reactionPopupKey = GlobalKey(); + static ChatViewInheritedWidget? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType(); diff --git a/lib/src/widgets/message_view.dart b/lib/src/widgets/message_view.dart index 2b834bd9..2d1215f5 100644 --- a/lib/src/widgets/message_view.dart +++ b/lib/src/widgets/message_view.dart @@ -269,7 +269,7 @@ class _MessageViewState extends State void _onLongPressStart(LongPressStartDetails details) async { await _animationController?.forward(); widget.onLongPress( - details.globalPosition.dy - 120 - 64, + details.globalPosition.dy, details.globalPosition.dx, ); } diff --git a/lib/src/widgets/reaction_popup.dart b/lib/src/widgets/reaction_popup.dart index 4fc10c1c..d7330300 100644 --- a/lib/src/widgets/reaction_popup.dart +++ b/lib/src/widgets/reaction_popup.dart @@ -165,10 +165,14 @@ class ReactionPopupState extends State required double xCoordinate, required double yCoordinate, }) { - setState(() { - _message = message; - _xCoordinate = xCoordinate; - _yCoordinate = yCoordinate; + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + final yPosition = yCoordinate - + (chatViewIW!.reactionPopupKey.currentContext?.size?.height ?? 0); + _message = message; + _xCoordinate = xCoordinate; + _yCoordinate = yPosition < 0 ? 0 : yPosition; + }); }); }