From f5ad0d7a0e2b8c87dbb7d812415487fff9780ad6 Mon Sep 17 00:00:00 2001 From: Apurva Kanthraviya Date: Thu, 30 May 2024 14:25:23 +0530 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=90=9B=20add=20support=20for=20cus?= =?UTF-8?q?tomize=20view=20for=20the=20reply=20of=20any=20message=20#139?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 +- README.md | 61 ++++++++ lib/src/values/typedefs.dart | 8 ++ lib/src/widgets/chat_view.dart | 16 +++ lib/src/widgets/reactions_bottomsheet.dart | 1 - lib/src/widgets/send_message_widget.dart | 160 +++++++++++---------- 6 files changed, 175 insertions(+), 75 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94e1cc1b..ce3c224b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,13 @@ ## [1.3.2] (Unreleased) +* **Fix**: [139](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/139) Added + support to customize view for the reply of any message. * **Fix**: [174](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/174) Fix wrong username shown while replying to any messages. * **Fix**: [134](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/134) Added a reply message view for custom message type. * **Feat**: [157](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/157) - Added onTap of reacted user from reacted user list + Added onTap of reacted user from reacted user list. * **Fix**: [137](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/137) Added support for cancel voice recording and field to provide cancel record icon. * **Feat**: [93](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/93) Added support diff --git a/README.md b/README.md index 3d2deccb..af0490b8 100644 --- a/README.md +++ b/README.md @@ -681,6 +681,67 @@ ChatView( ) ``` +30. Added a `replyMessageBuilder` to customize view for the reply. + +```dart +ChatView( + ... + replyMessageBuilder: (context, state) { + return Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical( + top: Radius.circular(14), + ), + ), + margin: const EdgeInsets.only( + bottom: 17, + right: 0.4, + left: 0.4, + ), + padding: const EdgeInsets.fromLTRB(10, 10, 10, 30), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, + ), + decoration: BoxDecoration( + color: Colors.grey.shade200, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + state.message, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + IconButton( + constraints: const BoxConstraints(), + padding: EdgeInsets.zero, + icon: const Icon( + Icons.close, + size: 16, + ), + onPressed: () => ChatView.replyMessageViewClose(context), + ), + ], + ), + ], + ), + ), + ); + }, + ... +) +``` + ## How to use diff --git a/lib/src/values/typedefs.dart b/lib/src/values/typedefs.dart index 7be43ca7..30e9a288 100644 --- a/lib/src/values/typedefs.dart +++ b/lib/src/values/typedefs.dart @@ -47,4 +47,12 @@ typedef ReactedUserCallback = void Function( ChatUser reactedUser, String reaction, ); + +/// customMessageType view for a reply of custom message type typedef CustomMessageReplyViewBuilder = Widget Function(ReplyMessage state); + +/// customView for replying to any message +typedef CustomViewForReplyMessage = Widget Function( + BuildContext context, + ReplyMessage state, +); diff --git a/lib/src/widgets/chat_view.dart b/lib/src/widgets/chat_view.dart index 532f4302..d888c544 100644 --- a/lib/src/widgets/chat_view.dart +++ b/lib/src/widgets/chat_view.dart @@ -56,6 +56,7 @@ class ChatView extends StatefulWidget { this.featureActiveConfig = const FeatureActiveConfig(), this.chatTextFieldTopPadding = 0, this.emojiPickerSheetConfig, + this.replyMessageBuilder, }) : chatBackgroundConfig = chatBackgroundConfig ?? const ChatBackgroundConfiguration(), chatViewStateConfig = @@ -145,6 +146,16 @@ class ChatView extends StatefulWidget { /// Configuration for emoji picker sheet final Config? emojiPickerSheetConfig; + /// Provides callback for reply view of message + final CustomViewForReplyMessage? replyMessageBuilder; + + static void replyMessageViewClose(BuildContext context) { + final state = context.findAncestorStateOfType<_ChatViewState>(); + if (state != null) { + state.replyMessageViewClose(); + } + } + @override State createState() => _ChatViewState(); } @@ -276,6 +287,7 @@ class _ChatViewState extends State onReplyCloseCallback: () => replyMessage.value = const ReplyMessage(), messageConfig: widget.messageConfig, + replyMessageBuilder: widget.replyMessageBuilder, ), ], ), @@ -300,6 +312,10 @@ class _ChatViewState extends State chatController.scrollToLastMessage(); } + void replyMessageViewClose() { + _sendMessageKey.currentState?.onCloseTap(); + } + void _assignReplyMessage() { if (replyMessage.value.message.isNotEmpty) { replyMessage.value = const ReplyMessage(); diff --git a/lib/src/widgets/reactions_bottomsheet.dart b/lib/src/widgets/reactions_bottomsheet.dart index 6fb42a1e..0a271548 100644 --- a/lib/src/widgets/reactions_bottomsheet.dart +++ b/lib/src/widgets/reactions_bottomsheet.dart @@ -1,7 +1,6 @@ import 'package:chatview/src/controller/chat_controller.dart'; import 'package:chatview/src/models/models.dart'; import 'package:chatview/src/utils/constants/constants.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class ReactionsBottomSheet { diff --git a/lib/src/widgets/send_message_widget.dart b/lib/src/widgets/send_message_widget.dart index fad40d3a..5941d603 100644 --- a/lib/src/widgets/send_message_widget.dart +++ b/lib/src/widgets/send_message_widget.dart @@ -42,6 +42,7 @@ class SendMessageWidget extends StatefulWidget { this.onReplyCallback, this.onReplyCloseCallback, this.messageConfig, + this.replyMessageBuilder, }) : super(key: key); /// Provides call back when user tap on send button on text field. @@ -68,6 +69,9 @@ class SendMessageWidget extends StatefulWidget { /// Provides configuration of all types of messages. final MessageConfiguration? messageConfig; + /// Provides callback for reply view of message + final CustomViewForReplyMessage? replyMessageBuilder; + @override State createState() => SendMessageWidgetState(); } @@ -138,83 +142,93 @@ class SendMessageWidgetState extends State { final replyTitle = "${PackageStrings.replyTo} $_replyTo"; if (state.message.isNotEmpty) { - return Container( - decoration: BoxDecoration( - color: widget.sendMessageConfig - ?.textFieldBackgroundColor ?? - Colors.white, - borderRadius: const BorderRadius.vertical( - top: Radius.circular(14), - ), - ), - margin: const EdgeInsets.only( - bottom: 17, - right: 0.4, - left: 0.4, - ), - padding: const EdgeInsets.fromLTRB( - leftPadding, - leftPadding, - leftPadding, - 30, - ), - child: Container( - margin: const EdgeInsets.only(bottom: 2), - padding: const EdgeInsets.symmetric( - vertical: 4, - horizontal: 6, - ), - decoration: BoxDecoration( - color: widget.sendMessageConfig - ?.replyDialogColor ?? - Colors.grey.shade200, - borderRadius: BorderRadius.circular(12), - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + return widget.replyMessageBuilder + ?.call(context, state) ?? + Container( + decoration: BoxDecoration( + color: widget.sendMessageConfig + ?.textFieldBackgroundColor ?? + Colors.white, + borderRadius: const BorderRadius.vertical( + top: Radius.circular(14), + ), + ), + margin: const EdgeInsets.only( + bottom: 17, + right: 0.4, + left: 0.4, + ), + padding: const EdgeInsets.fromLTRB( + leftPadding, + leftPadding, + leftPadding, + 30, + ), + child: Container( + margin: const EdgeInsets.only(bottom: 2), + padding: const EdgeInsets.symmetric( + vertical: 4, + horizontal: 6, + ), + decoration: BoxDecoration( + color: widget.sendMessageConfig + ?.replyDialogColor ?? + Colors.grey.shade200, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, children: [ - Text( - replyTitle, - style: TextStyle( - color: widget.sendMessageConfig - ?.replyTitleColor ?? - Colors.deepPurple, - fontWeight: FontWeight.bold, - letterSpacing: 0.25, - ), + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + replyTitle, + maxLines: 1, + overflow: + TextOverflow.ellipsis, + style: TextStyle( + color: widget + .sendMessageConfig + ?.replyTitleColor ?? + Colors.deepPurple, + fontWeight: FontWeight.bold, + letterSpacing: 0.25, + ), + ), + ), + IconButton( + constraints: + const BoxConstraints(), + padding: EdgeInsets.zero, + icon: Icon( + Icons.close, + color: widget + .sendMessageConfig + ?.closeIconColor ?? + Colors.black, + size: 16, + ), + onPressed: onCloseTap, + ), + ], ), - IconButton( - constraints: const BoxConstraints(), - padding: EdgeInsets.zero, - icon: Icon( - Icons.close, - color: widget.sendMessageConfig - ?.closeIconColor ?? - Colors.black, - size: 16, - ), - onPressed: _onCloseTap, + ReplyMessageView( + message: state, + customMessageReplyViewBuilder: widget + .messageConfig + ?.customMessageReplyViewBuilder, + sendMessageConfig: + widget.sendMessageConfig, ), ], ), - ReplyMessageView( - message: state, - customMessageReplyViewBuilder: widget - .messageConfig - ?.customMessageReplyViewBuilder, - sendMessageConfig: - widget.sendMessageConfig, - ), - ], - ), - ), - ); + ), + ); } else { return const SizedBox.shrink(); } @@ -287,7 +301,7 @@ class SendMessageWidgetState extends State { if (widget.onReplyCallback != null) widget.onReplyCallback!(replyMessage); } - void _onCloseTap() { + void onCloseTap() { _replyMessage.value = const ReplyMessage(); if (widget.onReplyCloseCallback != null) widget.onReplyCloseCallback!(); }