Skip to content

Draft: feat: 🌟 dynamic swipe; handle chat prev and next message; currentContext in ChatController; detect more emojis #187

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
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