diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0a27ab62..71a52877 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,46 +1,42 @@
## [2.0.0] (Unreleased)
-* **Fix**: [182](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/182) Fix
- send message not working when user start texting after newLine.
-* **Feat**: [156](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/156) Added
- default avatar, error builder for asset, network and base64 profile image and
- cached_network_image for network images.
-* **Breaking**: [173](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/173) Added
- callback to sort message in chat.
-* **Fix**: [181](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/181) Removed
- deprecated field `showTypingIndicator` from ChatView.
+* **Feat**: [179](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/179) Added reply
+ suggestions functionality
+* **Feat**: [161](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/161) Added field
+ to set top padding of chat text field.
+* **Feat**: [157](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/157) Added onTap
+ of reacted user from reacted user list.
+* **Feat**: [121](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/121) Added support
+ for configuring the audio recording quality.
+* **Feat**: [93](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/93) Added support
+ that provide date pattern to change chat separation.
* **Fix**: [139](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/139) Added
support to customize view for the reply of any message.
-* **Fix**: [174](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/174) Fix
- wrong username shown while replying to any messages.
-* **Fix**: [134](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/134)
- Added a reply message view for custom message type.
-* **Feat**: [157](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/157)
- Added onTap of reacted user from reacted user list.
+* **Fix**: [174](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/174) Fix wrong
+ username shown while replying to any messages.
+* **Fix**: [134](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/134) Added a
+ reply message view for custom message type.
* **Fix**: [137](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/137) Added
support for cancel voice recording and field to provide cancel record icon.
-* **Feat**: [93](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/93) Added support
- that provide date pattern to change chat separation.
-* **Fix**: [142](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/142) Added
- field to provide base64 string data for profile picture.
-* **Fix**: [165](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/165) Fix issue
- of user reaction callback provides incorrect message object when user react on any message
- with double or from reaction sheet.
-* **Fix**: [164](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/164)
- Add flag to enable/disable chat text field.
-* **Feat**: [121](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/121)Added support
- for configuring the audio recording quality.
-* **Fix**: [131](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/131)
- Fix unsupported operation while running on the web.
+* **Fix**: [142](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/142) Added field
+ to provide base64 string data for profile picture.
+* **Fix**: [165](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/165) Fix issue of
+ user reaction callback provides incorrect message object when user react on any message with
+ double or from reaction sheet.
+* **Fix**: [164](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/164) Add flag to
+ enable/disable chat text field.
+* **Fix**: [131](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/131) Fix
+ unsupported operation while running on the web.
* **Fix**: [160](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/160) Added
configuration for emoji picker sheet.
-* **Fix**: [130](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/130) Added
- report button for receiver message and update onMoreTap, onReportTap callback.
-* **Fix**: [126](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/126) Added
- flag to hide user name in chat.
-* **Feat**: [161](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/161) Added
- field to set top padding of chat text field.
-
+* **Fix**: [130](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/130) Added report
+ button for receiver message and update onMoreTap, onReportTap callback.
+* **Fix**: [126](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/126) Added flag
+ to hide user name in chat.
+* **Fix**: [181](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/pull/181) Removed
+ deprecated field `showTypingIndicator` from ChatView.
+* **Fix**: [182](https://github.com/SimformSolutionsPvtLtd/flutter_chatview/issues/182) Fix
+ send message not working when user start texting after newLine.
## [1.3.1]
diff --git a/README.md b/README.md
index bf0fcd5e..1c6c0457 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
![Banner](https://raw.githubusercontent.com/SimformSolutionsPvtLtd/flutter_chat_ui/main/preview/banner.png)
# ChatView
- [![chatview](https://img.shields.io/pub/v/chatview?label=chatview)](https://pub.dev/packages/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.
@@ -34,7 +34,7 @@ ChatView(
),
```
-## Installing
+## Installing
1. Add dependency to `pubspec.yaml`
@@ -434,7 +434,7 @@ ChatView(
```
17. Callback when a user starts/stops typing in `TextFieldConfiguration`
-
+
```dart
ChatView(
...
@@ -459,7 +459,7 @@ ChatView(
```
18. Passing customReceipts builder or handling stuffs related receipts see `ReceiptsWidgetConfig` in outgoingChatBubbleConfig.
-
+
```dart
ChatView(
...
@@ -812,6 +812,103 @@ ChatView(
)
```
+31. 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 Sugestions 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
+),
+```
+
+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. Added callback `messageSorter` to sort message in `ChatBackgroundConfiguration`.
```dart
@@ -832,7 +929,7 @@ ChatView(
## 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.
+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/flutter_chatview/tree/main/example) directory or the 'Example' tab on pub.dartlang.org for a more complete example.
@@ -844,6 +941,8 @@ Also, for whole example, check out the **example** app in the [example](https://
![](https://avatars.githubusercontent.com/u/25323183?s=100) Vatsal Tanna |
![](https://avatars.githubusercontent.com/u/64645989?v=4) Dhvanit Vaghani |
![](https://avatars.githubusercontent.com/u/56400956?v=4) Ujas Majithiya |
+ ![](https://avatars.githubusercontent.com/u/65003381?v=4) Apurva Kanthraviya |
+
diff --git a/example/lib/main.dart b/example/lib/main.dart
index bdc02f92..174975c9 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -71,6 +71,20 @@ class _ChatScreenState extends State {
_chatController.setTypingIndicator = !_chatController.showTypingIndicator;
}
+ void receiveMessage() async {
+ _chatController.addMessage(Message(
+ id: DateTime.now().toString(),
+ message: 'I will schedule the meeting.',
+ createdAt: DateTime.now(),
+ sendBy: '2'));
+ await Future.delayed(const Duration(milliseconds: 500));
+ _chatController.addReplySuggestions([
+ SuggestionItemData(text: 'Thanks.'),
+ SuggestionItemData(text: 'Thank you very much.'),
+ SuggestionItemData(text: 'Great.')
+ ]);
+ }
+
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -125,6 +139,14 @@ class _ChatScreenState extends State {
color: theme.themeIconColor,
),
),
+ IconButton(
+ tooltip: 'Simulate Message receive',
+ onPressed: receiveMessage,
+ icon: Icon(
+ Icons.supervised_user_circle,
+ color: theme.themeIconColor,
+ ),
+ ),
],
),
chatBackgroundConfig: ChatBackgroundConfiguration(
@@ -266,6 +288,22 @@ class _ChatScreenState extends State {
swipeToReplyConfig: SwipeToReplyConfiguration(
replyIconColor: theme.swipeToReplyIconColor,
),
+ replySuggestionsConfig: ReplySuggestionsConfig(
+ itemConfig: SuggestionItemConfig(
+ decoration: BoxDecoration(
+ color: theme.textFieldBackgroundColor,
+ borderRadius: BorderRadius.circular(8),
+ border: Border.all(
+ color: theme.outgoingChatBubbleColor ?? Colors.white,
+ ),
+ ),
+ textStyle: TextStyle(
+ color: isDarkTheme ? Colors.white : Colors.black,
+ ),
+ ),
+ onTap: (item) =>
+ _onSendTap(item.text, const ReplyMessage(), MessageType.text),
+ ),
),
);
}
@@ -275,10 +313,9 @@ class _ChatScreenState extends State {
ReplyMessage replyMessage,
MessageType messageType,
) {
- final id = int.parse(Data.messageList.last.id) + 1;
_chatController.addMessage(
Message(
- id: id.toString(),
+ id: DateTime.now().toString(),
createdAt: DateTime.now(),
message: message,
sendBy: currentUser.id,
diff --git a/lib/src/controller/chat_controller.dart b/lib/src/controller/chat_controller.dart
index d1c277e6..0046746c 100644
--- a/lib/src/controller/chat_controller.dart
+++ b/lib/src/controller/chat_controller.dart
@@ -21,6 +21,7 @@
*/
import 'dart:async';
+import 'package:chatview/src/widgets/suggestions/suggestion_list.dart';
import 'package:flutter/material.dart';
import '../models/models.dart';
@@ -42,6 +43,19 @@ class ChatController {
/// For more functionalities see [ValueNotifier].
ValueNotifier get typingIndicatorNotifier => _showTypingIndicator;
+ /// Allow user to add reply suggestions defaults to empty.
+ final ValueNotifier> _replySuggestion =
+ ValueNotifier([]);
+
+ /// newSuggestions as [ValueNotifier] for [SuggestionList] widget's [ValueListenableBuilder].
+ /// Use this to listen when suggestion gets added
+ /// ```dart
+ /// chatcontroller.newSuggestions.addListener((){});
+ /// ```
+ /// For more functionalities see [ValueNotifier].
+ ValueNotifier> get newSuggestions =>
+ _replySuggestion;
+
/// Getter for typingIndicator value instead of accessing [_showTypingIndicator.value]
/// for better accessibility.
bool get showTypingIndicator => _showTypingIndicator.value;
@@ -74,6 +88,16 @@ class ChatController {
messageStreamController.sink.add(initialMessageList);
}
+ /// Used to add reply suggestions.
+ void addReplySuggestions(List suggestions) {
+ _replySuggestion.value = suggestions;
+ }
+
+ /// Used to remove reply suggestions.
+ void removeReplySuggestions() {
+ _replySuggestion.value = [];
+ }
+
/// Function for setting reaction on specific chat bubble
void setReaction({
required String emoji,
diff --git a/lib/src/extensions/extensions.dart b/lib/src/extensions/extensions.dart
index 0e8ebcfc..99c0a53f 100644
--- a/lib/src/extensions/extensions.dart
+++ b/lib/src/extensions/extensions.dart
@@ -22,6 +22,7 @@
import 'package:chatview/chatview.dart';
import 'package:chatview/src/widgets/chat_view_inherited_widget.dart';
import 'package:chatview/src/widgets/profile_image_widget.dart';
+import 'package:chatview/src/widgets/suggestions/suggestions_config_inherited_widget.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../utils/constants/constants.dart';
@@ -129,4 +130,15 @@ extension ChatViewStateTitleExtension on String? {
/// Extension on State for accessing inherited widget.
extension StatefulWidgetExtension on State {
ChatViewInheritedWidget? get provide => ChatViewInheritedWidget.of(context);
+
+ ReplySuggestionsConfig? get suggestionsConfig =>
+ SuggestionsConfigIW.of(context)?.suggestionsConfig;
+}
+
+/// Extension on State for accessing inherited widget.
+extension BuildContextExtension on BuildContext {
+ ChatViewInheritedWidget? get provide => ChatViewInheritedWidget.of(this);
+
+ ReplySuggestionsConfig? get suggestionsConfig =>
+ SuggestionsConfigIW.of(this)?.suggestionsConfig;
}
diff --git a/lib/src/models/models.dart b/lib/src/models/models.dart
index 45bcbbdf..52b6bd13 100644
--- a/lib/src/models/models.dart
+++ b/lib/src/models/models.dart
@@ -41,3 +41,7 @@ export 'chat_view_states_configuration.dart';
export 'reaction.dart';
export 'replied_msg_auto_scroll_config.dart';
export 'feature_active_config.dart';
+export 'suggestion_item_data.dart';
+export 'suggestions_config.dart';
+export 'suggestion_list_config.dart';
+export 'suggestion_item_config.dart';
diff --git a/lib/src/models/profile_circle.dart b/lib/src/models/profile_circle.dart
index 5e805cb9..88614a94 100644
--- a/lib/src/models/profile_circle.dart
+++ b/lib/src/models/profile_circle.dart
@@ -59,7 +59,7 @@ class ProfileCircleConfiguration {
/// Progress indicator builder for network image
final NetworkImageProgressIndicatorBuilder?
- networkImageProgressIndicatorBuilder;
+ networkImageProgressIndicatorBuilder;
const ProfileCircleConfiguration({
this.onAvatarTap,
diff --git a/lib/src/models/suggestion_item_config.dart b/lib/src/models/suggestion_item_config.dart
new file mode 100644
index 00000000..902c5a49
--- /dev/null
+++ b/lib/src/models/suggestion_item_config.dart
@@ -0,0 +1,16 @@
+import '../values/typedefs.dart';
+import 'package:flutter/material.dart';
+
+class SuggestionItemConfig {
+ final BoxDecoration? decoration;
+ final EdgeInsets? padding;
+ final TextStyle? textStyle;
+ final SuggestionItemBuilder? customItemBuilder;
+
+ SuggestionItemConfig({
+ this.decoration,
+ this.padding,
+ this.textStyle,
+ this.customItemBuilder,
+ });
+}
diff --git a/lib/src/models/suggestion_item_data.dart b/lib/src/models/suggestion_item_data.dart
new file mode 100644
index 00000000..1933f016
--- /dev/null
+++ b/lib/src/models/suggestion_item_data.dart
@@ -0,0 +1,11 @@
+import 'suggestion_item_config.dart';
+
+class SuggestionItemData {
+ final String text;
+ final SuggestionItemConfig? config;
+
+ SuggestionItemData({
+ required this.text,
+ this.config,
+ });
+}
diff --git a/lib/src/models/suggestion_list_config.dart b/lib/src/models/suggestion_list_config.dart
new file mode 100644
index 00000000..37ed4fc1
--- /dev/null
+++ b/lib/src/models/suggestion_list_config.dart
@@ -0,0 +1,16 @@
+import '../values/enumeration.dart';
+import 'package:flutter/cupertino.dart';
+
+class SuggestionListConfig {
+ final BoxDecoration? decoration;
+ final EdgeInsets? padding;
+ final double itemSeparatorWidth;
+ final SuggestionListAlignment axisAlignment;
+
+ SuggestionListConfig({
+ this.decoration,
+ this.padding,
+ this.axisAlignment = SuggestionListAlignment.right,
+ this.itemSeparatorWidth = 8,
+ });
+}
diff --git a/lib/src/models/suggestions_config.dart b/lib/src/models/suggestions_config.dart
new file mode 100644
index 00000000..4212a3ba
--- /dev/null
+++ b/lib/src/models/suggestions_config.dart
@@ -0,0 +1,17 @@
+import 'suggestion_item_config.dart';
+import 'suggestion_item_data.dart';
+import 'suggestion_list_config.dart';
+
+class ReplySuggestionsConfig {
+ final SuggestionItemConfig? itemConfig;
+ final SuggestionListConfig? listConfig;
+ final Function(SuggestionItemData)? onTap;
+ final bool autoDismissOnSelection;
+
+ ReplySuggestionsConfig({
+ this.listConfig,
+ this.itemConfig,
+ this.onTap,
+ this.autoDismissOnSelection = true,
+ });
+}
diff --git a/lib/src/values/enumeration.dart b/lib/src/values/enumeration.dart
index 9b2f9cac..ff64744a 100644
--- a/lib/src/values/enumeration.dart
+++ b/lib/src/values/enumeration.dart
@@ -21,6 +21,9 @@
*/
// Different types Message of ChatView
+
+import 'package:flutter/material.dart';
+
enum MessageType {
image,
text,
@@ -55,6 +58,15 @@ enum ImageType {
bool get isBase64 => this == ImageType.base64;
}
+enum SuggestionListAlignment {
+ left(CrossAxisAlignment.start),
+ center(CrossAxisAlignment.center),
+ right(CrossAxisAlignment.end);
+
+ const SuggestionListAlignment(this.alignment);
+ final CrossAxisAlignment alignment;
+}
+
extension ChatViewStateExtension on ChatViewState {
bool get hasMessages => this == ChatViewState.hasMessages;
diff --git a/lib/src/values/typedefs.dart b/lib/src/values/typedefs.dart
index 966d2c4c..d7331acc 100644
--- a/lib/src/values/typedefs.dart
+++ b/lib/src/values/typedefs.dart
@@ -83,3 +83,5 @@ typedef NetworkImageProgressIndicatorBuilder = Widget Function(
String url,
DownloadProgress progress,
);
+typedef SuggestionItemBuilder = Widget Function(
+ int index, SuggestionItemData suggestionItemData);
diff --git a/lib/src/widgets/chat_groupedlist_widget.dart b/lib/src/widgets/chat_groupedlist_widget.dart
index ab9c7d1e..e86cb998 100644
--- a/lib/src/widgets/chat_groupedlist_widget.dart
+++ b/lib/src/widgets/chat_groupedlist_widget.dart
@@ -202,16 +202,12 @@ class _ChatGroupedListWidgetState extends State
.chatController
.typingIndicatorNotifier,
builder: (context, value, child) => TypingIndicator(
- typeIndicatorConfig: widget.typeIndicatorConfig,
- chatBubbleConfig:
- chatBubbleConfig?.inComingChatBubbleConfig,
- showIndicator: value,
- )),
- SizedBox(
- height: (MediaQuery.of(context).size.width *
- (widget.replyMessage.message.isNotEmpty ? 0.3 : 0.14)) +
- (widget.chatTextFieldTopPadding),
- ),
+ typeIndicatorConfig: widget.typeIndicatorConfig,
+ chatBubbleConfig:
+ chatBubbleConfig?.inComingChatBubbleConfig,
+ showIndicator: value,
+ ),
+ ),
],
),
);
diff --git a/lib/src/widgets/chat_view.dart b/lib/src/widgets/chat_view.dart
index e206adc8..9c26c483 100644
--- a/lib/src/widgets/chat_view.dart
+++ b/lib/src/widgets/chat_view.dart
@@ -20,43 +20,46 @@
* SOFTWARE.
*/
import 'package:chatview/chatview.dart';
+import 'package:chatview/src/extensions/extensions.dart';
import 'package:chatview/src/widgets/chat_list_widget.dart';
import 'package:chatview/src/widgets/chat_view_inherited_widget.dart';
import 'package:chatview/src/widgets/chatview_state_widget.dart';
+import 'package:chatview/src/widgets/suggestions/suggestions_config_inherited_widget.dart';
import 'package:flutter/material.dart';
import 'package:timeago/timeago.dart';
import '../values/custom_time_messages.dart';
import 'send_message_widget.dart';
class ChatView extends StatefulWidget {
- const ChatView({
- Key? key,
- required this.chatController,
- required this.currentUser,
- this.onSendTap,
- this.profileCircleConfig,
- this.chatBubbleConfig,
- this.repliedMessageConfig,
- this.swipeToReplyConfig,
- this.replyPopupConfig,
- this.reactionPopupConfig,
- this.loadMoreData,
- this.loadingWidget,
- this.messageConfig,
- this.isLastPage,
- this.appBar,
- ChatBackgroundConfiguration? chatBackgroundConfig,
- this.typeIndicatorConfig,
- this.sendMessageBuilder,
- this.sendMessageConfig,
- this.onChatListTap,
- required this.chatViewState,
- ChatViewStateConfiguration? chatViewStateConfig,
- this.featureActiveConfig = const FeatureActiveConfig(),
- this.chatTextFieldTopPadding = 0,
- this.emojiPickerSheetConfig,
- this.replyMessageBuilder,
- }) : chatBackgroundConfig =
+ const ChatView(
+ {Key? key,
+ required this.chatController,
+ required this.currentUser,
+ this.onSendTap,
+ this.profileCircleConfig,
+ this.chatBubbleConfig,
+ this.repliedMessageConfig,
+ this.swipeToReplyConfig,
+ this.replyPopupConfig,
+ this.reactionPopupConfig,
+ this.loadMoreData,
+ this.loadingWidget,
+ this.messageConfig,
+ this.isLastPage,
+ this.appBar,
+ ChatBackgroundConfiguration? chatBackgroundConfig,
+ this.typeIndicatorConfig,
+ this.sendMessageBuilder,
+ this.sendMessageConfig,
+ this.onChatListTap,
+ required this.chatViewState,
+ ChatViewStateConfiguration? chatViewStateConfig,
+ this.featureActiveConfig = const FeatureActiveConfig(),
+ this.chatTextFieldTopPadding = 0,
+ this.emojiPickerSheetConfig,
+ this.replyMessageBuilder,
+ this.replySuggestionsConfig})
+ : chatBackgroundConfig =
chatBackgroundConfig ?? const ChatBackgroundConfiguration(),
chatViewStateConfig =
chatViewStateConfig ?? const ChatViewStateConfiguration(),
@@ -140,6 +143,9 @@ class ChatView extends StatefulWidget {
/// Configuration for emoji picker sheet
final Config? emojiPickerSheetConfig;
+ /// Suggestion Item Config
+ final ReplySuggestionsConfig? replySuggestionsConfig;
+
/// Provides a callback for the view when replying to message
final CustomViewForReplyMessage? replyMessageBuilder;
@@ -194,97 +200,127 @@ class _ChatViewState extends State
featureActiveConfig: featureActiveConfig,
currentUser: widget.currentUser,
profileCircleConfiguration: widget.profileCircleConfig,
- child: Container(
- height:
- chatBackgroundConfig.height ?? MediaQuery.of(context).size.height,
- width: chatBackgroundConfig.width ?? MediaQuery.of(context).size.width,
- decoration: BoxDecoration(
- color: chatBackgroundConfig.backgroundColor ?? Colors.white,
- image: chatBackgroundConfig.backgroundImage != null
- ? DecorationImage(
- fit: BoxFit.fill,
- image: NetworkImage(chatBackgroundConfig.backgroundImage!),
- )
- : null,
- ),
- padding: chatBackgroundConfig.padding,
- margin: chatBackgroundConfig.margin,
- child: Column(
- children: [
- if (widget.appBar != null) widget.appBar!,
- Expanded(
- child: Stack(
- children: [
- if (chatViewState.isLoading)
- ChatViewStateWidget(
- chatViewStateWidgetConfig:
- chatViewStateConfig?.loadingWidgetConfig,
- chatViewState: chatViewState,
- )
- else if (chatViewState.noMessages)
- ChatViewStateWidget(
- chatViewStateWidgetConfig:
- chatViewStateConfig?.noMessageWidgetConfig,
- chatViewState: chatViewState,
- onReloadButtonTap: chatViewStateConfig?.onReloadButtonTap,
+ child: SuggestionsConfigIW(
+ suggestionsConfig: widget.replySuggestionsConfig,
+ child: Builder(builder: (context) {
+ return Container(
+ height: chatBackgroundConfig.height ??
+ MediaQuery.of(context).size.height,
+ width:
+ chatBackgroundConfig.width ?? MediaQuery.of(context).size.width,
+ decoration: BoxDecoration(
+ color: chatBackgroundConfig.backgroundColor ?? Colors.white,
+ image: chatBackgroundConfig.backgroundImage != null
+ ? DecorationImage(
+ fit: BoxFit.fill,
+ image:
+ NetworkImage(chatBackgroundConfig.backgroundImage!),
)
- else if (chatViewState.isError)
- ChatViewStateWidget(
- chatViewStateWidgetConfig:
- chatViewStateConfig?.errorWidgetConfig,
- chatViewState: chatViewState,
- onReloadButtonTap: chatViewStateConfig?.onReloadButtonTap,
- )
- else if (chatViewState.hasMessages)
- ValueListenableBuilder(
- valueListenable: replyMessage,
- builder: (_, state, child) {
- return ChatListWidget(
- showTypingIndicator:
- chatController.showTypingIndicator,
- replyMessage: state,
- chatController: widget.chatController,
- chatBackgroundConfig: widget.chatBackgroundConfig,
- reactionPopupConfig: widget.reactionPopupConfig,
- typeIndicatorConfig: widget.typeIndicatorConfig,
- chatBubbleConfig: widget.chatBubbleConfig,
- loadMoreData: widget.loadMoreData,
- isLastPage: widget.isLastPage,
- replyPopupConfig: widget.replyPopupConfig,
- loadingWidget: widget.loadingWidget,
+ : null,
+ ),
+ padding: chatBackgroundConfig.padding,
+ margin: chatBackgroundConfig.margin,
+ child: Column(
+ children: [
+ if (widget.appBar != null) widget.appBar!,
+ Expanded(
+ child: Column(
+ children: [
+ Expanded(
+ child: Stack(
+ children: [
+ if (chatViewState.isLoading)
+ ChatViewStateWidget(
+ chatViewStateWidgetConfig:
+ chatViewStateConfig?.loadingWidgetConfig,
+ chatViewState: chatViewState,
+ )
+ else if (chatViewState.noMessages)
+ ChatViewStateWidget(
+ chatViewStateWidgetConfig:
+ chatViewStateConfig?.noMessageWidgetConfig,
+ chatViewState: chatViewState,
+ onReloadButtonTap:
+ chatViewStateConfig?.onReloadButtonTap,
+ )
+ else if (chatViewState.isError)
+ ChatViewStateWidget(
+ chatViewStateWidgetConfig:
+ chatViewStateConfig?.errorWidgetConfig,
+ chatViewState: chatViewState,
+ onReloadButtonTap:
+ chatViewStateConfig?.onReloadButtonTap,
+ )
+ else if (chatViewState.hasMessages)
+ ValueListenableBuilder(
+ valueListenable: replyMessage,
+ builder: (_, state, child) {
+ return ChatListWidget(
+ showTypingIndicator:
+ chatController.showTypingIndicator,
+ replyMessage: state,
+ chatController: widget.chatController,
+ chatBackgroundConfig:
+ widget.chatBackgroundConfig,
+ reactionPopupConfig:
+ widget.reactionPopupConfig,
+ typeIndicatorConfig:
+ widget.typeIndicatorConfig,
+ chatBubbleConfig: widget.chatBubbleConfig,
+ loadMoreData: widget.loadMoreData,
+ isLastPage: widget.isLastPage,
+ replyPopupConfig: widget.replyPopupConfig,
+ loadingWidget: widget.loadingWidget,
+ messageConfig: widget.messageConfig,
+ profileCircleConfig:
+ widget.profileCircleConfig,
+ repliedMessageConfig:
+ widget.repliedMessageConfig,
+ swipeToReplyConfig:
+ widget.swipeToReplyConfig,
+ onChatListTap: widget.onChatListTap,
+ assignReplyMessage: (message) =>
+ _sendMessageKey.currentState
+ ?.assignReplyMessage(message),
+ chatTextFieldTopPadding:
+ widget.chatTextFieldTopPadding,
+ emojiPickerSheetConfig:
+ widget.emojiPickerSheetConfig,
+ );
+ },
+ ),
+ ],
+ ),
+ ),
+ if (featureActiveConfig.enableTextField)
+ SendMessageWidget(
+ key: _sendMessageKey,
+ chatController: chatController,
+ sendMessageBuilder: widget.sendMessageBuilder,
+ sendMessageConfig: widget.sendMessageConfig,
+ backgroundColor: chatBackgroundConfig.backgroundColor,
+ onSendTap: (message, replyMessage, messageType) {
+ if (context.suggestionsConfig
+ ?.autoDismissOnSelection ??
+ true) {
+ chatController.removeReplySuggestions();
+ }
+ _onSendTap(message, replyMessage, messageType);
+ },
+ onReplyCallback: (reply) =>
+ replyMessage.value = reply,
+ onReplyCloseCallback: () =>
+ replyMessage.value = const ReplyMessage(),
messageConfig: widget.messageConfig,
- profileCircleConfig: widget.profileCircleConfig,
- repliedMessageConfig: widget.repliedMessageConfig,
- swipeToReplyConfig: widget.swipeToReplyConfig,
- onChatListTap: widget.onChatListTap,
- assignReplyMessage: (message) => _sendMessageKey
- .currentState
- ?.assignReplyMessage(message),
- chatTextFieldTopPadding:
- widget.chatTextFieldTopPadding,
- emojiPickerSheetConfig: widget.emojiPickerSheetConfig,
- );
- },
- ),
- if (featureActiveConfig.enableTextField)
- SendMessageWidget(
- key: _sendMessageKey,
- chatController: chatController,
- sendMessageBuilder: widget.sendMessageBuilder,
- sendMessageConfig: widget.sendMessageConfig,
- backgroundColor: chatBackgroundConfig.backgroundColor,
- onSendTap: _onSendTap,
- onReplyCallback: (reply) => replyMessage.value = reply,
- onReplyCloseCallback: () =>
- replyMessage.value = const ReplyMessage(),
- messageConfig: widget.messageConfig,
- replyMessageBuilder: widget.replyMessageBuilder,
- ),
- ],
- ),
+ replyMessageBuilder: widget.replyMessageBuilder,
+ ),
+ ],
+ ),
+ ),
+ ],
),
- ],
- ),
+ );
+ }),
),
);
}
diff --git a/lib/src/widgets/chat_view_appbar.dart b/lib/src/widgets/chat_view_appbar.dart
index fb7cebe6..8da6f4d2 100644
--- a/lib/src/widgets/chat_view_appbar.dart
+++ b/lib/src/widgets/chat_view_appbar.dart
@@ -104,7 +104,7 @@ class ChatViewAppBar extends StatelessWidget {
/// Progress indicator builder for network image
final NetworkImageProgressIndicatorBuilder?
- networkImageProgressIndicatorBuilder;
+ networkImageProgressIndicatorBuilder;
@override
Widget build(BuildContext context) {
@@ -142,7 +142,8 @@ class ChatViewAppBar extends StatelessWidget {
assetImageErrorBuilder: assetImageErrorBuilder,
networkImageErrorBuilder: networkImageErrorBuilder,
imageType: imageType,
- networkImageProgressIndicatorBuilder: networkImageProgressIndicatorBuilder,
+ networkImageProgressIndicatorBuilder:
+ networkImageProgressIndicatorBuilder,
),
),
Column(
diff --git a/lib/src/widgets/send_message_widget.dart b/lib/src/widgets/send_message_widget.dart
index 4fa0ab5f..79f5f803 100644
--- a/lib/src/widgets/send_message_widget.dart
+++ b/lib/src/widgets/send_message_widget.dart
@@ -24,7 +24,9 @@ import 'dart:io' if (kIsWeb) 'dart:html';
import 'package:chatview/chatview.dart';
import 'package:chatview/src/extensions/extensions.dart';
import 'package:chatview/src/utils/package_strings.dart';
+import 'package:chatview/src/widgets/chat_view_inherited_widget.dart';
import 'package:chatview/src/widgets/chatui_textfield.dart';
+import 'package:chatview/src/widgets/suggestions/suggestion_list.dart';
import 'package:chatview/src/widgets/reply_message_view.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
@@ -104,152 +106,172 @@ class SendMessageWidgetState extends State {
@override
Widget build(BuildContext context) {
- return widget.sendMessageBuilder != null
- ? Positioned(
- right: 0,
- left: 0,
- bottom: 0,
- child: widget.sendMessageBuilder!(replyMessage),
- )
- : Align(
- alignment: Alignment.bottomCenter,
- child: SizedBox(
- width: MediaQuery.of(context).size.width,
- child: Stack(
- children: [
- Positioned(
- right: 0,
- left: 0,
- bottom: 0,
- child: Container(
- height: MediaQuery.of(context).size.height /
- ((!kIsWeb && Platform.isIOS) ? 24 : 28),
- color: widget.backgroundColor ?? Colors.white,
- ),
- ),
- Padding(
- padding: EdgeInsets.fromLTRB(
- bottomPadding4,
- bottomPadding4,
- bottomPadding4,
- _bottomPadding,
- ),
- child: Stack(
- alignment: Alignment.bottomCenter,
- children: [
- ValueListenableBuilder(
- builder: (_, state, child) {
- final replyTitle =
- "${PackageStrings.replyTo} $_replyTo";
- if (state.message.isNotEmpty) {
- return widget.replyMessageBuilder
- ?.call(context, state) ??
- Container(
- decoration: BoxDecoration(
- color: widget.sendMessageConfig
- ?.textFieldBackgroundColor ??
- Colors.white,
- borderRadius: const BorderRadius.vertical(
- top: Radius.circular(14),
- ),
- ),
- margin: const EdgeInsets.only(
- bottom: 17,
- right: 0.4,
- left: 0.4,
- ),
- padding: const EdgeInsets.fromLTRB(
- leftPadding,
- leftPadding,
- leftPadding,
- 30,
- ),
- child: Container(
- margin: const EdgeInsets.only(bottom: 2),
- padding: const EdgeInsets.symmetric(
- vertical: 4,
- horizontal: 6,
- ),
- decoration: BoxDecoration(
- color: widget.sendMessageConfig
- ?.replyDialogColor ??
- Colors.grey.shade200,
- borderRadius: BorderRadius.circular(12),
- ),
- child: Column(
- crossAxisAlignment:
- CrossAxisAlignment.start,
- mainAxisSize: MainAxisSize.min,
- children: [
- Row(
- mainAxisAlignment:
- MainAxisAlignment.spaceBetween,
+ final suggestionsListConfig = suggestionsConfig?.listConfig;
+ return Align(
+ alignment: Alignment.bottomCenter,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: suggestionsListConfig?.axisAlignment.alignment ??
+ CrossAxisAlignment.end,
+ children: [
+ Flexible(
+ child: ValueListenableBuilder(
+ valueListenable: ChatViewInheritedWidget.of(context)!
+ .chatController
+ .newSuggestions,
+ builder: (context, value, child) {
+ return SuggestionList(
+ suggestions: value,
+ );
+ },
+ ),
+ ),
+ widget.sendMessageBuilder != null
+ ? widget.sendMessageBuilder!(replyMessage)
+ : SizedBox(
+ width: MediaQuery.of(context).size.width,
+ child: Stack(
+ children: [
+ Positioned(
+ right: 0,
+ left: 0,
+ bottom: 0,
+ child: Container(
+ height: MediaQuery.of(context).size.height /
+ ((!kIsWeb && Platform.isIOS) ? 24 : 28),
+ color: widget.backgroundColor ?? Colors.white,
+ ),
+ ),
+ Padding(
+ padding: EdgeInsets.fromLTRB(
+ bottomPadding4,
+ bottomPadding4,
+ bottomPadding4,
+ _bottomPadding,
+ ),
+ child: Stack(
+ alignment: Alignment.bottomCenter,
+ children: [
+ ValueListenableBuilder(
+ builder: (_, state, child) {
+ final replyTitle =
+ "${PackageStrings.replyTo} $_replyTo";
+ if (state.message.isNotEmpty) {
+ return widget.replyMessageBuilder
+ ?.call(context, state) ??
+ Container(
+ decoration: BoxDecoration(
+ color: widget.sendMessageConfig
+ ?.textFieldBackgroundColor ??
+ Colors.white,
+ borderRadius:
+ const BorderRadius.vertical(
+ top: Radius.circular(14),
+ ),
+ ),
+ margin: const EdgeInsets.only(
+ bottom: 17,
+ right: 0.4,
+ left: 0.4,
+ ),
+ padding: const EdgeInsets.fromLTRB(
+ leftPadding,
+ leftPadding,
+ leftPadding,
+ 30,
+ ),
+ child: Container(
+ margin:
+ const EdgeInsets.only(bottom: 2),
+ padding: const EdgeInsets.symmetric(
+ vertical: 4,
+ horizontal: 6,
+ ),
+ decoration: BoxDecoration(
+ color: widget.sendMessageConfig
+ ?.replyDialogColor ??
+ Colors.grey.shade200,
+ borderRadius:
+ BorderRadius.circular(12),
+ ),
+ child: Column(
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
children: [
- Expanded(
- child: Text(
- replyTitle,
- maxLines: 1,
- overflow:
- TextOverflow.ellipsis,
- style: TextStyle(
- color: widget
- .sendMessageConfig
- ?.replyTitleColor ??
- Colors.deepPurple,
- fontWeight: FontWeight.bold,
- letterSpacing: 0.25,
+ Row(
+ mainAxisAlignment:
+ MainAxisAlignment
+ .spaceBetween,
+ children: [
+ Expanded(
+ child: Text(
+ replyTitle,
+ maxLines: 1,
+ overflow:
+ TextOverflow.ellipsis,
+ style: TextStyle(
+ color: widget
+ .sendMessageConfig
+ ?.replyTitleColor ??
+ Colors.deepPurple,
+ fontWeight:
+ FontWeight.bold,
+ letterSpacing: 0.25,
+ ),
+ ),
+ ),
+ IconButton(
+ constraints:
+ const BoxConstraints(),
+ padding: EdgeInsets.zero,
+ icon: Icon(
+ Icons.close,
+ color: widget
+ .sendMessageConfig
+ ?.closeIconColor ??
+ Colors.black,
+ size: 16,
+ ),
+ onPressed: onCloseTap,
),
- ),
+ ],
),
- IconButton(
- constraints:
- const BoxConstraints(),
- padding: EdgeInsets.zero,
- icon: Icon(
- Icons.close,
- color: widget
- .sendMessageConfig
- ?.closeIconColor ??
- Colors.black,
- size: 16,
- ),
- onPressed: onCloseTap,
+ ReplyMessageView(
+ message: state,
+ customMessageReplyViewBuilder:
+ widget.messageConfig
+ ?.customMessageReplyViewBuilder,
+ sendMessageConfig:
+ widget.sendMessageConfig,
),
],
),
- ReplyMessageView(
- message: state,
- customMessageReplyViewBuilder: widget
- .messageConfig
- ?.customMessageReplyViewBuilder,
- sendMessageConfig:
- widget.sendMessageConfig,
- ),
- ],
- ),
- ),
- );
- } else {
- return const SizedBox.shrink();
- }
- },
- valueListenable: _replyMessage,
+ ),
+ );
+ } else {
+ return const SizedBox.shrink();
+ }
+ },
+ valueListenable: _replyMessage,
+ ),
+ ChatUITextField(
+ focusNode: _focusNode,
+ textEditingController: _textEditingController,
+ onPressed: _onPressed,
+ sendMessageConfig: widget.sendMessageConfig,
+ onRecordingComplete: _onRecordingComplete,
+ onImageSelected: _onImageSelected,
+ )
+ ],
),
- ChatUITextField(
- focusNode: _focusNode,
- textEditingController: _textEditingController,
- onPressed: _onPressed,
- sendMessageConfig: widget.sendMessageConfig,
- onRecordingComplete: _onRecordingComplete,
- onImageSelected: _onImageSelected,
- )
- ],
- ),
+ ),
+ ],
),
- ],
- ),
- ),
- );
+ )
+ ],
+ ),
+ );
}
void _onRecordingComplete(String? path) {
diff --git a/lib/src/widgets/suggestions/suggestion_item.dart b/lib/src/widgets/suggestions/suggestion_item.dart
new file mode 100644
index 00000000..752e7262
--- /dev/null
+++ b/lib/src/widgets/suggestions/suggestion_item.dart
@@ -0,0 +1,47 @@
+import 'package:chatview/src/extensions/extensions.dart';
+import 'package:chatview/src/models/models.dart';
+import 'package:flutter/material.dart';
+
+class SuggestionItem extends StatelessWidget {
+ const SuggestionItem({
+ super.key,
+ required this.suggestionItemData,
+ });
+
+ final SuggestionItemData suggestionItemData;
+
+ @override
+ Widget build(BuildContext context) {
+ final suggestionsConfig =
+ context.suggestionsConfig ?? ReplySuggestionsConfig();
+ final suggestionsListConfig = suggestionsConfig.itemConfig;
+ final theme = Theme.of(context);
+ return GestureDetector(
+ onTap: () {
+ suggestionsConfig.onTap?.call(suggestionItemData);
+ if (suggestionsConfig.autoDismissOnSelection) {
+ context.provide?.chatController.removeReplySuggestions();
+ }
+ },
+ child: Container(
+ padding: suggestionsListConfig?.padding ??
+ suggestionItemData.config?.padding ??
+ const EdgeInsets.all(6),
+ decoration: suggestionsListConfig?.decoration ??
+ suggestionItemData.config?.decoration ??
+ BoxDecoration(
+ color: Colors.white,
+ borderRadius: const BorderRadius.all(Radius.circular(8)),
+ border: Border.all(
+ color: theme.primaryColor,
+ ),
+ ),
+ child: Text(
+ suggestionItemData.text,
+ style: suggestionsListConfig?.textStyle ??
+ suggestionItemData.config?.textStyle,
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/src/widgets/suggestions/suggestion_list.dart b/lib/src/widgets/suggestions/suggestion_list.dart
new file mode 100644
index 00000000..dee7a593
--- /dev/null
+++ b/lib/src/widgets/suggestions/suggestion_list.dart
@@ -0,0 +1,93 @@
+import 'package:chatview/src/extensions/extensions.dart';
+import 'package:chatview/src/models/models.dart';
+import 'package:chatview/src/widgets/suggestions/suggestion_item.dart';
+import 'package:flutter/material.dart';
+
+class SuggestionList extends StatefulWidget {
+ const SuggestionList({
+ super.key,
+ required this.suggestions,
+ this.gap,
+ });
+
+ final List suggestions;
+ final double? gap;
+
+ @override
+ State createState() => _SuggestionListState();
+}
+
+class _SuggestionListState extends State
+ with SingleTickerProviderStateMixin {
+ AnimationController? _controller;
+
+ @override
+ void initState() {
+ super.initState();
+
+ _controller = AnimationController(
+ duration: const Duration(milliseconds: 200),
+ vsync: this,
+ );
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ if (!mounted) return;
+ final newSuggestions = provide?.chatController.newSuggestions;
+ newSuggestions?.addListener(() {
+ newSuggestions.value.isEmpty
+ ? _controller?.reverse()
+ : _controller?.forward();
+ });
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final suggestionsItemConfig = suggestionsConfig?.itemConfig;
+ final suggestionsListConfig =
+ suggestionsConfig?.listConfig ?? SuggestionListConfig();
+ return Container(
+ decoration: suggestionsListConfig.decoration,
+ child: SizeTransition(
+ sizeFactor: _controller!,
+ axisAlignment: -1.0,
+ fixedCrossAxisSizeFactor: 1,
+ child: Padding(
+ padding: suggestionsListConfig.padding ??
+ const EdgeInsets.only(top: 8.0, left: 8.0),
+ child: SingleChildScrollView(
+ scrollDirection: Axis.horizontal,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: List.generate(
+ widget.suggestions.length,
+ (index) {
+ final suggestion = widget.suggestions[index];
+ return suggestionsItemConfig?.customItemBuilder
+ ?.call(index, suggestion) ??
+ suggestion.config?.customItemBuilder
+ ?.call(index, suggestion) ??
+ Padding(
+ padding: EdgeInsets.only(
+ right: index == widget.suggestions.length
+ ? 0
+ : (suggestionsListConfig.itemSeparatorWidth),
+ ),
+ child: SuggestionItem(
+ suggestionItemData: suggestion,
+ ),
+ );
+ },
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ @override
+ void dispose() {
+ _controller?.dispose();
+ super.dispose();
+ }
+}
diff --git a/lib/src/widgets/suggestions/suggestions_config_inherited_widget.dart b/lib/src/widgets/suggestions/suggestions_config_inherited_widget.dart
new file mode 100644
index 00000000..2b4a95f1
--- /dev/null
+++ b/lib/src/widgets/suggestions/suggestions_config_inherited_widget.dart
@@ -0,0 +1,21 @@
+import 'package:chatview/src/models/suggestions_config.dart';
+import 'package:flutter/material.dart';
+import 'package:chatview/chatview.dart';
+
+/// This widget for alternative of excessive amount of passing arguments
+/// over widgets.
+class SuggestionsConfigIW extends InheritedWidget {
+ const SuggestionsConfigIW({
+ super.key,
+ required super.child,
+ this.suggestionsConfig,
+ });
+
+ final ReplySuggestionsConfig? suggestionsConfig;
+
+ static SuggestionsConfigIW? of(BuildContext context) =>
+ context.dependOnInheritedWidgetOfExactType();
+
+ @override
+ bool updateShouldNotify(covariant SuggestionsConfigIW oldWidget) => false;
+}