diff --git a/README.md b/README.md index 06d78050..d090686a 100644 --- a/README.md +++ b/README.md @@ -1,1083 +1,61 @@ ![Banner](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/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 -chat, group chat, message reactions, reply messages, link preview and configurations for overall view. - -For web demo visit [Chat View Example](https://simformsolutionspvtltd.github.io/chatview/). - -## Preview - -![The example app running in iOS](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview/main/preview/chatview.gif) - -## Migration guide for release 2.0.0 - -- Renamed `sendBy` field to `sentBy` in `Message` class. - -- Renamed `chatUsers` field to `otherUsers` in `ChatController` class. - -- Moved `currentUser` field from `ChatView` widget to `ChatController` class - -- Updated `id` value in `copyWith` method of `Message` to have correct value. - -- Removed `showTypingIndicator` field from `ChatView` and replaced it with `ChatController.showTypingIndicator`. - - Before: - ```dart - ChatView( - showTypingIndicator:false, - ), - ``` - - After: - ```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 - { - ... - imageType: ImageType.asset, - ... - } - ``` - - After: - ```dart - { - ... - imageType: asset, - ... - } - ``` - - ##### in `Message.fromJson`: - - Before: - ```dart - Message.fromJson( - { - ... - 'createdAt': DateTime.now(), - 'message_type': MessageType.text, - 'voice_message_duration': Duration(seconds: 5), - ... - } - ) - ``` - After: - ```dart - Message.fromJson( - { - ... - 'createdAt': '2024-06-13T17:32:19.586412', - 'message_type': 'text', - 'voice_message_duration': '5000000', - ... - } - ) - ``` - - ##### in `Message.toJson`: - - Before: - ```dart - { - ... - createdAt: 2024-06-13 17:23:19.454789, - message_type: MessageType.text, - voice_message_duration: 0:00:05.000000, - ... - } - ``` - - After: - ```dart - { - ... - createdAt: 2024-06-13T17:32:19.586412, - message_type: text, - voice_message_duration: 5000000, - ... - } - ``` - - ##### in `ReplyMessage.fromJson`: +[![chatview](https://img.shields.io/pub/v/chatview?label=chatview)](https://pub.dev/packages/chatview) +[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/SimformSolutionsPvtLtd/chatview/blob/main/LICENSE) - Before: - ```dart - ReplyMessage.fromJson( - { - ... - 'message_type': MessageType.text, - 'voiceMessageDuration': Duration(seconds: 5), - ... - } - ) - ``` +ChatView is a Flutter package that allows you to integrate a highly customizable chat UI in your +Flutter applications with [Flexible Backend Integration][chatViewConnect]. - After: - ```dart - ReplyMessage.fromJson( - { - ... - 'message_type': 'text', - 'voiceMessageDuration': '5000000', - ... - } - ) - ``` +![Preview](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview/main/preview/chatview.gif) - in `ReplyMessage.toJson`: +## Features - Before: - ```dart - { - ... - message_type: MessageType.text, - voiceMessageDuration: 0:00:05.000000, - ... - } - ``` +- One-on-one and group chat support +- Message reactions with emoji +- Reply to messages functionality +- Link preview for URLs +- Voice messages support +- Image sharing capabilities +- Custom message types +- Typing indicators +- Reply suggestions +- Message status indicators (sent, delivered, read) +- Highly customizable UI components +- Plug-and-play backend support using [chatview_connect][chatViewConnect] - After: - ```dart - { - ... - message_type: text, - voiceMessageDuration: 5000000, - ... - } - ``` +## Documentation -## Installing +Visit our [documentation](https://simform-flutter-packages.web.app/chatView) site for all +implementation details, usage instructions, code examples, and advanced features. -1. Add dependency to `pubspec.yaml` +## Installation -```dart +```yaml dependencies: 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, - scrollController: ScrollController(), - currentUser: ChatUser(id: '1', name: 'Flutter'), - otherUsers: [ChatUser(id: '2', name: 'Simform')], -); -``` - -4. Adding a `ChatView` widget. -```dart -ChatView( - chatController: chatController, - onSendTap: onSendTap, - chatViewState: ChatViewState.hasMessages, // Add this state once data is available. -) -``` - -5. Adding a messageList with `Message` class. -```dart -List messageList = [ - Message( - id: '1', - message: "Hi", - createdAt: createdAt, - sentBy: userId, - ), - Message( - id: '2', - message: "Hello", - createdAt: createdAt, - sentBy: userId, - ), -]; -``` - -6. Adding a `onSendTap`. -```dart -void onSendTap(String message, ReplyMessage replyMessage, MessageType messageType){ - final message = Message( - id: '3', - message: "How are you", - createdAt: DateTime.now(), - sentBy: currentUser.id, - replyMessage: replyMessage, - messageType: messageType, - ); - chatController.addMessage(message); -} -``` - -Note: you can evaluate message type from `messageType` parameter, based on that you can perform operations. - -## Messages types compability - -|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`: - -``` - NSCameraUsageDescription - Used to demonstrate image picker plugin - NSMicrophoneUsageDescription - Used to capture audio for image picker plugin - NSPhotoLibraryUsageDescription - Used to demonstrate image picker plugin -``` - -### For voice messages -#### iOS -* 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` -``` - platform :ios, '10.0' -``` - -#### Android -* 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` -``` - -``` +## ChatView with Backend Support -## Some more optional parameters +Make `ChatView` backend-ready with [chatview_connect][chatViewConnect] -1. Enable and disable specific features with `FeatureActiveConfig`. -```dart -ChatView( - ... - featureActiveConfig: FeatureActiveConfig( - enableSwipeToReply: true, - enableSwipeToSeeTime: false, - ), - ... -) -``` +- 🔌 Easy backend integration without boilerplate (🔥 Firebase) +- ⚙️ Setup in 3 steps: set **Service Type** -> **User ID** and get **`ChatManager`** +- 💬 Supports **1-on-1** and **group chats** with **media uploads** *(audio not supported).* -2. Adding an appbar with `ChatViewAppBar`. -```dart -ChatView( - ... - appBar: ChatViewAppBar( - profilePicture: profileImage, - chatTitle: "Simform", - userStatus: "online", - actions: [ - Icon(Icons.more_vert), - ], - ), - ... -) -``` +## Support -3. Adding a message list configuration with `ChatBackgroundConfiguration` class. -```dart -ChatView( - ... - chatBackgroundConfig: ChatBackgroundConfiguration( - backgroundColor: Colors.white, - backgroundImage: backgroundImage, - ), - ... -) -``` - -4. Adding a send message configuration with `SendMessageConfiguration` class. -```dart -ChatView( - ... - sendMessageConfig: SendMessageConfiguration( - replyMessageColor: Colors.grey, - replyDialogColor:Colors.blue, - replyTitleColor: Colors.black, - closeIconColor: Colors.black, - ), - ... -) -``` - -5. Adding a chat bubble configuration with `ChatBubbleConfiguration` class. -```dart -ChatView( - ... - chatBubbleConfig: ChatBubbleConfiguration( - onDoubleTap: (){ - // Your code goes here - }, - outgoingChatBubbleConfig: ChatBubble( // Sender's message chat bubble - color: Colors.blue, - borderRadius: const BorderRadius.only( - topRight: Radius.circular(12), - topLeft: Radius.circular(12), - bottomLeft: Radius.circular(12), - ), - ), - inComingChatBubbleConfig: ChatBubble( // Receiver's message chat bubble - color: Colors.grey.shade200, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(12), - topRight: Radius.circular(12), - bottomRight: Radius.circular(12), - ), - ), - ) - ... -) -``` - -6. Adding swipe to reply configuration with `SwipeToReplyConfiguration` class. -```dart -ChatView( - ... - swipeToReplyConfig: SwipeToReplyConfiguration( - onLeftSwipe: (message, sentBy){ - // Your code goes here - }, - 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 - imageMessageConfig: ImageMessageConfiguration( - onTap: (){ - // Your code goes here - }, - shareIconConfig: ShareIconConfiguration( - onPressed: (){ - // Your code goes here - }, - ), - ), - ), - ... -) -``` - -8. Adding reaction pop-up configuration with `ReactionPopupConfiguration` class. -```dart -ChatView( - ... - reactionPopupConfig: ReactionPopupConfiguration( - backgroundColor: Colors.white, - userReactionCallback: (message, emoji){ - // Your code goes here - } - padding: EdgeInsets.all(12), - shadow: BoxShadow( - color: Colors.black54, - blurRadius: 20, - ), - ), - ... -) -``` - -9. Adding reply pop-up configuration with `ReplyPopupConfiguration` class. -```dart -ChatView( - ... - replyPopupConfig: ReplyPopupConfiguration( - backgroundColor: Colors.white, - onUnsendTap:(message){ // message is 'Message' class instance - // Your code goes here - }, - onReplyTap:(message){ // message is 'Message' class instance - // Your code goes here - }, - onReportTap:(){ - // Your code goes here - }, - onMoreTap:(){ - // Your code goes here - }, - ), - ... -) -``` - -10. Adding replied message configuration with `RepliedMessageConfiguration` class. -```dart -ChatView( - ... - repliedMessageConfig: RepliedMessageConfiguration( - backgroundColor: Colors.blue, - verticalBarColor: Colors.black, - repliedMsgAutoScrollConfig: RepliedMsgAutoScrollConfig(), - ), - ... -) -``` - -11. For customizing typing indicators use `typeIndicatorConfig` with `TypeIndicatorConfig`. -```dart -ChatView( - ... - - typeIndicatorConfig: TypeIndicatorConfiguration( - flashingCircleBrightColor: Colors.grey, - flashingCircleDarkColor: Colors.black, - ), - ... -) - -``` -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 -_chatContoller.setTypingIndicator = false; // for hiding indicator -``` - -13. Adding linkpreview configuration with `LinkPreviewConfiguration` class. -```dart -ChatView( - ... - chatBubbleConfig: ChatBubbleConfiguration( - linkPreviewConfig: LinkPreviewConfiguration( - linkStyle: const TextStyle( - color: Colors.white, - decoration: TextDecoration.underline, - ), - backgroundColor: Colors.grey, - bodyStyle: const TextStyle( - color: Colors.grey.shade200, - fontSize:16, - ), - titleStyle: const TextStyle( - color: Colors.black, - fontSize:20, - ), - ), - ) - ... -) -``` - -14. Adding pagination. -```dart -ChatView( - ... - isLastPage: false, - featureActiveConfig: FeatureActiveConfig( - enablePagination: true, - ), - loadMoreData: chatController.loadMoreData, - ... -) -``` - -15. Add image picker configuration. -```dart -ChatView( - ... - sendMessageConfig: SendMessageConfiguration( - enableCameraImagePicker: false, - enableGalleryImagePicker: true, - imagePickerIconsConfig: ImagePickerIconsConfiguration( - cameraIconColor: Colors.black, - galleryIconColor: Colors.black, - ) - ) - ... -) -``` - -16. Add `ChatViewState` customisations. -```dart -ChatView( - ... - chatViewStateConfig: ChatViewStateConfiguration( - loadingWidgetConfig: ChatViewStateWidgetConfiguration( - loadingIndicatorColor: Colors.pink, - ), - onReloadButtonTap: () {}, - ), - ... -) -``` - -17. Setting auto scroll and highlight config with `RepliedMsgAutoScrollConfig` class. -```dart -ChatView( - ... - repliedMsgAutoScrollConfig: RepliedMsgAutoScrollConfig( - enableHighlightRepliedMsg: true, - highlightColor: Colors.grey, - highlightScale: 1.1, - ) - ... -) -``` - -18. Callback when a user starts/stops typing in `TextFieldConfiguration` - -```dart -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. - compositionThresholdTime: const Duration(seconds: 1), - - ), - ... - ) -) -``` - -19. Passing customReceipts builder or handling stuffs related receipts see `ReceiptsWidgetConfig` in outgoingChatBubbleConfig. - -```dart -ChatView( - ... - featureActiveConfig: const FeatureActiveConfig( - /// Controls the visibility of message seen ago receipts default is true - lastSeenAgoBuilderVisibility: false, - /// Controls the visibility of the message [receiptsBuilder] - receiptsBuilderVisibility: false), - ChatBubbleConfiguration( - inComingChatBubbleConfig: ChatBubble( - onMessageRead: (message) { - /// send your message reciepts to the other client - debugPrint('Message Read'); - }, - - ), - outgoingChatBubbleConfig: ChatBubble( - receiptsWidgetConfig: ReceiptsWidgetConfig( - /// custom receipts builder - receiptsBuilder: _customReceiptsBuilder, - /// whether to display receipts in all - /// message or just at the last one just like instagram - showReceiptsIn: ShowReceiptsIn.lastMessage - ), - ), - ), - - ... - -) -``` - -20. Flag `enableOtherUserName` to hide user name in chat. - -```dart -ChatView( - ... - featureActiveConfig: const FeatureActiveConfig( - enableOtherUserName: false, - ), - ... - -) -``` - -21. Added report button for receiver message and update `onMoreTap` and `onReportTap` callbacks. - -```dart -ChatView( - ... - replyPopupConfig: ReplyPopupConfiguration( - onReportTap: (Message message) { - debugPrint('Message: $message'); - }, - onMoreTap: (Message message, bool sentByCurrentUser) { - debugPrint('Message : $message'); - }, - ), - ... -) -``` - -22. Added `emojiPickerSheetConfig` for configuration of emoji picker sheet. - -```dart -ChatView( - ... - emojiPickerSheetConfig: Config( - emojiViewConfig: EmojiViewConfig( - columns: 7, - emojiSizeMax: 32, - recentsLimit: 28, - backgroundColor: Colors.white, - ), - categoryViewConfig: const CategoryViewConfig( - initCategory: Category.RECENT, - recentTabBehavior: RecentTabBehavior.NONE, - ), - ... - -) -``` - -23. Configure the styling & audio recording quality using `VoiceRecordingConfiguration` in sendMessageConfig. - -```dart -ChatView( - ... - sendMessageConfig: SendMessageConfiguration( - - voiceRecordingConfiguration: VoiceRecordingConfiguration( - iosEncoder: IosEncoder.kAudioFormatMPEG4AAC, - androidOutputFormat: AndroidOutputFormat.mpeg4, - androidEncoder: AndroidEncoder.aac, - bitRate: 128000, - sampleRate: 44100, - waveStyle: WaveStyle( - showMiddleLine: false, - waveColor: theme.waveColor ?? Colors.white, - extendWaveform: true, - ), - ), - - ... - ) -) -``` - -24. Added `enabled` to enable/disable chat text field. - -```dart -ChatView( - ... - sendMessageConfig: SendMessageConfiguration( - ... - textFieldConfig: TextFieldConfig( - enabled: true // [false] to disable text field. - ), - ... - ), - ... - -) -``` -25. Added flag `isProfilePhotoInBase64` that defines whether provided image is url or base64 data. - -```dart -final chatController = ChatController( - ... - chatUsers: [ - ChatUser( - id: '1', - name: 'Simform', - isProfilePhotoInBase64: false, - profilePhoto: 'ImageNetworkUrl', - ), - ], - ... -); - -ChatView( - ... - profileCircleConfig: const ProfileCircleConfiguration( - isProfilePhotoInBase64: false, - profileImageUrl: 'ImageNetworkUrl', - ), - ... -) -``` - -26. Added `chatSeparatorDatePattern` in `DefaultGroupSeparatorConfiguration` to separate chats with provided pattern. - -```dart -ChatView( - ... - chatBackgroundConfig: ChatBackgroundConfiguration( - ... - defaultGroupSeparatorConfig: DefaultGroupSeparatorConfiguration( - chatSeparatorDatePattern: 'MMM dd, yyyy' - ), - ... - ), - ... -) -``` - -27. Field `cancelRecordConfiguration` to provide an configuration to cancel voice record message. - -```dart -ChatView( - ... - sendMessageConfig: SendMessageConfiguration( - ... - cancelRecordConfiguration: CancelRecordConfiguration( - icon: const Icon( - Icons.cancel_outlined, - ), - onCancel: () { - debugPrint('Voice recording cancelled'); - }, - iconColor: Colors.black, - ), - ... - ), - ... - -) -``` - -28. Added callback of onTap on list of reacted users in reaction sheet `reactedUserCallback`. -```dart - -ChatView( - ... - messageConfig: MessageConfiguration( - ... - messageReactionConfig: MessageReactionConfiguration( - reactionsBottomSheetConfig: ReactionsBottomSheetConfiguration( - reactedUserCallback: (reactedUser, reaction) { - debugPrint(reaction); - }, - ), - ), - ... - ), - ... -), -``` - -29. Added a `customMessageReplyViewBuilder` to customize reply message view for custom type message. - -```dart -ChatView( - ... - messageConfig: MessageConfiguration( - customMessageBuilder: (ReplyMessage state) { - return Text( - state.message, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 12, - color: Colors.black, - ), - ); - }, - ), - ... -) -``` - -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( - ... - appBar: ChatViewAppBar( - defaultAvatarImage: defaultAvatar, - imageType: ImageType.network, - networkImageErrorBuilder: (context, url, error) { - return Center( - child: Text('Error $error'), - ); - }, - assetImageErrorBuilder: (context, error, stackTrace) { - return Center( - child: Text('Error $error'), - ); - }, - ), - ... -), -``` - -31. Added a `customMessageReplyViewBuilder` to customize reply message view for custom type message. - -```dart -ChatView( - ... - messageConfig: MessageConfiguration( - customMessageBuilder: (ReplyMessage state) { - return Text( - state.message, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 12, - color: Colors.black, - ), - ); - }, - ), - ... -) -``` - -32. 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: [ - Expanded( - child: 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.closeReplyMessageView(context), - ), - ], - ), - ], - ), - ), - ); - }, - ... -) -``` - -33. Reply Suggestions functionalities. - -* Add reply suggestions -```dart -_chatController.addReplySuggestions([ - SuggestionItemData(text: 'Thanks.'), - SuggestionItemData(text: 'Thank you very much.'), - SuggestionItemData(text: 'Great.') - ]); -``` -* Remove reply suggestions -```dart -_chatController.removeReplySuggestions(); -``` -* Update suggestions Config -```dart -replySuggestionsConfig: ReplySuggestionsConfig( - itemConfig: SuggestionItemConfig( - decoration: BoxDecoration(), - textStyle: TextStyle(), - padding: EdgetInsets.all(8), - customItemBuilder: (index, suggestionItemData) => Container() - ), - listConfig: SuggestionListConfig( - decoration: BoxDecoration(), - padding: EdgetInsets.all(8), - itemSeparatorWidth: 8, - axisAlignment: SuggestionListAlignment.left - ) - onTap: (item) => - _onSendTap(item.text, const ReplyMessage(), MessageType.text), - autoDismissOnSelection: true -), -``` - -34. Added callback `messageSorter` to sort message in `ChatBackgroundConfiguration`. - -```dart -ChatView( - ... - chatBackgroundConfig: ChatBackgroundConfiguration( - ... - messageSorter: (message1, message2) { - return message1.createdAt.compareTo(message2.createdAt); - } - ... - ), - ... -), -``` - -35. Use `ScrollToBottomButtonConfig` to change the configuration of scroll to bottom button. - - -```dart -ChatView( - ... - scrollToBottomButtonConfig: ScrollToBottomButtonConfig( - -), - ... -), -``` - - -36. Use `errorBody` to displays an error message when the link cannot be parsed for preview. - - -```dart -ChatView( - ... - linkPreviewConfig: LinkPreviewConfiguration( - errorBody: 'Error encountered while parsing the link for preview' -), - ... -), -``` - - -36. Use `suggestionItemType` to displays a suggestion items in multi line and not in scrollable form. - - -```dart -ChatView( - ... - replySuggestionsConfig: ReplySuggestionsConfig( - suggestionItemType: SuggestionItemsType.multiline, - ), - ... -), -``` - - -## How to use - -Check out [blog](https://medium.com/simform-engineering/chatview-a-cutting-edge-chat-ui-solution-7367b1f9d772) for better understanding and basic implementation. - -Also, for whole example, check out the **example** app in the [example](https://github.com/SimformSolutionsPvtLtd/chatview/tree/main/example) directory or the 'Example' tab on pub.dartlang.org for a more complete example. - - -## Main Contributors - - - - - - - - - -

Vatsal Tanna

Dhvanit Vaghani

Ujas Majithiya

Apurva Kanthraviya

Aditya Chavda
-
+For questions, issues, or feature +requests, [create an issue](https://github.com/SimformSolutionsPvtLtd/chatview/issues) on GitHub or +reach out via the GitHub Discussions tab. We're happy to help and encourage community contributions. +To contribute documentation updates specifically, please make changes to the doc/documentation.md +file and submit a pull request. ## License -```text -MIT License -Copyright (c) 2022 Simform Solutions -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -``` +This project is licensed under the MIT License - see +the [LICENSE](https://simform-flutter-packages.web.app/chatView/license). + +[chatViewConnect]: https://pub.dev/packages/chatview_connect diff --git a/doc/documentation.md b/doc/documentation.md new file mode 100644 index 00000000..f08f6710 --- /dev/null +++ b/doc/documentation.md @@ -0,0 +1,731 @@ +# Overview + +ChatView is a Flutter package that allows you to integrate a highly customizable chat UI in your +Flutter applications with [Flexible Backend Integration](https://pub.dev/packages/chatview_connect). + +## Preview + +![Preview](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/chatview/main/preview/chatview.gif) + +## Features + +- One-on-one chat +- Group chat +- Message reactions +- Reply messages +- Link preview +- Voice messages +- Image sharing +- Message styling +- Typing indicators +- Reply suggestions +- Connect ChatView to any backend + using [chatview_connect](https://pub.dev/packages/chatview_connect) +- And a wide range of configuration options to customize your chat. + +For a live web demo, visit [Chat View Example](https://simformsolutionspvtltd.github.io/chatview/). + +## Compatible Message Types + +| Message Types | Android | iOS | MacOS | Web | Linux | Windows | +| :-----: | :-----: | :-: | :---: | :-: | :---: | :-----: | +| Text messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| Image messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| Voice messages | ✔️ | ✔️ | ❌ | ❌ | ❌ | ❌ | +| Custom messages | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | + + +# Installation + +## Adding the dependency + +1. Add the package dependency to your `pubspec.yaml` file: + +```yaml +dependencies: + chatview: +``` + +You can find the latest version on [pub.dev](https://pub.dev/packages/chatview) under the 'Installing' tab. + +2. Import the package in your Dart code: + +```dart +import 'package:chatview/chatview.dart'; +``` + +## Platform-specific configurations + +### For Image Picker + +#### iOS +Add the following keys to your _Info.plist_ file, located in `/ios/Runner/Info.plist`: + +```xml +NSCameraUsageDescription +Used to demonstrate image picker plugin +NSMicrophoneUsageDescription +Used to capture audio for image picker plugin +NSPhotoLibraryUsageDescription +Used to demonstrate image picker plugin +``` + +### For Voice Messages + +#### iOS +* Add this row in `ios/Runner/Info.plist`: +```xml +NSMicrophoneUsageDescription +This app requires Mic permission. +``` + +* This plugin requires iOS 10.0 or higher. Add this line in `Podfile`: +```ruby +platform :ios, '10.0' +``` + +#### Android +* Change the minimum Android SDK version to 21 (or higher) in your `android/app/build.gradle` file: +```gradle +minSdkVersion 21 +``` + +* Add RECORD_AUDIO permission in `AndroidManifest.xml`: +```xml + +``` + +# Basic Usage + +Here's how to integrate ChatView into your Flutter application with minimal setup: + +## Step 1: Create a Chat Controller + +The `ChatController` manages the state of your chat view: + +```dart +final chatController = ChatController( + initialMessageList: messageList, + scrollController: ScrollController(), + currentUser: ChatUser(id: '1', name: 'Flutter'), + otherUsers: [ChatUser(id: '2', name: 'Simform')], +); +``` + +## Step 2: Add the ChatView Widget + +```dart +ChatView( + chatController: chatController, + onSendTap: onSendTap, + chatViewState: ChatViewState.hasMessages, // Add this state once data is available +) +``` + +## Step 3: Define Message List + +Define your initial message list: + +```dart +List messageList = [ + Message( + id: '1', + message: "Hi", + createdAt: DateTime.now(), + sentBy: userId, + ), + Message( + id: '2', + message: "Hello", + createdAt: DateTime.now(), + sentBy: userId, + ), +]; +``` + +## Step 4: Implement onSendTap Callback + +Handle the send message event: + +```dart +void onSendTap(String message, ReplyMessage replyMessage, MessageType messageType) { + // Create a new message + final newMessage = Message( + id: '3', + message: message, + createdAt: DateTime.now(), + sentBy: currentUser.id, + replyMessage: replyMessage, + messageType: messageType, + ); + + // Add message to chat controller + chatController.addMessage(newMessage); +} +``` + +> Note: You can evaluate message type from the 'messageType' parameter and perform operations accordingly. + +# Advanced Usage + +ChatView offers extensive customization options to tailor the chat UI to your specific needs. + +## Adding Custom Appbar + +```dart +ChatView( + // ... + appBar: ChatViewAppBar( + profilePicture: profileImage, + chatTitle: "Simform", + userStatus: "online", + actions: [ + Icon(Icons.more_vert), + ], + defaultAvatarImage: defaultAvatar, + imageType: ImageType.network, + networkImageErrorBuilder: (context, url, error) { + return Center( + child: Text('Error $error'), + ); + }, + ), + // ... +) +``` + +## Adding Message Reactions + +```dart +ChatView( + // ... + reactionPopupConfig: ReactionPopupConfiguration( + backgroundColor: Colors.white, + userReactionCallback: (message, emoji) { + // Your code here + }, + padding: EdgeInsets.all(12), + shadow: BoxShadow( + color: Colors.black54, + blurRadius: 20, + ), + ), + // ... +) +``` + +## Reply Message Configuration + +```dart +ChatView( + // ... + repliedMessageConfig: RepliedMessageConfiguration( + backgroundColor: Colors.blue, + verticalBarColor: Colors.black, + repliedMsgAutoScrollConfig: RepliedMsgAutoScrollConfig( + enableHighlightRepliedMsg: true, + highlightColor: Colors.grey, + highlightScale: 1.1, + ), + ), + // ... +) +``` + +## Chat Bubble Customization + +```dart +ChatView( + // ... + chatBubbleConfig: ChatBubbleConfiguration( + onDoubleTap: () { + // Your code here + }, + outgoingChatBubbleConfig: ChatBubble( + color: Colors.blue, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(12), + topLeft: Radius.circular(12), + bottomLeft: Radius.circular(12), + ), + ), + inComingChatBubbleConfig: ChatBubble( + color: Colors.grey.shade200, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(12), + topRight: Radius.circular(12), + bottomRight: Radius.circular(12), + ), + ), + ), + // ... +) +``` + +## Swipe to Reply Configuration + +```dart +ChatView( + // ... + swipeToReplyConfig: SwipeToReplyConfiguration( + onLeftSwipe: (message, sentBy) { + // Your code here + }, + onRightSwipe: (message, sentBy) { + // Your code here + }, + ), + // ... +) +``` + +## Voice Message Configuration + +```dart +ChatView( + // ... + sendMessageConfig: SendMessageConfiguration( + voiceRecordingConfiguration: VoiceRecordingConfiguration( + iosEncoder: IosEncoder.kAudioFormatMPEG4AAC, + androidOutputFormat: AndroidOutputFormat.mpeg4, + androidEncoder: AndroidEncoder.aac, + bitRate: 128000, + sampleRate: 44100, + waveStyle: WaveStyle( + showMiddleLine: false, + waveColor: Colors.white, + extendWaveform: true, + ), + ), + cancelRecordConfiguration: CancelRecordConfiguration( + icon: const Icon( + Icons.cancel_outlined, + ), + onCancel: () { + debugPrint('Voice recording cancelled'); + }, + iconColor: Colors.black, + ), + ), + // ... +) +``` + +## Reply Suggestions + +```dart +// Add reply suggestions +_chatController.addReplySuggestions([ + SuggestionItemData(text: 'Thanks.'), + SuggestionItemData(text: 'Thank you very much.'), + SuggestionItemData(text: 'Great.') +]); + +// Remove reply suggestions +_chatController.removeReplySuggestions(); + +// Reply suggestions configuration +ChatView( + // ... + replySuggestionsConfig: ReplySuggestionsConfig( + itemConfig: SuggestionItemConfig( + decoration: BoxDecoration(), + textStyle: TextStyle(), + padding: EdgeInsets.all(8), + ), + listConfig: SuggestionListConfig( + decoration: BoxDecoration(), + padding: EdgeInsets.all(8), + itemSeparatorWidth: 8, + axisAlignment: SuggestionListAlignment.left + ), + onTap: (item) => _onSendTap(item.text, const ReplyMessage(), MessageType.text), + autoDismissOnSelection: true, + suggestionItemType: SuggestionItemsType.multiline, + ), + // ... +) +``` + +## Enabling/Disabling Features + +```dart +ChatView( + // ... + featureActiveConfig: FeatureActiveConfig( + enableSwipeToReply: true, + enableSwipeToSeeTime: false, + enablePagination: true, + enableOtherUserName: false, + lastSeenAgoBuilderVisibility: false, + receiptsBuilderVisibility: false, + ), + // ... +) +``` + +## Link Preview Configuration + +```dart +ChatView( + // ... + chatBubbleConfig: ChatBubbleConfiguration( + linkPreviewConfig: LinkPreviewConfiguration( + linkStyle: const TextStyle( + color: Colors.white, + decoration: TextDecoration.underline, + ), + backgroundColor: Colors.grey, + bodyStyle: const TextStyle( + color: Colors.grey.shade200, + fontSize: 16, + ), + titleStyle: const TextStyle( + color: Colors.black, + fontSize: 20, + ), + errorBody: 'Error encountered while parsing the link for preview' + ), + ), + // ... +) +``` + +## Typing Indicator Configuration + +```dart +ChatView( + // ... + typeIndicatorConfig: TypeIndicatorConfiguration( + flashingCircleBrightColor: Colors.grey, + flashingCircleDarkColor: Colors.black, + ), + // ... +) + +// Show/hide typing indicator +_chatController.setTypingIndicator = true; // Show indicator +_chatController.setTypingIndicator = false; // Hide indicator +``` + +## Custom Message Reply View Builder + +```dart +ChatView( + // ... + messageConfig: MessageConfiguration( + customMessageBuilder: (ReplyMessage state) { + return Text( + state.message, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontSize: 12, + color: Colors.black, + ), + ); + }, + ), + // ... +) +``` + +## Custom Reply Message Builder + +```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: [ + Expanded( + child: 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.closeReplyMessageView(context), + ), + ], + ), + ], + ), + ), + ); + }, + // ... +) +``` + +## Backend Integration + +Easily connect Chatview UI to any backend using the [**Chatview Connect**](https://pub.dev/packages/chatview_connect) +package. It offers ready-to-use solutions for +real-time messaging with supporting media uploads. + + +# Migration Guide + +## Migration Guide for ChatView 2.0.0 +This guide will help you migrate your code from previous versions of ChatView to version 2.0.0. + +## Key Changes + +### Renamed Properties + +- Renamed `sendBy` field to `sentBy` in `Message` class. +- Renamed `chatUsers` field to `otherUsers` in `ChatController` class. + +### Moved Properties + +- Moved `currentUser` field from `ChatView` widget to `ChatController` class. + +### Updated Methods + +- Updated `id` value in `copyWith` method of `Message` to have correct value. +- Removed `showTypingIndicator` field from `ChatView` and replaced it with `ChatController.showTypingIndicator`. + +### JSON Serialization Changes + +The format for `fromJson` and `toJson` methods changed for several classes: + +#### ChatUser + +**Before (`ChatUser.fromJson`):** +```dart +ChatUser.fromJson( + { + ... + 'imageType': ImageType.asset, + ... + }, +), +``` + +**After (`ChatUser.fromJson`):** +```dart +ChatUser.fromJson( + { + ... + 'imageType': 'asset', + ... + }, +), +``` + +**Before (`ChatUser.toJson`):** +```dart +{ + ... + imageType: ImageType.asset, + ... +} +``` + +**After (`ChatUser.toJson`):** +```dart +{ + ... + imageType: asset, + ... +} +``` + +#### Message + +**Before (`Message.fromJson`):** +```dart +Message.fromJson( + { + ... + 'createdAt': DateTime.now(), + 'message_type': MessageType.text, + 'voice_message_duration': Duration(seconds: 5), + ... + } +) +``` + +**After (`Message.fromJson`):** +```dart +Message.fromJson( + { + ... + 'createdAt': '2024-06-13T17:32:19.586412', + 'message_type': 'text', + 'voice_message_duration': '5000000', + ... + } +) +``` + +**Before (`Message.toJson`):** +```dart +{ + ... + createdAt: 2024-06-13 17:23:19.454789, + message_type: MessageType.text, + voice_message_duration: 0:00:05.000000, + ... +} +``` + +**After (`Message.toJson`):** +```dart +{ + ... + createdAt: 2024-06-13T17:32:19.586412, + message_type: text, + voice_message_duration: 5000000, + ... +} +``` + +#### ReplyMessage + +**Before (`ReplyMessage.fromJson`):** +```dart +ReplyMessage.fromJson( + { + ... + 'message_type': MessageType.text, + 'voiceMessageDuration': Duration(seconds: 5), + ... + } +) +``` + +**After (`ReplyMessage.fromJson`):** +```dart +ReplyMessage.fromJson( + { + ... + 'message_type': 'text', + 'voiceMessageDuration': '5000000', + ... + } +) +``` + +**Before (`ReplyMessage.toJson`):** +```dart +{ + ... + message_type: MessageType.text, + voiceMessageDuration: 0:00:05.000000, + ... +} +``` + +**After (`ReplyMessage.toJson`):** +```dart +{ + ... + message_type: text, + voiceMessageDuration: 5000000, + ... +} +``` + +## Typing Indicator Changes + +**Before:** +```dart +ChatView( + showTypingIndicator: false, +), +``` + +**After:** +```dart +// Use it with your ChatController instance +_chatController.setTypingIndicator = true; // for showing indicator +_chatController.setTypingIndicator = false; // for hiding indicator +``` + +# Contributors + +## Main Contributors + +| ![img](https://avatars.githubusercontent.com/u/25323183?v=4&s=200) | ![img](https://avatars.githubusercontent.com/u/56400956?v=4&s=200) | ![img](https://avatars.githubusercontent.com/u/65003381?v=4&s=200) | ![img](https://avatars.githubusercontent.com/u/41247722?v=4&s=200) | +|:------------------------------------------------------------------:|:------------------------------------------------------------:|:------------------------------------------------------------:|:------------------------------------------------------------:| +| [Vatsal Tanna](https://github.com/vatsaltanna) | [Ujas Majithiya](https://github.com/Ujas-Majithiya) | [Apurva Kanthraviya](https://github.com/apurva780) | [Aditya Chavda](https://github.com/aditya-chavda) | + +## How to Contribute + +Contributions are welcome! If you'd like to contribute to this project, please follow these steps: + +1. Fork the repository +2. Create your feature branch (`git checkout -b feature/amazing-feature`) +3. Commit your changes (`git commit -m 'Add some amazing feature'`) +4. Push to the branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +## Report Issues + +If you find any bugs or have feature requests, please create an issue in the [issue tracker](https://github.com/SimformSolutionsPvtLtd/chatview/issues). + +## Project Resources + +- GitHub Repository: [chatview](https://github.com/SimformSolutionsPvtLtd/chatview). +- Package on pub.dev: [chatview](https://pub.dev/packages/chatview). +- Web Demo: [Chat View Example](https://simformsolutionspvtltd.github.io/chatview/). +- Blog Post: [ChatView: A Cutting-Edge Chat UI Solution](https://medium.com/simform-engineering/chatview-a-cutting-edge-chat-ui-solution-7367b1f9d772). + +# License + +``` +MIT License +Copyright (c) 2022 Simform Solutions +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +```