Skip to content
Draft
6 changes: 0 additions & 6 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,6 @@ class _ChatScreenState extends State<ChatScreen> {
cameraIconColor: theme.cameraIconColor,
galleryIconColor: theme.galleryIconColor,
),
replyMessageColor: theme.replyMessageColor,
defaultSendButtonColor: theme.sendButtonColor,
replyDialogColor: theme.replyDialogColor,
replyTitleColor: theme.replyTitleColor,
textFieldBackgroundColor: theme.textFieldBackgroundColor,
closeIconColor: theme.closeIconColor,
textFieldConfig: TextFieldConfiguration(
onMessageTyping: (status) {
/// Do with status
Expand Down
22 changes: 15 additions & 7 deletions lib/src/controller/chat_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,17 @@ class ChatController {
StreamController<List<Message>> messageStreamController = StreamController();

/// Used to dispose stream.
void dispose() => messageStreamController.close();
void dispose() {
_replySuggestion.dispose();
messageStreamController.close();
}

/// Used to add message in message list.
void addMessage(Message message) {
initialMessageList.add(message);
messageStreamController.sink.add(initialMessageList);
if (!messageStreamController.isClosed) {
messageStreamController.sink.add(initialMessageList);
}
}

/// Used to add reply suggestions.
Expand Down Expand Up @@ -136,11 +141,14 @@ class ChatController {
/// Function to scroll to last messages in chat view
void scrollToLastMessage() => Timer(
const Duration(milliseconds: 300),
() => scrollController.animateTo(
scrollController.position.minScrollExtent,
curve: Curves.easeIn,
duration: const Duration(milliseconds: 300),
),
() {
if (!scrollController.hasClients) return;
scrollController.animateTo(
scrollController.position.minScrollExtent,
curve: Curves.easeIn,
duration: const Duration(milliseconds: 300),
);
},
);

/// Function for loading data while pagination.
Expand Down
3 changes: 2 additions & 1 deletion lib/src/extensions/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ extension ChatViewStateTitleExtension on String? {

/// Extension on State for accessing inherited widget.
extension StatefulWidgetExtension on State {
ChatViewInheritedWidget? get provide => ChatViewInheritedWidget.of(context);
ChatViewInheritedWidget? get provide =>
mounted ? ChatViewInheritedWidget.of(context) : null;

ReplySuggestionsConfig? get suggestionsConfig =>
SuggestionsConfigIW.of(context)?.suggestionsConfig;
Expand Down
8 changes: 8 additions & 0 deletions lib/src/models/chat_bubble_configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ class ChatBubbleConfiguration {
/// Used for giving maximum width of chat bubble.
final double? maxWidth;

/// Used for insetting the messages from the bottom according to text field height.
final double? additionalBottomInsetIfMessageIsLast;

/// Used for insetting the messages from the bottom more if the user is about to reply to another message.
final double? additionalBottomInsetIfReplyHeaderIsThere;

/// Provides callback when user long press on chat bubble.
final Duration? longPressAnimationDuration;

Expand All @@ -53,6 +59,8 @@ class ChatBubbleConfiguration {
this.padding,
this.margin,
this.maxWidth,
this.additionalBottomInsetIfMessageIsLast,
this.additionalBottomInsetIfReplyHeaderIsThere,
this.longPressAnimationDuration,
this.inComingChatBubbleConfig,
this.outgoingChatBubbleConfig,
Expand Down
29 changes: 23 additions & 6 deletions lib/src/models/message_configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,47 @@
*/
import 'package:chatview/src/models/models.dart';
import 'package:chatview/src/models/voice_message_configuration.dart';
import 'package:chatview/src/widgets/message_view.dart';
import 'package:flutter/material.dart';

import '../values/typedefs.dart';

class MessageConfiguration {
/// Provides configuration of image message appearance.
final ImageMessageConfiguration? imageMessageConfig;

/// Provides configuration of image message appearance.
/// Provides configuration of message reaction.
final MessageReactionConfiguration? messageReactionConfig;

/// Provides configuration of emoji messages appearance.
final EmojiMessageConfiguration? emojiMessageConfig;

/// Provides builder to create view for custom messages.
final Widget Function(Message)? customMessageBuilder;
/// Provides configuration of image message appearance.
final ImageMessageConfiguration? imageMessageConfig;

/// Configurations for voice message bubble
final VoiceMessageConfiguration? voiceMessageConfig;

/// Provides builder to create view for emoji messages.
final Widget Function(MessageView)? emojiMessageBuilder;

/// Provides builder to create view for image messages.
final Widget Function(MessageView)? imageMessageBuilder;

/// Provides builder to create view for text messages.
final Widget Function(MessageView)? textMessageBuilder;

/// Provides builder to create view for voice messages.
final Widget Function(MessageView)? voiceMessageBuilder;

/// Provides builder to create view for custom messages.
final Widget Function(MessageView)? customMessageBuilder;

/// To customize reply view for custom message type
final CustomMessageReplyViewBuilder? customMessageReplyViewBuilder;

const MessageConfiguration({
this.imageMessageBuilder,
this.textMessageBuilder,
this.emojiMessageBuilder,
this.voiceMessageBuilder,
this.imageMessageConfig,
this.messageReactionConfig,
this.emojiMessageConfig,
Expand Down
4 changes: 2 additions & 2 deletions lib/src/models/profile_circle.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ProfileCircleConfiguration {
final double? bottomPadding;

/// Used for give circle radius to profile circle
final double? circleRadius;
final double circleRadius;

/// Provides callback when user tap on profile circle.
final void Function(ChatUser)? onAvatarTap;
Expand All @@ -62,11 +62,11 @@ class ProfileCircleConfiguration {
networkImageProgressIndicatorBuilder;

const ProfileCircleConfiguration({
this.circleRadius = 12,
this.onAvatarTap,
this.padding,
this.profileImageUrl,
this.bottomPadding,
this.circleRadius,
this.onAvatarLongPress,
this.imageType = ImageType.network,
this.defaultAvatarImage = profileImage,
Expand Down
85 changes: 46 additions & 39 deletions lib/src/models/send_message_configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import '../values/typedefs.dart';

class SendMessageConfiguration {
/// Used to give background color to text field.
final Color? textFieldBackgroundColor;
final Color textFieldBackgroundColor;

/// Used to give color to send button.
final Color? defaultSendButtonColor;
Expand All @@ -39,16 +39,16 @@ class SendMessageConfiguration {
final Widget? sendButtonIcon;

/// Used to give reply dialog color.
final Color? replyDialogColor;
final Color replyDialogColor;

/// Used to give color to title of reply pop-up.
final Color? replyTitleColor;
final Color replyTitleColor;

/// Used to give color to reply message.
final Color? replyMessageColor;
final Color replyMessageColor;

/// Used to give color to close icon in reply pop-up.
final Color? closeIconColor;
final Color closeIconColor;

/// Provides configuration of image picker functionality.
final ImagePickerIconsConfiguration? imagePickerIconsConfig;
Expand All @@ -57,7 +57,7 @@ class SendMessageConfiguration {
final ImagePickerConfiguration? imagePickerConfiguration;

/// Provides configuration of text field.
final TextFieldConfiguration? textFieldConfig;
final TextFieldConfiguration textFieldConfig;

/// Enable/disable voice recording. Enabled by default.
final bool allowRecordingVoice;
Expand All @@ -77,20 +77,23 @@ class SendMessageConfiguration {
/// Configuration for cancel voice recording
final CancelRecordConfiguration? cancelRecordConfiguration;

bool get allowImageSending =>
enableCameraImagePicker || enableGalleryImagePicker;

const SendMessageConfiguration({
this.textFieldConfig,
this.textFieldBackgroundColor,
this.textFieldConfig = const TextFieldConfiguration(),
this.textFieldBackgroundColor = Colors.white,
this.imagePickerIconsConfig,
this.imagePickerConfiguration,
this.defaultSendButtonColor,
this.sendButtonIcon,
this.replyDialogColor,
this.replyTitleColor,
this.replyMessageColor,
this.closeIconColor,
this.replyDialogColor = const Color.fromRGBO(238, 238, 238, 1),
this.replyTitleColor = Colors.deepPurple,
this.replyMessageColor = Colors.black,
this.closeIconColor = Colors.black,
this.allowRecordingVoice = true,
this.enableCameraImagePicker = true,
this.enableGalleryImagePicker = true,
this.enableCameraImagePicker = true,
this.voiceRecordingConfiguration,
this.micIconColor,
this.cancelRecordConfiguration,
Expand Down Expand Up @@ -118,6 +121,32 @@ class ImagePickerIconsConfiguration {
});
}

class ImagePickerConfiguration {
/// Used to give max width of image.
final double? maxWidth;

/// Used to give max height of image.
final double? maxHeight;

/// Used to give image quality.
final int? imageQuality;

/// Preferred camera device to pick image from.
final CameraDevice? preferredCameraDevice;

/// Callback when image is picked from camera or gallery,
/// we can perform our task on image like adding crop options and return new image path
final Future<String?> Function(String? path)? onImagePicked;

const ImagePickerConfiguration({
this.maxWidth,
this.maxHeight,
this.imageQuality,
this.preferredCameraDevice,
this.onImagePicked,
});
}

class TextFieldConfiguration {
/// Used to give max lines in text field.
final int? maxLines;
Expand All @@ -140,6 +169,9 @@ class TextFieldConfiguration {
/// Used to give text style of actual text in text field.
final TextStyle? textStyle;

/// Used to give a border to the text field.
final BoxBorder? border;

/// Used to give border radius in text field.
final BorderRadius? borderRadius;

Expand Down Expand Up @@ -171,6 +203,7 @@ class TextFieldConfiguration {
const TextFieldConfiguration({
this.contentPadding,
this.maxLines,
this.border,
this.borderRadius,
this.hintText,
this.hintStyle,
Expand All @@ -187,32 +220,6 @@ class TextFieldConfiguration {
});
}

class ImagePickerConfiguration {
/// Used to give max width of image.
final double? maxWidth;

/// Used to give max height of image.
final double? maxHeight;

/// Used to give image quality.
final int? imageQuality;

/// Preferred camera device to pick image from.
final CameraDevice? preferredCameraDevice;

/// Callback when image is picked from camera or gallery,
/// we can perform our task on image like adding crop options and return new image path
final Future<String?> Function(String? path)? onImagePicked;

const ImagePickerConfiguration({
this.maxWidth,
this.maxHeight,
this.imageQuality,
this.preferredCameraDevice,
this.onImagePicked,
});
}

class VoiceRecordingConfiguration {
/// Styling configuration for the recorder widget as well as
/// configuring the audio recording quality.
Expand Down
17 changes: 6 additions & 11 deletions lib/src/models/swipe_to_reply_configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,20 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import 'package:chatview/chatview.dart';
import 'package:flutter/material.dart';

class SwipeToReplyConfiguration {
/// Used to give color of reply icon while swipe to reply.
final Color? replyIconColor;

/// Used to give animation duration while swipe to reply.
final Duration? animationDuration;

/// Provides callback when user swipe chat bubble from left side.
final void Function(String message, String sendBy)? onLeftSwipe;

/// Provides callback when user swipe chat bubble from right side.
final void Function(String message, String sendBy)? onRightSwipe;
/// Provides callback when user wants to reply to a message.
/// If this function returns false, the reply initialization is
/// prevented.
final bool? Function(Message message)? onInitReply;

const SwipeToReplyConfiguration({
this.replyIconColor,
this.animationDuration,
this.onRightSwipe,
this.onLeftSwipe,
this.onInitReply,
});
}
Loading