diff --git a/README.md b/README.md index e54eed85..f0385f26 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ![Banner](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/flutter_chatview/main/preview/banner.png) # ChatView + [![chatview](https://img.shields.io/pub/v/chatview?label=chatview)](https://pub.dev/packages/chatview) A Flutter package that allows you to integrate Chat View with highly customization options such as one on one @@ -25,164 +26,178 @@ For web demo visit [Chat View Example](https://simformsolutionspvtltd.github.io/ - Removed `showTypingIndicator` field from `ChatView` and replaced it with `ChatController.showTypingIndicator`. Before: - ```dart - ChatView( - showTypingIndicator:false, - ), - ``` + + ```dart + ChatView( + showTypingIndicator:false, + ), + ``` After: - ```dart - /// use it with your [ChatController] instance. - _chatContoller.setTypingIndicator = true; // for showing indicator - _chatContoller.setTypingIndicator = false; // for hiding indicator - ``` + + ```dart + /// use it with your [ChatController] instance. + _chatContoller.setTypingIndicator = true; // for showing indicator + _chatContoller.setTypingIndicator = false; // for hiding indicator + ``` - Updated `ChatUser`, `Message` and `ReplyMessage` Data Model's `fromJson` and `toJson` methods: ##### in `ChatUser.fromJson`: Before: - ```dart - ChatUser.fromJson( - { - ... - 'imageType': ImageType.asset, - ... - }, - ), - ``` - - After: - ```dart - ChatUser.fromJson( - { - ... - 'imageType': 'asset', - ... - }, - ), - ``` - - ##### in `ChatUser.toJson`: - Before: - ```dart + ```dart + ChatUser.fromJson( { ... - imageType: ImageType.asset, + 'imageType': ImageType.asset, ... - } - ``` + }, + ), + ``` After: - ```dart + + ```dart + ChatUser.fromJson( { ... - imageType: asset, + 'imageType': 'asset', ... - } - ``` + }, + ), + ``` - ##### in `Message.fromJson`: + ##### in `ChatUser.toJson`: Before: - ```dart - Message.fromJson( - { - ... - 'createdAt': DateTime.now(), - 'message_type': MessageType.text, - 'voice_message_duration': Duration(seconds: 5), - ... - } - ) - ``` + + ```dart + { + ... + imageType: ImageType.asset, + ... + } + ``` After: - ```dart - Message.fromJson( - { - ... - 'createdAt': '2024-06-13T17:32:19.586412', - 'message_type': 'text', - 'voice_message_duration': '5000000', - ... - } - ) - ``` - ##### in `Message.toJson`: + ```dart + { + ... + imageType: asset, + ... + } + ``` + + ##### in `Message.fromJson`: Before: - ```dart + + ```dart + Message.fromJson( { ... - createdAt: 2024-06-13 17:23:19.454789, - message_type: MessageType.text, - voice_message_duration: 0:00:05.000000, + 'createdAt': DateTime.now(), + 'message_type': MessageType.text, + 'voice_message_duration': Duration(seconds: 5), ... } - ``` + ) + ``` After: - ```dart + + ```dart + Message.fromJson( { ... - createdAt: 2024-06-13T17:32:19.586412, - message_type: text, - voice_message_duration: 5000000, + 'createdAt': '2024-06-13T17:32:19.586412', + 'message_type': 'text', + 'voice_message_duration': '5000000', ... } - ``` + ) + ``` - ##### in `ReplyMessage.fromJson`: + ##### in `Message.toJson`: Before: - ```dart - ReplyMessage.fromJson( - { - ... - 'message_type': MessageType.text, - 'voiceMessageDuration': Duration(seconds: 5), - ... - } - ) - ``` + + ```dart + { + ... + createdAt: 2024-06-13 17:23:19.454789, + message_type: MessageType.text, + voice_message_duration: 0:00:05.000000, + ... + } + ``` After: - ```dart - ReplyMessage.fromJson( - { - ... - 'message_type': 'text', - 'voiceMessageDuration': '5000000', - ... - } - ) - ``` - in `ReplyMessage.toJson`: + ```dart + { + ... + createdAt: 2024-06-13T17:32:19.586412, + message_type: text, + voice_message_duration: 5000000, + ... + } + ``` + + ##### in `ReplyMessage.fromJson`: Before: - ```dart + + ```dart + ReplyMessage.fromJson( { ... - message_type: MessageType.text, - voiceMessageDuration: 0:00:05.000000, + 'message_type': MessageType.text, + 'voiceMessageDuration': Duration(seconds: 5), ... } - ``` + ) + ``` After: - ```dart + + ```dart + ReplyMessage.fromJson( { ... - message_type: text, - voiceMessageDuration: 5000000, + 'message_type': 'text', + 'voiceMessageDuration': '5000000', ... } - ``` + ) + ``` + + in `ReplyMessage.toJson`: + + Before: + + ```dart + { + ... + message_type: MessageType.text, + voiceMessageDuration: 0:00:05.000000, + ... + } + ``` + + After: + + ```dart + { + ... + message_type: text, + voiceMessageDuration: 5000000, + ... + } + ``` ## Installing @@ -192,14 +207,17 @@ For web demo visit [Chat View Example](https://simformsolutionspvtltd.github.io/ dependencies: chatview: ``` -*Get the latest version in the 'Installing' tab on [pub.dev](https://pub.dev/packages/chatview)* + +_Get the latest version in the 'Installing' tab on [pub.dev](https://pub.dev/packages/chatview)_ 2. Import the package + ```dart import 'package:chatview/chatview.dart'; ``` 3. Adding a chat controller. + ```dart final chatController = ChatController( initialMessageList: messageList, @@ -210,6 +228,7 @@ final chatController = ChatController( ``` 4. Adding a `ChatView` widget. + ```dart ChatView( chatController: chatController, @@ -219,6 +238,7 @@ ChatView( ``` 5. Adding a messageList with `Message` class. + ```dart List messageList = [ Message( @@ -237,6 +257,7 @@ List messageList = [ ``` 6. Adding a `onSendTap`. + ```dart void onSendTap(String message, ReplyMessage replyMessage, MessageType messageType){ final message = Message( @@ -255,19 +276,20 @@ Note: you can evaluate message type from `messageType` parameter, based on that ## Messages types compability -|Message Types | Android | iOS | MacOS | Web | Linux | Windows | -| :-----: | :-----: | :-: | :---: | :-: | :---: | :-----: | -|Text messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -|Image messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -|Voice messages | ✔️ | ✔️ | ❌ | ❌ | ❌ | ❌ | -|Custom messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | - +| Message Types | Android | iOS | MacOS | Web | Linux | Windows | +| :-------------: | :-----: | :-: | :---: | :-: | :---: | :-----: | +| Text messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| Image messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| Voice messages | ✔️ | ✔️ | ❌ | ❌ | ❌ | ❌ | +| Custom messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ## Platform specific configuration ### For image Picker + #### iOS -* Add the following keys to your _Info.plist_ file, located in `/ios/Runner/Info.plist`: + +- Add the following keys to your _Info.plist_ file, located in `/ios/Runner/Info.plist`: ``` NSCameraUsageDescription @@ -279,32 +301,40 @@ Note: you can evaluate message type from `messageType` parameter, based on that ``` ### For voice messages + #### iOS -* Add this two rows in `ios/Runner/Info.plist` + +- Add this two rows in `ios/Runner/Info.plist` + ``` NSMicrophoneUsageDescription This app requires Mic permission. ``` -* This plugin requires ios 10.0 or higher. So add this line in `Podfile` + +- This plugin requires ios 10.0 or higher. So add this line in `Podfile` + ``` platform :ios, '10.0' ``` #### Android -* Change the minimum Android sdk version to 21 (or higher) in your android/app/build.gradle file. + +- Change the minimum Android sdk version to 21 (or higher) in your android/app/build.gradle file. + ``` minSdkVersion 21 ``` -* Add RECORD_AUDIO permission in `AndroidManifest.xml` +- Add RECORD_AUDIO permission in `AndroidManifest.xml` + ``` ``` - ## Some more optional parameters 1. Enable and disable specific features with `FeatureActiveConfig`. + ```dart ChatView( ... @@ -317,6 +347,7 @@ ChatView( ``` 2. Adding an appbar with `ChatViewAppBar`. + ```dart ChatView( ... @@ -333,6 +364,7 @@ ChatView( ``` 3. Adding a message list configuration with `ChatBackgroundConfiguration` class. + ```dart ChatView( ... @@ -345,6 +377,7 @@ ChatView( ``` 4. Adding a send message configuration with `SendMessageConfiguration` class. + ```dart ChatView( ... @@ -359,6 +392,7 @@ ChatView( ``` 5. Adding a chat bubble configuration with `ChatBubbleConfiguration` class. + ```dart ChatView( ... @@ -366,15 +400,15 @@ ChatView( onDoubleTap: (){ // Your code goes here }, - outgoingChatBubbleConfig: ChatBubble( // Sender's message chat bubble + outgoingChatBubble: ChatBubble( // Sender's message chat bubble color: Colors.blue, - borderRadius: const BorderRadius.only( + borderRadius: const BorderRadius.only( topRight: Radius.circular(12), topLeft: Radius.circular(12), bottomLeft: Radius.circular(12), ), ), - inComingChatBubbleConfig: ChatBubble( // Receiver's message chat bubble + incomingChatBubble: ChatBubble( // Receiver's message chat bubble color: Colors.grey.shade200, borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), @@ -388,6 +422,7 @@ ChatView( ``` 6. Adding swipe to reply configuration with `SwipeToReplyConfiguration` class. + ```dart ChatView( ... @@ -397,22 +432,23 @@ ChatView( }, onRightSwipe: (message, sentBy){ // Your code goes here - }, + }, ), ... ) ``` 7. Adding messages configuration with `MessageConfiguration` class. + ```dart ChatView( ... messageConfig: MessageConfiguration( - messageReactionConfig: MessageReactionConfiguration(), // Emoji reaction configuration for single message + messageReactionConfig: MessageReactionConfiguration(), // Emoji reaction configuration for single message imageMessageConfig: ImageMessageConfiguration( onTap: (){ // Your code goes here - }, + }, shareIconConfig: ShareIconConfiguration( onPressed: (){ // Your code goes here @@ -425,6 +461,7 @@ ChatView( ``` 8. Adding reaction pop-up configuration with `ReactionPopupConfiguration` class. + ```dart ChatView( ... @@ -444,6 +481,7 @@ ChatView( ``` 9. Adding reply pop-up configuration with `ReplyPopupConfiguration` class. + ```dart ChatView( ... @@ -467,6 +505,7 @@ ChatView( ``` 10. Adding replied message configuration with `RepliedMessageConfiguration` class. + ```dart ChatView( ... @@ -479,12 +518,13 @@ ChatView( ) ``` -11. For customizing typing indicators use `typeIndicatorConfig` with `TypeIndicatorConfig`. +11. For customizing typing indicators use `typingIndicatorConfig` with `TypeIndicatorConfig`. + ```dart ChatView( ... - typeIndicatorConfig: TypeIndicatorConfiguration( + typingIndicatorConfig: TypingIndicatorConfiguration( flashingCircleBrightColor: Colors.grey, flashingCircleDarkColor: Colors.black, ), @@ -492,7 +532,9 @@ ChatView( ) ``` + 12. For showing hiding typeIndicatorwidget use `ChatController.setTypingIndicaor`, for more info see `ChatController`. + ```dart /// use it with your [ChatController] instance. _chatContoller.setTypingIndicator = true; // for showing indicator @@ -500,6 +542,7 @@ _chatContoller.setTypingIndicator = false; // for hiding indicator ``` 13. Adding linkpreview configuration with `LinkPreviewConfiguration` class. + ```dart ChatView( ... @@ -525,6 +568,7 @@ ChatView( ``` 14. Adding pagination. + ```dart ChatView( ... @@ -538,6 +582,7 @@ ChatView( ``` 15. Add image picker configuration. + ```dart ChatView( ... @@ -554,6 +599,7 @@ ChatView( ``` 16. Add `ChatViewState` customisations. + ```dart ChatView( ... @@ -568,6 +614,7 @@ ChatView( ``` 17. Setting auto scroll and highlight config with `RepliedMsgAutoScrollConfig` class. + ```dart ChatView( ... @@ -586,14 +633,14 @@ ChatView( ChatView( ... sendMessageConfig: SendMessageConfiguration( - + textFieldConfig: TextFieldConfiguration( onMessageTyping: (status) { // send composing/composed status to other client // your code goes here - }, + }, + - /// After typing stopped, the threshold time after which the composing /// status to be changed to [TypeWriterStatus.typed]. /// Default is 1 second. @@ -605,7 +652,7 @@ ChatView( ) ``` -19. Passing customReceipts builder or handling stuffs related receipts see `ReceiptsWidgetConfig` in outgoingChatBubbleConfig. +19. Passing customReceipts builder or handling stuffs related receipts see `ReceiptsWidgetConfig` in outgoingChatBubble. ```dart ChatView( @@ -614,28 +661,28 @@ ChatView( /// Controls the visibility of message seen ago receipts default is true lastSeenAgoBuilderVisibility: false, /// Controls the visibility of the message [receiptsBuilder] - receiptsBuilderVisibility: false), + receiptsBuilderVisibility: false), ChatBubbleConfiguration( - inComingChatBubbleConfig: ChatBubble( + incomingChatBubble: ChatBubble( onMessageRead: (message) { /// send your message reciepts to the other client debugPrint('Message Read'); }, ), - outgoingChatBubbleConfig: ChatBubble( + outgoingChatBubble: ChatBubble( receiptsWidgetConfig: ReceiptsWidgetConfig( - /// custom receipts builder + /// custom receipts builder receiptsBuilder: _customReceiptsBuilder, - /// whether to display receipts in all + /// whether to display receipts in all /// message or just at the last one just like instagram showReceiptsIn: ShowReceiptsIn.lastMessage ), - ), - ), - + ), + ), + ... - + ) ``` @@ -686,7 +733,7 @@ ChatView( recentTabBehavior: RecentTabBehavior.NONE, ), ... - + ) ``` @@ -700,7 +747,7 @@ ChatView( voiceRecordingConfiguration: VoiceRecordingConfiguration( iosEncoder: IosEncoder.kAudioFormatMPEG4AAC, androidOutputFormat: AndroidOutputFormat.mpeg4, - androidEncoder: AndroidEncoder.aac, + androidEncoder: AndroidEncoder.aac, bitRate: 128000, sampleRate: 44100, waveStyle: WaveStyle( @@ -709,7 +756,7 @@ ChatView( extendWaveform: true, ), ), - + ... ) ) @@ -728,9 +775,10 @@ ChatView( ... ), ... - + ) ``` + 25. Added flag `isProfilePhotoInBase64` that defines whether provided image is url or base64 data. ```dart @@ -797,6 +845,7 @@ ChatView( ``` 28. Added callback of onTap on list of reacted users in reaction sheet `reactedUserCallback`. + ```dart ChatView( @@ -841,6 +890,7 @@ ChatView( 30. Add default avatar for profile image `defaultAvatarImage`, error builder for asset and network profile image `assetImageErrorBuilder` `networkImageErrorBuilder`, Enum `ImageType` to define image as asset, network or base64 data. + ```dart ChatView( ... @@ -918,7 +968,7 @@ ChatView( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: Text( + child: Text( state.message, maxLines: 1, overflow: TextOverflow.ellipsis, @@ -949,7 +999,8 @@ ChatView( 33. Reply Suggestions functionalities. -* Add reply suggestions +- Add reply suggestions + ```dart _chatController.addReplySuggestions([ SuggestionItemData(text: 'Thanks.'), @@ -957,11 +1008,15 @@ _chatController.addReplySuggestions([ SuggestionItemData(text: 'Great.') ]); ``` -* Remove reply suggestions + +- Remove reply suggestions + ```dart _chatController.removeReplySuggestions(); ``` -* Update suggestions Config + +- Update suggestions Config + ```dart replySuggestionsConfig: ReplySuggestionsConfig( itemConfig: SuggestionItemConfig( @@ -1000,7 +1055,6 @@ ChatView( 35. Use `ScrollToBottomButtonConfig` to change the configuration of scroll to bottom button. - ```dart ChatView( ... @@ -1017,7 +1071,6 @@ Check out [blog](https://medium.com/simform-engineering/chatview-a-cutting-edge- Also, for whole example, check out the **example** app in the [example](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/tree/main/example) directory or the 'Example' tab on pub.dartlang.org for a more complete example. - ## Main Contributors diff --git a/example/lib/main.dart b/example/lib/main.dart index 8c1fa88e..b03d2399 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -117,7 +117,7 @@ class _ChatScreenState extends State { ), onReloadButtonTap: () {}, ), - typeIndicatorConfig: TypeIndicatorConfiguration( + typingIndicatorConfig: TypingIndicatorConfiguration( flashingCircleBrightColor: theme.flashingCircleBrightColor, flashingCircleDarkColor: theme.flashingCircleDarkColor, ), @@ -206,7 +206,7 @@ class _ChatScreenState extends State { ), ), chatBubbleConfig: ChatBubbleConfiguration( - outgoingChatBubbleConfig: ChatBubble( + outgoingChatBubble: ChatBubble( linkPreviewConfig: LinkPreviewConfiguration( backgroundColor: theme.linkPreviewOutgoingChatColor, bodyStyle: theme.outgoingChatLinkBodyStyle, @@ -215,7 +215,7 @@ class _ChatScreenState extends State { receiptsWidgetConfig: const ReceiptsWidgetConfig(showReceiptsIn: ShowReceiptsIn.all), color: theme.outgoingChatBubbleColor, ), - inComingChatBubbleConfig: ChatBubble( + incomingChatBubble: ChatBubble( linkPreviewConfig: LinkPreviewConfiguration( linkStyle: TextStyle( color: theme.inComingChatBubbleTextColor, diff --git a/lib/src/inherited_widgets/configurations_inherited_widgets.dart b/lib/src/inherited_widgets/configurations_inherited_widgets.dart index b9059cc6..df827295 100644 --- a/lib/src/inherited_widgets/configurations_inherited_widgets.dart +++ b/lib/src/inherited_widgets/configurations_inherited_widgets.dart @@ -13,7 +13,7 @@ class ConfigurationsInheritedWidget extends InheritedWidget { this.profileCircleConfig, this.swipeToReplyConfig, this.repliedMessageConfig, - this.typeIndicatorConfig, + this.typingIndicatorConfig, this.replyPopupConfig, this.emojiPickerSheetConfig, this.scrollToBottomButtonConfig, @@ -43,7 +43,7 @@ class ConfigurationsInheritedWidget extends InheritedWidget { final RepliedMessageConfiguration? repliedMessageConfig; /// Provides configuration of typing indicator's appearance. - final TypeIndicatorConfiguration? typeIndicatorConfig; + final TypingIndicatorConfiguration? typingIndicatorConfig; /// Provides configuration for reply snack bar's appearance and options. final ReplyPopupConfiguration? replyPopupConfig; @@ -54,10 +54,9 @@ class ConfigurationsInheritedWidget extends InheritedWidget { /// Provides a configuration for scroll to bottom button config final ScrollToBottomButtonConfig? scrollToBottomButtonConfig; - static ConfigurationsInheritedWidget? of(BuildContext context) => context - .dependOnInheritedWidgetOfExactType(); + static ConfigurationsInheritedWidget? of(BuildContext context) => + context.dependOnInheritedWidgetOfExactType(); @override - bool updateShouldNotify(covariant ConfigurationsInheritedWidget oldWidget) => - oldWidget != this; + bool updateShouldNotify(covariant ConfigurationsInheritedWidget oldWidget) => oldWidget != this; } diff --git a/lib/src/models/config_models/chat_bubble_configuration.dart b/lib/src/models/config_models/chat_bubble_configuration.dart index 2f1222d8..92c3aad9 100644 --- a/lib/src/models/config_models/chat_bubble_configuration.dart +++ b/lib/src/models/config_models/chat_bubble_configuration.dart @@ -39,10 +39,10 @@ class ChatBubbleConfiguration { final Duration? longPressAnimationDuration; /// Provides configuration of other users message's chat bubble. - final ChatBubble? inComingChatBubbleConfig; + final ChatBubble? incomingChatBubble; /// Provides configuration of current user message's chat bubble. - final ChatBubble? outgoingChatBubbleConfig; + final ChatBubble? outgoingChatBubble; /// Provides callback when user tap twice on chat bubble. final MessageCallBack? onDoubleTap; @@ -54,8 +54,8 @@ class ChatBubbleConfiguration { this.margin, this.maxWidth, this.longPressAnimationDuration, - this.inComingChatBubbleConfig, - this.outgoingChatBubbleConfig, + this.incomingChatBubble, + this.outgoingChatBubble, this.onDoubleTap, this.receiptsWidgetConfig, }); diff --git a/lib/src/models/config_models/type_indicator_configuration.dart b/lib/src/models/config_models/type_indicator_configuration.dart index a8852f0c..e674b3a0 100644 --- a/lib/src/models/config_models/type_indicator_configuration.dart +++ b/lib/src/models/config_models/type_indicator_configuration.dart @@ -21,7 +21,7 @@ */ import 'package:flutter/material.dart'; -class TypeIndicatorConfiguration { +class TypingIndicatorConfiguration { /// Used for giving typing indicator size. final double? indicatorSize; @@ -34,7 +34,7 @@ class TypeIndicatorConfiguration { /// Used to give color of light circle dots. final Color? flashingCircleBrightColor; - const TypeIndicatorConfiguration({ + const TypingIndicatorConfiguration({ this.indicatorSize, this.indicatorSpacing, this.flashingCircleDarkColor, diff --git a/lib/src/widgets/chat_bubble_widget.dart b/lib/src/widgets/chat_bubble_widget.dart index 4c748f96..7f83103b 100644 --- a/lib/src/widgets/chat_bubble_widget.dart +++ b/lib/src/widgets/chat_bubble_widget.dart @@ -69,8 +69,7 @@ class _ChatBubbleWidgetState extends State { bool get isMessageBySender => widget.message.sentBy == currentUser?.id; - bool get isLastMessage => - chatController?.initialMessageList.last.id == widget.message.id; + bool get isLastMessage => chatController?.initialMessageList.last.id == widget.message.id; FeatureActiveConfig? featureActiveConfig; ChatController? chatController; @@ -123,19 +122,16 @@ class _ChatBubbleWidgetState extends State { margin: chatBubbleConfig?.margin ?? const EdgeInsets.only(bottom: 10), child: Row( mainAxisSize: MainAxisSize.min, - mainAxisAlignment: - isMessageBySender ? MainAxisAlignment.end : MainAxisAlignment.start, + mainAxisAlignment: isMessageBySender ? MainAxisAlignment.end : MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.end, children: [ - if (!isMessageBySender && - (featureActiveConfig?.enableOtherUserProfileAvatar ?? true)) + if (!isMessageBySender && (featureActiveConfig?.enableOtherUserProfileAvatar ?? true)) profileCircle(messagedUser), Expanded( child: _messagesWidgetColumn(messagedUser), ), if (isMessageBySender) ...[getReceipt()], - if (isMessageBySender && - (featureActiveConfig?.enableCurrentUserProfileAvatar ?? true)) + if (isMessageBySender && (featureActiveConfig?.enableCurrentUserProfileAvatar ?? true)) profileCircle(messagedUser), ], ), @@ -152,8 +148,7 @@ class _ChatBubbleWidgetState extends State { imageUrl: messagedUser?.profilePhoto, imageType: messagedUser?.imageType, defaultAvatarImage: messagedUser?.defaultAvatarImage ?? profileImage, - networkImageProgressIndicatorBuilder: - messagedUser?.networkImageProgressIndicatorBuilder, + networkImageProgressIndicatorBuilder: messagedUser?.networkImageProgressIndicatorBuilder, assetImageErrorBuilder: messagedUser?.assetImageErrorBuilder, networkImageErrorBuilder: messagedUser?.networkImageErrorBuilder, circleRadius: profileCircleConfig?.circleRadius, @@ -164,49 +159,39 @@ class _ChatBubbleWidgetState extends State { void onRightSwipe() { if (maxDuration != null) { - widget.message.voiceMessageDuration = - Duration(milliseconds: maxDuration!); + widget.message.voiceMessageDuration = Duration(milliseconds: maxDuration!); } if (chatListConfig.swipeToReplyConfig?.onRightSwipe != null) { - chatListConfig.swipeToReplyConfig?.onRightSwipe!( - widget.message.message, widget.message.sentBy); + chatListConfig.swipeToReplyConfig?.onRightSwipe!(widget.message.message, widget.message.sentBy); } widget.onSwipe(widget.message); } void onLeftSwipe() { if (maxDuration != null) { - widget.message.voiceMessageDuration = - Duration(milliseconds: maxDuration!); + widget.message.voiceMessageDuration = Duration(milliseconds: maxDuration!); } if (chatListConfig.swipeToReplyConfig?.onLeftSwipe != null) { - chatListConfig.swipeToReplyConfig?.onLeftSwipe!( - widget.message.message, widget.message.sentBy); + chatListConfig.swipeToReplyConfig?.onLeftSwipe!(widget.message.message, widget.message.sentBy); } widget.onSwipe(widget.message); } void _onAvatarTap(ChatUser? user) { - if (chatListConfig.profileCircleConfig?.onAvatarTap != null && - user != null) { + if (chatListConfig.profileCircleConfig?.onAvatarTap != null && user != null) { chatListConfig.profileCircleConfig?.onAvatarTap!(user); } } Widget getReceipt() { - final showReceipts = chatListConfig.chatBubbleConfig - ?.outgoingChatBubbleConfig?.receiptsWidgetConfig?.showReceiptsIn ?? + final showReceipts = chatListConfig.chatBubbleConfig?.outgoingChatBubble?.receiptsWidgetConfig?.showReceiptsIn ?? ShowReceiptsIn.lastMessage; if (showReceipts == ShowReceiptsIn.all) { return ValueListenableBuilder( valueListenable: widget.message.statusNotifier, builder: (context, value, child) { - if (ChatViewInheritedWidget.of(context) - ?.featureActiveConfig - .receiptsBuilderVisibility ?? - true) { - return chatListConfig.chatBubbleConfig?.outgoingChatBubbleConfig - ?.receiptsWidgetConfig?.receiptsBuilder + if (ChatViewInheritedWidget.of(context)?.featureActiveConfig.receiptsBuilderVisibility ?? true) { + return chatListConfig.chatBubbleConfig?.outgoingChatBubble?.receiptsWidgetConfig?.receiptsBuilder ?.call(value) ?? sendMessageAnimationBuilder(value); } @@ -215,15 +200,10 @@ class _ChatBubbleWidgetState extends State { ); } else if (showReceipts == ShowReceiptsIn.lastMessage && isLastMessage) { return ValueListenableBuilder( - valueListenable: - chatController!.initialMessageList.last.statusNotifier, + valueListenable: chatController!.initialMessageList.last.statusNotifier, builder: (context, value, child) { - if (ChatViewInheritedWidget.of(context) - ?.featureActiveConfig - .receiptsBuilderVisibility ?? - true) { - return chatListConfig.chatBubbleConfig?.outgoingChatBubbleConfig - ?.receiptsWidgetConfig?.receiptsBuilder + if (ChatViewInheritedWidget.of(context)?.featureActiveConfig.receiptsBuilderVisibility ?? true) { + return chatListConfig.chatBubbleConfig?.outgoingChatBubble?.receiptsWidgetConfig?.receiptsBuilder ?.call(value) ?? sendMessageAnimationBuilder(value); } @@ -234,59 +214,48 @@ class _ChatBubbleWidgetState extends State { } void _onAvatarLongPress(ChatUser? user) { - if (chatListConfig.profileCircleConfig?.onAvatarLongPress != null && - user != null) { + if (chatListConfig.profileCircleConfig?.onAvatarLongPress != null && user != null) { chatListConfig.profileCircleConfig?.onAvatarLongPress!(user); } } Widget _messagesWidgetColumn(ChatUser? messagedUser) { return Column( - crossAxisAlignment: - isMessageBySender ? CrossAxisAlignment.end : CrossAxisAlignment.start, + crossAxisAlignment: isMessageBySender ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [ if ((chatController?.otherUsers.isNotEmpty ?? false) && !isMessageBySender && (featureActiveConfig?.enableOtherUserName ?? true)) Padding( - padding: chatListConfig - .chatBubbleConfig?.inComingChatBubbleConfig?.padding ?? + padding: chatListConfig.chatBubbleConfig?.incomingChatBubble?.padding ?? const EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Text( messagedUser?.name ?? '', - style: chatListConfig.chatBubbleConfig?.inComingChatBubbleConfig - ?.senderNameTextStyle, + style: chatListConfig.chatBubbleConfig?.incomingChatBubble?.senderNameTextStyle, ), ), if (replyMessage.isNotEmpty) - chatListConfig.repliedMessageConfig?.repliedMessageWidgetBuilder != - null - ? chatListConfig.repliedMessageConfig! - .repliedMessageWidgetBuilder!(widget.message.replyMessage) + chatListConfig.repliedMessageConfig?.repliedMessageWidgetBuilder != null + ? chatListConfig.repliedMessageConfig!.repliedMessageWidgetBuilder!(widget.message.replyMessage) : ReplyMessageWidget( message: widget.message, repliedMessageConfig: chatListConfig.repliedMessageConfig, - onTap: () => widget.onReplyTap - ?.call(widget.message.replyMessage.messageId), + onTap: () => widget.onReplyTap?.call(widget.message.replyMessage.messageId), ), SwipeToReply( isMessageByCurrentUser: isMessageBySender, onSwipe: isMessageBySender ? onLeftSwipe : onRightSwipe, child: MessageView( - outgoingChatBubbleConfig: - chatListConfig.chatBubbleConfig?.outgoingChatBubbleConfig, - isLongPressEnable: - (featureActiveConfig?.enableReactionPopup ?? true) || - (featureActiveConfig?.enableReplySnackBar ?? true), - inComingChatBubbleConfig: - chatListConfig.chatBubbleConfig?.inComingChatBubbleConfig, + outgoingChatBubble: chatListConfig.chatBubbleConfig?.outgoingChatBubble, + isLongPressEnable: (featureActiveConfig?.enableReactionPopup ?? true) || + (featureActiveConfig?.enableReplySnackBar ?? true), + incomingChatBubble: chatListConfig.chatBubbleConfig?.incomingChatBubble, message: widget.message, isMessageBySender: isMessageBySender, messageConfig: chatListConfig.messageConfig, onLongPress: widget.onLongPress, chatBubbleMaxWidth: chatListConfig.chatBubbleConfig?.maxWidth, - longPressAnimationDuration: - chatListConfig.chatBubbleConfig?.longPressAnimationDuration, + longPressAnimationDuration: chatListConfig.chatBubbleConfig?.longPressAnimationDuration, onDoubleTap: featureActiveConfig?.enableDoubleTapToLike ?? false ? chatListConfig.chatBubbleConfig?.onDoubleTap ?? (message) => currentUser != null @@ -299,12 +268,9 @@ class _ChatBubbleWidgetState extends State { : null, shouldHighlight: widget.shouldHighlight, controller: chatController, - highlightColor: chatListConfig.repliedMessageConfig - ?.repliedMsgAutoScrollConfig.highlightColor ?? - Colors.grey, - highlightScale: chatListConfig.repliedMessageConfig - ?.repliedMsgAutoScrollConfig.highlightScale ?? - 1.1, + highlightColor: + chatListConfig.repliedMessageConfig?.repliedMsgAutoScrollConfig.highlightColor ?? Colors.grey, + highlightScale: chatListConfig.repliedMessageConfig?.repliedMsgAutoScrollConfig.highlightScale ?? 1.1, onMaxDuration: _onMaxDuration, ), ), diff --git a/lib/src/widgets/chat_groupedlist_widget.dart b/lib/src/widgets/chat_groupedlist_widget.dart index 9ba60f78..ebc74d04 100644 --- a/lib/src/widgets/chat_groupedlist_widget.dart +++ b/lib/src/widgets/chat_groupedlist_widget.dart @@ -66,8 +66,7 @@ class ChatGroupedListWidget extends StatefulWidget { State createState() => _ChatGroupedListWidgetState(); } -class _ChatGroupedListWidgetState extends State - with TickerProviderStateMixin { +class _ChatGroupedListWidgetState extends State with TickerProviderStateMixin { bool get showPopUp => widget.showPopUp; bool highlightMessage = false; @@ -82,8 +81,7 @@ class _ChatGroupedListWidgetState extends State bool get isEnableSwipeToSeeTime => widget.isEnableSwipeToSeeTime; - ChatBackgroundConfiguration get chatBackgroundConfig => - chatListConfig.chatBackgroundConfig; + ChatBackgroundConfiguration get chatBackgroundConfig => chatListConfig.chatBackgroundConfig; double chatTextFieldHeight = 0; @@ -104,8 +102,7 @@ class _ChatGroupedListWidgetState extends State WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; setState(() { - chatTextFieldHeight = - chatViewIW?.chatTextFieldViewKey.currentContext?.size?.height ?? 10; + chatTextFieldHeight = chatViewIW?.chatTextFieldViewKey.currentContext?.size?.height ?? 10; }); }); } @@ -142,8 +139,7 @@ class _ChatGroupedListWidgetState extends State @override Widget build(BuildContext context) { - final suggestionsListConfig = - suggestionsConfig?.listConfig ?? const SuggestionListConfig(); + final suggestionsListConfig = suggestionsConfig?.listConfig ?? const SuggestionListConfig(); return SingleChildScrollView( reverse: true, // When reaction popup is being appeared at that user should not scroll. @@ -154,13 +150,9 @@ class _ChatGroupedListWidgetState extends State children: [ GestureDetector( onHorizontalDragUpdate: (details) => - isEnableSwipeToSeeTime && !showPopUp - ? _onHorizontalDrag(details) - : null, + isEnableSwipeToSeeTime && !showPopUp ? _onHorizontalDrag(details) : null, onHorizontalDragEnd: (details) => - isEnableSwipeToSeeTime && !showPopUp - ? _animationController?.reverse() - : null, + isEnableSwipeToSeeTime && !showPopUp ? _animationController?.reverse() : null, onTap: widget.onChatListTap, child: _animationController != null ? AnimatedBuilder( @@ -175,9 +167,8 @@ class _ChatGroupedListWidgetState extends State ValueListenableBuilder( valueListenable: chatController!.typingIndicatorNotifier, builder: (context, value, child) => TypingIndicator( - typeIndicatorConfig: chatListConfig.typeIndicatorConfig, - chatBubbleConfig: - chatListConfig.chatBubbleConfig?.inComingChatBubbleConfig, + typingIndicatorConfig: chatListConfig.typingIndicatorConfig, + chatBubbleConfig: chatListConfig.chatBubbleConfig?.incomingChatBubble, showIndicator: value, ), ), @@ -202,18 +193,15 @@ class _ChatGroupedListWidgetState extends State Future _onReplyTap(String id, List? messages) async { // Finds the replied message if exists final repliedMessages = messages?.firstWhere((message) => id == message.id); - final repliedMsgAutoScrollConfig = - chatListConfig.repliedMessageConfig?.repliedMsgAutoScrollConfig; - final highlightDuration = repliedMsgAutoScrollConfig?.highlightDuration ?? - const Duration(milliseconds: 300); + final repliedMsgAutoScrollConfig = chatListConfig.repliedMessageConfig?.repliedMsgAutoScrollConfig; + final highlightDuration = repliedMsgAutoScrollConfig?.highlightDuration ?? const Duration(milliseconds: 300); // Scrolls to replied message and highlights if (repliedMessages != null && repliedMessages.key.currentState != null) { await Scrollable.ensureVisible( repliedMessages.key.currentState!.context, // This value will make widget to be in center when auto scrolled. alignment: 0.5, - curve: - repliedMsgAutoScrollConfig?.highlightScrollCurve ?? Curves.easeIn, + curve: repliedMsgAutoScrollConfig?.highlightScrollCurve ?? Curves.easeIn, duration: highlightDuration, ); if (repliedMsgAutoScrollConfig?.enableHighlightRepliedMsg ?? false) { @@ -238,9 +226,7 @@ class _ChatGroupedListWidgetState extends State ), ); - details.delta.dx > 1 - ? _animationController?.reverse() - : _animationController?.forward(); + details.delta.dx > 1 ? _animationController?.reverse() : _animationController?.forward(); } @override @@ -257,16 +243,12 @@ class _ChatGroupedListWidgetState extends State builder: (context, snapshot) { if (!snapshot.connectionState.isActive) { return Center( - child: chatBackgroundConfig.loadingWidget ?? - const CircularProgressIndicator(), + child: chatBackgroundConfig.loadingWidget ?? const CircularProgressIndicator(), ); } else { - final messages = chatBackgroundConfig.sortEnable - ? sortMessage(snapshot.data!) - : snapshot.data!; + final messages = chatBackgroundConfig.sortEnable ? sortMessage(snapshot.data!) : snapshot.data!; - final enableSeparator = - featureActiveConfig?.enableChatSeparator ?? false; + final enableSeparator = featureActiveConfig?.enableChatSeparator ?? false; Map messageSeparator = {}; @@ -287,9 +269,7 @@ class _ChatGroupedListWidgetState extends State physics: const NeverScrollableScrollPhysics(), padding: EdgeInsets.zero, shrinkWrap: true, - itemCount: (enableSeparator - ? messages.length + messageSeparator.length - : messages.length), + itemCount: (enableSeparator ? messages.length + messageSeparator.length : messages.length), itemBuilder: (context, index) { /// By removing [count] from [index] will get actual index /// to display message in chat @@ -309,26 +289,20 @@ class _ChatGroupedListWidgetState extends State valueListenable: _replyId, builder: (context, state, child) { final message = messages[newIndex]; - final enableScrollToRepliedMsg = chatListConfig - .repliedMessageConfig - ?.repliedMsgAutoScrollConfig - .enableScrollToRepliedMsg ?? - false; + final enableScrollToRepliedMsg = + chatListConfig.repliedMessageConfig?.repliedMsgAutoScrollConfig.enableScrollToRepliedMsg ?? false; return ChatBubbleWidget( key: message.key, message: message, slideAnimation: _slideAnimation, - onLongPress: (yCoordinate, xCoordinate) => - widget.onChatBubbleLongPress( + onLongPress: (yCoordinate, xCoordinate) => widget.onChatBubbleLongPress( yCoordinate, xCoordinate, message, ), onSwipe: widget.assignReplyMessage, shouldHighlight: state == message.id, - onReplyTap: enableScrollToRepliedMsg - ? (replyId) => _onReplyTap(replyId, snapshot.data) - : null, + onReplyTap: enableScrollToRepliedMsg ? (replyId) => _onReplyTap(replyId, snapshot.data) : null, ); }, ); @@ -342,8 +316,7 @@ class _ChatGroupedListWidgetState extends State List sortMessage(List messages) { final elements = [...messages]; elements.sort( - chatBackgroundConfig.messageSorter ?? - (a, b) => a.createdAt.compareTo(b.createdAt), + chatBackgroundConfig.messageSorter ?? (a, b) => a.createdAt.compareTo(b.createdAt), ); if (chatBackgroundConfig.groupedListOrder.isAsc) { return elements.toList(); @@ -362,8 +335,7 @@ class _ChatGroupedListWidgetState extends State /// When the conversation starts on a new date, /// we are returning new date [message.createdAt]. - return lastMatchedDate.getDateFromDateTime == - message.createdAt.getDateFromDateTime + return lastMatchedDate.getDateFromDateTime == message.createdAt.getDateFromDateTime ? lastMatchedDate : message.createdAt; } @@ -372,8 +344,7 @@ class _ChatGroupedListWidgetState extends State return featureActiveConfig?.enableChatSeparator ?? false ? _GroupSeparatorBuilder( separator: createdAt, - defaultGroupSeparatorConfig: - chatBackgroundConfig.defaultGroupSeparatorConfig, + defaultGroupSeparatorConfig: chatBackgroundConfig.defaultGroupSeparatorConfig, groupSeparatorBuilder: chatBackgroundConfig.groupSeparatorBuilder, ) : const SizedBox.shrink(); diff --git a/lib/src/widgets/chat_view.dart b/lib/src/widgets/chat_view.dart index 9c871018..1f2a642d 100644 --- a/lib/src/widgets/chat_view.dart +++ b/lib/src/widgets/chat_view.dart @@ -52,7 +52,7 @@ class ChatView extends StatefulWidget { this.isLastPage, this.appBar, ChatBackgroundConfiguration? chatBackgroundConfig, - this.typeIndicatorConfig, + this.typingIndicatorConfig, this.sendMessageBuilder, this.sendMessageConfig, this.onChatListTap, @@ -113,7 +113,7 @@ class ChatView extends StatefulWidget { final ReplyMessageWithReturnWidget? sendMessageBuilder; /// Allow user to giving customisation typing indicator. - final TypeIndicatorConfiguration? typeIndicatorConfig; + final TypingIndicatorConfiguration? typingIndicatorConfig; /// Provides controller for accessing few function for running chat. final ChatController chatController; @@ -195,7 +195,7 @@ class _ChatViewState extends State with SingleTickerProviderStateMixin return ConfigurationsInheritedWidget( chatBackgroundConfig: widget.chatBackgroundConfig, reactionPopupConfig: widget.reactionPopupConfig, - typeIndicatorConfig: widget.typeIndicatorConfig, + typingIndicatorConfig: widget.typingIndicatorConfig, chatBubbleConfig: widget.chatBubbleConfig, replyPopupConfig: widget.replyPopupConfig, messageConfig: widget.messageConfig, diff --git a/lib/src/widgets/message_view.dart b/lib/src/widgets/message_view.dart index 2d1215f5..70abeabc 100644 --- a/lib/src/widgets/message_view.dart +++ b/lib/src/widgets/message_view.dart @@ -38,8 +38,8 @@ class MessageView extends StatefulWidget { required this.onLongPress, required this.isLongPressEnable, this.chatBubbleMaxWidth, - this.inComingChatBubbleConfig, - this.outgoingChatBubbleConfig, + this.incomingChatBubble, + this.outgoingChatBubble, this.longPressAnimationDuration, this.onDoubleTap, this.highlightColor = Colors.grey, @@ -63,10 +63,10 @@ class MessageView extends StatefulWidget { final double? chatBubbleMaxWidth; /// Provides configuration of chat bubble appearance from other user of chat. - final ChatBubble? inComingChatBubbleConfig; + final ChatBubble? incomingChatBubble; /// Provides configuration of chat bubble appearance from current user of chat. - final ChatBubble? outgoingChatBubbleConfig; + final ChatBubble? outgoingChatBubble; /// Allow users to give duration of animation when user long press on chat bubble. final Duration? longPressAnimationDuration; @@ -98,8 +98,7 @@ class MessageView extends StatefulWidget { State createState() => _MessageViewState(); } -class _MessageViewState extends State - with SingleTickerProviderStateMixin { +class _MessageViewState extends State with SingleTickerProviderStateMixin { AnimationController? _animationController; MessageConfiguration? get messageConfig => widget.messageConfig; @@ -112,14 +111,12 @@ class _MessageViewState extends State if (isLongPressEnable) { _animationController = AnimationController( vsync: this, - duration: widget.longPressAnimationDuration ?? - const Duration(milliseconds: 250), + duration: widget.longPressAnimationDuration ?? const Duration(milliseconds: 250), upperBound: 0.1, lowerBound: 0.0, ); - if (widget.message.status != MessageStatus.read && - !widget.isMessageBySender) { - widget.inComingChatBubbleConfig?.onMessageRead?.call(widget.message); + if (widget.message.status != MessageStatus.read && !widget.isMessageBySender) { + widget.incomingChatBubble?.onMessageRead?.call(widget.message); } _animationController?.addStatusListener((status) { if (status == AnimationStatus.completed) { @@ -175,26 +172,20 @@ class _MessageViewState extends State leftPadding2, 4, leftPadding2, - widget.message.reaction.reactions.isNotEmpty - ? 14 - : 0, + widget.message.reaction.reactions.isNotEmpty ? 14 : 0, ), child: Transform.scale( - scale: widget.shouldHighlight - ? widget.highlightScale - : 1.0, + scale: widget.shouldHighlight ? widget.highlightScale : 1.0, child: Text( message, - style: emojiMessageConfiguration?.textStyle ?? - const TextStyle(fontSize: 30), + style: emojiMessageConfiguration?.textStyle ?? const TextStyle(fontSize: 30), ), ), ), if (widget.message.reaction.reactions.isNotEmpty) ReactionWidget( reaction: widget.message.reaction, - messageReactionConfig: - messageConfig?.messageReactionConfig, + messageReactionConfig: messageConfig?.messageReactionConfig, isMessageBySender: widget.isMessageBySender, ), ], @@ -210,8 +201,8 @@ class _MessageViewState extends State ); } else if (widget.message.messageType.isText) { return TextMessageView( - inComingChatBubbleConfig: widget.inComingChatBubbleConfig, - outgoingChatBubbleConfig: widget.outgoingChatBubbleConfig, + incomingChatBubble: widget.incomingChatBubble, + outgoingChatBubble: widget.outgoingChatBubble, isMessageBySender: widget.isMessageBySender, message: widget.message, chatBubbleMaxWidth: widget.chatBubbleMaxWidth, @@ -227,11 +218,10 @@ class _MessageViewState extends State onMaxDuration: widget.onMaxDuration, isMessageBySender: widget.isMessageBySender, messageReactionConfig: messageConfig?.messageReactionConfig, - inComingChatBubbleConfig: widget.inComingChatBubbleConfig, - outgoingChatBubbleConfig: widget.outgoingChatBubbleConfig, + incomingChatBubble: widget.incomingChatBubble, + outgoingChatBubble: widget.outgoingChatBubble, ); - } else if (widget.message.messageType.isCustom && - messageConfig?.customMessageBuilder != null) { + } else if (widget.message.messageType.isCustom && messageConfig?.customMessageBuilder != null) { return messageConfig?.customMessageBuilder!(widget.message); } }()) ?? @@ -240,21 +230,12 @@ class _MessageViewState extends State valueListenable: widget.message.statusNotifier, builder: (context, value, child) { if (widget.isMessageBySender && - widget.controller?.initialMessageList.last.id == - widget.message.id && + widget.controller?.initialMessageList.last.id == widget.message.id && widget.message.status == MessageStatus.read) { - if (ChatViewInheritedWidget.of(context) - ?.featureActiveConfig - .lastSeenAgoBuilderVisibility ?? - true) { - return widget.outgoingChatBubbleConfig?.receiptsWidgetConfig - ?.lastSeenAgoBuilder - ?.call( - widget.message, - applicationDateFormatter( - widget.message.createdAt)) ?? - lastSeenAgoBuilder(widget.message, - applicationDateFormatter(widget.message.createdAt)); + if (ChatViewInheritedWidget.of(context)?.featureActiveConfig.lastSeenAgoBuilderVisibility ?? true) { + return widget.outgoingChatBubble?.receiptsWidgetConfig?.lastSeenAgoBuilder + ?.call(widget.message, applicationDateFormatter(widget.message.createdAt)) ?? + lastSeenAgoBuilder(widget.message, applicationDateFormatter(widget.message.createdAt)); } return const SizedBox(); } diff --git a/lib/src/widgets/text_message_view.dart b/lib/src/widgets/text_message_view.dart index 4dacc90b..69c17f17 100644 --- a/lib/src/widgets/text_message_view.dart +++ b/lib/src/widgets/text_message_view.dart @@ -34,8 +34,8 @@ class TextMessageView extends StatelessWidget { required this.isMessageBySender, required this.message, this.chatBubbleMaxWidth, - this.inComingChatBubbleConfig, - this.outgoingChatBubbleConfig, + this.incomingChatBubble, + this.outgoingChatBubble, this.messageReactionConfig, this.highlightMessage = false, this.highlightColor, @@ -51,10 +51,10 @@ class TextMessageView extends StatelessWidget { final double? chatBubbleMaxWidth; /// Provides configuration of chat bubble appearance from other user of chat. - final ChatBubble? inComingChatBubbleConfig; + final ChatBubble? incomingChatBubble; /// Provides configuration of chat bubble appearance from current user of chat. - final ChatBubble? outgoingChatBubbleConfig; + final ChatBubble? outgoingChatBubble; /// Provides configuration of reaction appearance in chat bubble. final MessageReactionConfiguration? messageReactionConfig; @@ -73,17 +73,13 @@ class TextMessageView extends StatelessWidget { clipBehavior: Clip.none, children: [ Container( - constraints: BoxConstraints( - maxWidth: chatBubbleMaxWidth ?? - MediaQuery.of(context).size.width * 0.75), + constraints: BoxConstraints(maxWidth: chatBubbleMaxWidth ?? MediaQuery.of(context).size.width * 0.75), padding: _padding ?? const EdgeInsets.symmetric( horizontal: 12, vertical: 10, ), - margin: _margin ?? - EdgeInsets.fromLTRB( - 5, 0, 6, message.reaction.reactions.isNotEmpty ? 15 : 2), + margin: _margin ?? EdgeInsets.fromLTRB(5, 0, 6, message.reaction.reactions.isNotEmpty ? 15 : 2), decoration: BoxDecoration( color: highlightMessage ? highlightColor : _color, borderRadius: _borderRadius(textMessage), @@ -113,33 +109,22 @@ class TextMessageView extends StatelessWidget { ); } - EdgeInsetsGeometry? get _padding => isMessageBySender - ? outgoingChatBubbleConfig?.padding - : inComingChatBubbleConfig?.padding; + EdgeInsetsGeometry? get _padding => isMessageBySender ? outgoingChatBubble?.padding : incomingChatBubble?.padding; - EdgeInsetsGeometry? get _margin => isMessageBySender - ? outgoingChatBubbleConfig?.margin - : inComingChatBubbleConfig?.margin; + EdgeInsetsGeometry? get _margin => isMessageBySender ? outgoingChatBubble?.margin : incomingChatBubble?.margin; - LinkPreviewConfiguration? get _linkPreviewConfig => isMessageBySender - ? outgoingChatBubbleConfig?.linkPreviewConfig - : inComingChatBubbleConfig?.linkPreviewConfig; + LinkPreviewConfiguration? get _linkPreviewConfig => + isMessageBySender ? outgoingChatBubble?.linkPreviewConfig : incomingChatBubble?.linkPreviewConfig; - TextStyle? get _textStyle => isMessageBySender - ? outgoingChatBubbleConfig?.textStyle - : inComingChatBubbleConfig?.textStyle; + TextStyle? get _textStyle => isMessageBySender ? outgoingChatBubble?.textStyle : incomingChatBubble?.textStyle; BorderRadiusGeometry _borderRadius(String message) => isMessageBySender - ? outgoingChatBubbleConfig?.borderRadius ?? - (message.length < 37 - ? BorderRadius.circular(replyBorderRadius1) - : BorderRadius.circular(replyBorderRadius2)) - : inComingChatBubbleConfig?.borderRadius ?? - (message.length < 29 - ? BorderRadius.circular(replyBorderRadius1) - : BorderRadius.circular(replyBorderRadius2)); + ? outgoingChatBubble?.borderRadius ?? + (message.length < 37 ? BorderRadius.circular(replyBorderRadius1) : BorderRadius.circular(replyBorderRadius2)) + : incomingChatBubble?.borderRadius ?? + (message.length < 29 ? BorderRadius.circular(replyBorderRadius1) : BorderRadius.circular(replyBorderRadius2)); Color get _color => isMessageBySender - ? outgoingChatBubbleConfig?.color ?? Colors.purple - : inComingChatBubbleConfig?.color ?? Colors.grey.shade500; + ? outgoingChatBubble?.color ?? Colors.purple + : incomingChatBubble?.color ?? Colors.grey.shade500; } diff --git a/lib/src/widgets/type_indicator_widget.dart b/lib/src/widgets/type_indicator_widget.dart index 8a97b5ee..7edb366a 100644 --- a/lib/src/widgets/type_indicator_widget.dart +++ b/lib/src/widgets/type_indicator_widget.dart @@ -33,7 +33,7 @@ class TypingIndicator extends StatefulWidget { Key? key, this.showIndicator = false, this.chatBubbleConfig, - this.typeIndicatorConfig, + this.typingIndicatorConfig, }) : super(key: key); /// Allow user to turn on/off typing indicator. @@ -44,14 +44,13 @@ class TypingIndicator extends StatefulWidget { final ChatBubble? chatBubbleConfig; /// Provides configurations related to typing indicator appearance. - final TypeIndicatorConfiguration? typeIndicatorConfig; + final TypingIndicatorConfiguration? typingIndicatorConfig; @override State createState() => _TypingIndicatorState(); } -class _TypingIndicatorState extends State - with TickerProviderStateMixin { +class _TypingIndicatorState extends State with TickerProviderStateMixin { late AnimationController _appearanceController; late Animation _indicatorSpaceAnimation; @@ -72,18 +71,15 @@ class _TypingIndicatorState extends State ChatBubble? get chatBubbleConfig => widget.chatBubbleConfig; - double get indicatorSize => widget.typeIndicatorConfig?.indicatorSize ?? 10; + double get indicatorSize => widget.typingIndicatorConfig?.indicatorSize ?? 10; - double get indicatorSpacing => - widget.typeIndicatorConfig?.indicatorSpacing ?? 4; + double get indicatorSpacing => widget.typingIndicatorConfig?.indicatorSpacing ?? 4; Color? get flashingCircleDarkColor => - widget.typeIndicatorConfig?.flashingCircleDarkColor ?? - const Color(0xFF939497); + widget.typingIndicatorConfig?.flashingCircleDarkColor ?? const Color(0xFF939497); Color? get flashingCircleBrightColor => - widget.typeIndicatorConfig?.flashingCircleBrightColor ?? - const Color(0xFFadacb0); + widget.typingIndicatorConfig?.flashingCircleBrightColor ?? const Color(0xFFadacb0); @override void initState() { @@ -245,15 +241,10 @@ class _TypingIndicatorState extends State bottomPadding: 0, imageUrl: profileCircleConfiguration?.profileImageUrl, imageType: profileCircleConfiguration?.imageType, - assetImageErrorBuilder: - profileCircleConfiguration?.assetImageErrorBuilder, - networkImageErrorBuilder: - profileCircleConfiguration?.networkImageErrorBuilder, - defaultAvatarImage: - profileCircleConfiguration?.defaultAvatarImage ?? - profileImage, - networkImageProgressIndicatorBuilder: profileCircleConfiguration - ?.networkImageProgressIndicatorBuilder, + assetImageErrorBuilder: profileCircleConfiguration?.assetImageErrorBuilder, + networkImageErrorBuilder: profileCircleConfiguration?.networkImageErrorBuilder, + defaultAvatarImage: profileCircleConfiguration?.defaultAvatarImage ?? profileImage, + networkImageProgressIndicatorBuilder: profileCircleConfiguration?.networkImageProgressIndicatorBuilder, ), bubble, ], @@ -264,13 +255,10 @@ class _TypingIndicatorState extends State Widget _buildStatusBubble() { return Container( - padding: chatBubbleConfig?.padding ?? - const EdgeInsets.fromLTRB( - leftPadding3, 0, leftPadding3, leftPadding3), + padding: chatBubbleConfig?.padding ?? const EdgeInsets.fromLTRB(leftPadding3, 0, leftPadding3, leftPadding3), margin: chatBubbleConfig?.margin ?? const EdgeInsets.fromLTRB(5, 0, 6, 2), decoration: BoxDecoration( - borderRadius: chatBubbleConfig?.borderRadius ?? - BorderRadius.circular(replyBorderRadius2), + borderRadius: chatBubbleConfig?.borderRadius ?? BorderRadius.circular(replyBorderRadius2), color: chatBubbleConfig?.color ?? Colors.grey.shade500, ), child: Padding( @@ -290,8 +278,7 @@ class _TypingIndicatorState extends State return AnimatedBuilder( animation: _jumpAnimations[value], builder: (context, child) { - final circleFlashPercent = - _dotIntervals[index].transform(_repeatingController.value); + final circleFlashPercent = _dotIntervals[index].transform(_repeatingController.value); final circleColorPercent = sin(pi * circleFlashPercent); return Transform.translate( offset: Offset(0, _jumpAnimations[value].value), @@ -301,8 +288,7 @@ class _TypingIndicatorState extends State margin: EdgeInsets.symmetric(horizontal: indicatorSpacing), decoration: BoxDecoration( shape: BoxShape.circle, - color: Color.lerp(flashingCircleDarkColor, - flashingCircleBrightColor, circleColorPercent), + color: Color.lerp(flashingCircleDarkColor, flashingCircleBrightColor, circleColorPercent), ), ), ); diff --git a/lib/src/widgets/voice_message_view.dart b/lib/src/widgets/voice_message_view.dart index 40466e3c..1076cc32 100644 --- a/lib/src/widgets/voice_message_view.dart +++ b/lib/src/widgets/voice_message_view.dart @@ -12,8 +12,8 @@ class VoiceMessageView extends StatefulWidget { required this.screenWidth, required this.message, required this.isMessageBySender, - this.inComingChatBubbleConfig, - this.outgoingChatBubbleConfig, + this.incomingChatBubble, + this.outgoingChatBubble, this.onMaxDuration, this.messageReactionConfig, this.config, @@ -36,10 +36,10 @@ class VoiceMessageView extends StatefulWidget { final MessageReactionConfiguration? messageReactionConfig; /// Provides configuration of chat bubble appearance from other user of chat. - final ChatBubble? inComingChatBubbleConfig; + final ChatBubble? incomingChatBubble; /// Provides configuration of chat bubble appearance from current user of chat. - final ChatBubble? outgoingChatBubbleConfig; + final ChatBubble? outgoingChatBubble; @override State createState() => _VoiceMessageViewState(); @@ -49,8 +49,7 @@ class _VoiceMessageViewState extends State { late PlayerController controller; late StreamSubscription playerStateSubscription; - final ValueNotifier _playerState = - ValueNotifier(PlayerState.stopped); + final ValueNotifier _playerState = ValueNotifier(PlayerState.stopped); PlayerState get playerState => _playerState.value; @@ -62,12 +61,10 @@ class _VoiceMessageViewState extends State { controller = PlayerController() ..preparePlayer( path: widget.message.message, - noOfSamples: widget.config?.playerWaveStyle - ?.getSamplesForWidth(widget.screenWidth * 0.5) ?? + noOfSamples: widget.config?.playerWaveStyle?.getSamplesForWidth(widget.screenWidth * 0.5) ?? playerWaveStyle.getSamplesForWidth(widget.screenWidth * 0.5), ).whenComplete(() => widget.onMaxDuration?.call(controller.maxDuration)); - playerStateSubscription = controller.onPlayerStateChanged - .listen((state) => _playerState.value = state); + playerStateSubscription = controller.onPlayerStateChanged.listen((state) => _playerState.value = state); } @override @@ -87,12 +84,9 @@ class _VoiceMessageViewState extends State { decoration: widget.config?.decoration ?? BoxDecoration( borderRadius: BorderRadius.circular(12), - color: widget.isMessageBySender - ? widget.outgoingChatBubbleConfig?.color - : widget.inComingChatBubbleConfig?.color, + color: widget.isMessageBySender ? widget.outgoingChatBubble?.color : widget.incomingChatBubble?.color, ), - padding: widget.config?.padding ?? - const EdgeInsets.symmetric(horizontal: 8), + padding: widget.config?.padding ?? const EdgeInsets.symmetric(horizontal: 8), margin: widget.config?.margin ?? EdgeInsets.symmetric( horizontal: 8, @@ -105,18 +99,17 @@ class _VoiceMessageViewState extends State { builder: (context, state, child) { return IconButton( onPressed: _playOrPause, - icon: - state.isStopped || state.isPaused || state.isInitialised - ? widget.config?.playIcon ?? - const Icon( - Icons.play_arrow, - color: Colors.white, - ) - : widget.config?.pauseIcon ?? - const Icon( - Icons.stop, - color: Colors.white, - ), + icon: state.isStopped || state.isPaused || state.isInitialised + ? widget.config?.playIcon ?? + const Icon( + Icons.play_arrow, + color: Colors.white, + ) + : widget.config?.pauseIcon ?? + const Icon( + Icons.stop, + color: Colors.white, + ), ); }, valueListenable: _playerState, @@ -125,14 +118,11 @@ class _VoiceMessageViewState extends State { size: Size(widget.screenWidth * 0.50, 60), playerController: controller, waveformType: WaveformType.fitWidth, - playerWaveStyle: - widget.config?.playerWaveStyle ?? playerWaveStyle, - padding: widget.config?.waveformPadding ?? - const EdgeInsets.only(right: 10), + playerWaveStyle: widget.config?.playerWaveStyle ?? playerWaveStyle, + padding: widget.config?.waveformPadding ?? const EdgeInsets.only(right: 10), margin: widget.config?.waveformMargin, animationCurve: widget.config?.animationCurve ?? Curves.easeIn, - animationDuration: widget.config?.animationDuration ?? - const Duration(milliseconds: 500), + animationDuration: widget.config?.animationDuration ?? const Duration(milliseconds: 500), enableSeekGesture: widget.config?.enableSeekGesture ?? true, ), ], @@ -150,13 +140,10 @@ class _VoiceMessageViewState extends State { void _playOrPause() { assert( - defaultTargetPlatform == TargetPlatform.iOS || - defaultTargetPlatform == TargetPlatform.android, + defaultTargetPlatform == TargetPlatform.iOS || defaultTargetPlatform == TargetPlatform.android, "Voice messages are only supported with android and ios platform", ); - if (playerState.isInitialised || - playerState.isPaused || - playerState.isStopped) { + if (playerState.isInitialised || playerState.isPaused || playerState.isStopped) { controller.startPlayer(finishMode: FinishMode.pause); } else { controller.pausePlayer();