From 1574f8b336f3b96d1fa563e6fc35c2d1710a4a68 Mon Sep 17 00:00:00 2001 From: elihaialgoaitech <139055716+elihaialgoaitech@users.noreply.github.com> Date: Wed, 17 Jan 2024 09:43:16 +0200 Subject: [PATCH 1/3] Add paramter of message width ratio --- lib/src/widgets/chat.dart | 51 +++++++++++++++------------------------ 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/lib/src/widgets/chat.dart b/lib/src/widgets/chat.dart index ab394f8c..d3e60040 100644 --- a/lib/src/widgets/chat.dart +++ b/lib/src/widgets/chat.dart @@ -28,9 +28,6 @@ import 'state/inherited_user.dart'; import 'typing_indicator.dart'; import 'unread_header.dart'; -/// Keep track of all the auto scroll indices by their respective message's id to allow animating to them. -final Map chatMessageAutoScrollIndexById = {}; - /// Entry widget, represents the complete chat. If you wrap it in [SafeArea] and /// it should be full screen, set [SafeArea]'s `bottom` to `false`. class Chat extends StatefulWidget { @@ -100,8 +97,7 @@ class Chat extends StatefulWidget { this.userAgent, this.useTopSafeAreaInset, this.videoMessageBuilder, - this.slidableMessageBuilder, - this.isLeftStatus = false, + this.messageWidthRatio = 0.72, }); /// See [Message.audioMessageBuilder]. @@ -109,7 +105,7 @@ class Chat extends StatefulWidget { audioMessageBuilder; /// See [Message.avatarBuilder]. - final Widget Function(types.User author)? avatarBuilder; + final Widget Function(String userId)? avatarBuilder; /// See [Message.bubbleBuilder]. final Widget Function( @@ -323,15 +319,8 @@ class Chat extends StatefulWidget { final Widget Function(types.VideoMessage, {required int messageWidth})? videoMessageBuilder; - /// See [Message.slidableMessageBuilder]. - final Widget Function(types.Message, Widget msgWidget)? - slidableMessageBuilder; - - /// See [Message.isLeftStatus]. - /// If true, status will be shown on the left side of the message. - /// If false, status will be shown on the right side of the message. - /// Default value is false. - final bool isLeftStatus; + /// Width ratio for message bubble. + final double messageWidthRatio; @override State createState() => ChatState(); @@ -339,7 +328,7 @@ class Chat extends StatefulWidget { /// [Chat] widget state. class ChatState extends State { - /// Used to get the correct auto scroll index from [chatMessageAutoScrollIndexById]. + /// Used to get the correct auto scroll index from [_autoScrollIndexById]. static const String _unreadHeaderId = 'unread_header_id'; List _chatMessages = []; @@ -348,6 +337,8 @@ class ChatState extends State { bool _hadScrolledToUnreadOnOpen = false; bool _isImageViewVisible = false; + /// Keep track of all the auto scroll indices by their respective message's id to allow animating to them. + final Map _autoScrollIndexById = {}; late final AutoScrollController _scrollController; @override @@ -361,7 +352,7 @@ class ChatState extends State { /// Scroll to the unread header. void scrollToUnreadHeader() { - final unreadHeaderIndex = chatMessageAutoScrollIndexById[_unreadHeaderId]; + final unreadHeaderIndex = _autoScrollIndexById[_unreadHeaderId]; if (unreadHeaderIndex != null) { _scrollController.scrollToIndex( unreadHeaderIndex, @@ -378,13 +369,13 @@ class ChatState extends State { Duration? highlightDuration, }) async { await _scrollController.scrollToIndex( - chatMessageAutoScrollIndexById[id]!, + _autoScrollIndexById[id]!, duration: scrollDuration ?? scrollAnimationDuration, preferPosition: AutoScrollPosition.middle, ); if (withHighlight) { await _scrollController.highlight( - chatMessageAutoScrollIndexById[id]!, + _autoScrollIndexById[id]!, highlightDuration: highlightDuration ?? const Duration(seconds: 3), ); } @@ -393,7 +384,7 @@ class ChatState extends State { /// Highlight the message with the specified [id]. void highlightMessage(String id, {Duration? duration}) => _scrollController.highlight( - chatMessageAutoScrollIndexById[id]!, + _autoScrollIndexById[id]!, highlightDuration: duration ?? const Duration(seconds: 3), ); @@ -465,12 +456,12 @@ class ChatState extends State { messageWidget = widget.systemMessageBuilder?.call(message) ?? SystemMessage(message: message.text); } else { - final maxWidth = widget.theme.messageMaxWidth; final messageWidth = widget.showUserAvatars && message.author.id != widget.user.id - ? min(constraints.maxWidth * 0.72, maxWidth).floor() - : min(constraints.maxWidth * 0.78, maxWidth).floor(); - final Widget msgWidget = Message( + ? min(constraints.maxWidth * widget.messageWidthRatio, 440).floor() + : min(constraints.maxWidth * widget.messageWidthRatio + 0.06, 440).floor(); + + messageWidget = Message( audioMessageBuilder: widget.audioMessageBuilder, avatarBuilder: widget.avatarBuilder, bubbleBuilder: widget.bubbleBuilder, @@ -505,7 +496,6 @@ class ChatState extends State { showAvatar: map['nextMessageInGroup'] == false, showName: map['showName'] == true, showStatus: map['showStatus'] == true, - isLeftStatus: widget.isLeftStatus, showUserAvatars: widget.showUserAvatars, textMessageBuilder: widget.textMessageBuilder, textMessageOptions: widget.textMessageOptions, @@ -513,9 +503,6 @@ class ChatState extends State { userAgent: widget.userAgent, videoMessageBuilder: widget.videoMessageBuilder, ); - messageWidget = widget.slidableMessageBuilder == null - ? msgWidget - : widget.slidableMessageBuilder!(message, msgWidget); } return AutoScrollTag( @@ -553,16 +540,16 @@ class ChatState extends State { widget.onPreviewDataFetched?.call(message, previewData); } - /// Updates the [chatMessageAutoScrollIndexById] mapping with the latest messages. + /// Updates the [_autoScrollIndexById] mapping with the latest messages. void _refreshAutoScrollMapping() { - chatMessageAutoScrollIndexById.clear(); + _autoScrollIndexById.clear(); var i = 0; for (final object in _chatMessages) { if (object is UnreadHeaderData) { - chatMessageAutoScrollIndexById[_unreadHeaderId] = i; + _autoScrollIndexById[_unreadHeaderId] = i; } else if (object is Map) { final message = object['message']! as types.Message; - chatMessageAutoScrollIndexById[message.id] = i; + _autoScrollIndexById[message.id] = i; } i++; } From d12583ca6735a12c4cabdeb152d71083a861d879 Mon Sep 17 00:00:00 2001 From: elihaialgoaitech <139055716+elihaialgoaitech@users.noreply.github.com> Date: Wed, 17 Jan 2024 09:47:26 +0200 Subject: [PATCH 2/3] Update chat.dart --- lib/src/widgets/chat.dart | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/lib/src/widgets/chat.dart b/lib/src/widgets/chat.dart index d3e60040..d16e4c08 100644 --- a/lib/src/widgets/chat.dart +++ b/lib/src/widgets/chat.dart @@ -28,6 +28,9 @@ import 'state/inherited_user.dart'; import 'typing_indicator.dart'; import 'unread_header.dart'; +/// Keep track of all the auto scroll indices by their respective message's id to allow animating to them. +final Map chatMessageAutoScrollIndexById = {}; + /// Entry widget, represents the complete chat. If you wrap it in [SafeArea] and /// it should be full screen, set [SafeArea]'s `bottom` to `false`. class Chat extends StatefulWidget { @@ -97,6 +100,7 @@ class Chat extends StatefulWidget { this.userAgent, this.useTopSafeAreaInset, this.videoMessageBuilder, + this.slidableMessageBuilder, this.messageWidthRatio = 0.72, }); @@ -105,7 +109,7 @@ class Chat extends StatefulWidget { audioMessageBuilder; /// See [Message.avatarBuilder]. - final Widget Function(String userId)? avatarBuilder; + final Widget Function(types.User author)? avatarBuilder; /// See [Message.bubbleBuilder]. final Widget Function( @@ -319,6 +323,10 @@ class Chat extends StatefulWidget { final Widget Function(types.VideoMessage, {required int messageWidth})? videoMessageBuilder; + /// See [Message.slidableMessageBuilder]. + final Widget Function(types.Message, Widget msgWidget)? + slidableMessageBuilder; + /// Width ratio for message bubble. final double messageWidthRatio; @@ -328,7 +336,7 @@ class Chat extends StatefulWidget { /// [Chat] widget state. class ChatState extends State { - /// Used to get the correct auto scroll index from [_autoScrollIndexById]. + /// Used to get the correct auto scroll index from [chatMessageAutoScrollIndexById]. static const String _unreadHeaderId = 'unread_header_id'; List _chatMessages = []; @@ -337,8 +345,6 @@ class ChatState extends State { bool _hadScrolledToUnreadOnOpen = false; bool _isImageViewVisible = false; - /// Keep track of all the auto scroll indices by their respective message's id to allow animating to them. - final Map _autoScrollIndexById = {}; late final AutoScrollController _scrollController; @override @@ -352,7 +358,7 @@ class ChatState extends State { /// Scroll to the unread header. void scrollToUnreadHeader() { - final unreadHeaderIndex = _autoScrollIndexById[_unreadHeaderId]; + final unreadHeaderIndex = chatMessageAutoScrollIndexById[_unreadHeaderId]; if (unreadHeaderIndex != null) { _scrollController.scrollToIndex( unreadHeaderIndex, @@ -369,13 +375,13 @@ class ChatState extends State { Duration? highlightDuration, }) async { await _scrollController.scrollToIndex( - _autoScrollIndexById[id]!, + chatMessageAutoScrollIndexById[id]!, duration: scrollDuration ?? scrollAnimationDuration, preferPosition: AutoScrollPosition.middle, ); if (withHighlight) { await _scrollController.highlight( - _autoScrollIndexById[id]!, + chatMessageAutoScrollIndexById[id]!, highlightDuration: highlightDuration ?? const Duration(seconds: 3), ); } @@ -384,7 +390,7 @@ class ChatState extends State { /// Highlight the message with the specified [id]. void highlightMessage(String id, {Duration? duration}) => _scrollController.highlight( - _autoScrollIndexById[id]!, + chatMessageAutoScrollIndexById[id]!, highlightDuration: duration ?? const Duration(seconds: 3), ); @@ -459,9 +465,8 @@ class ChatState extends State { final messageWidth = widget.showUserAvatars && message.author.id != widget.user.id ? min(constraints.maxWidth * widget.messageWidthRatio, 440).floor() - : min(constraints.maxWidth * widget.messageWidthRatio + 0.06, 440).floor(); - - messageWidget = Message( + : min(constraints.maxWidth * (widget.messageWidthRatio + 0.06), 440).floor(); + final Widget msgWidget = Message( audioMessageBuilder: widget.audioMessageBuilder, avatarBuilder: widget.avatarBuilder, bubbleBuilder: widget.bubbleBuilder, @@ -503,6 +508,9 @@ class ChatState extends State { userAgent: widget.userAgent, videoMessageBuilder: widget.videoMessageBuilder, ); + messageWidget = widget.slidableMessageBuilder == null + ? msgWidget + : widget.slidableMessageBuilder!(message, msgWidget); } return AutoScrollTag( @@ -540,16 +548,16 @@ class ChatState extends State { widget.onPreviewDataFetched?.call(message, previewData); } - /// Updates the [_autoScrollIndexById] mapping with the latest messages. + /// Updates the [chatMessageAutoScrollIndexById] mapping with the latest messages. void _refreshAutoScrollMapping() { - _autoScrollIndexById.clear(); + chatMessageAutoScrollIndexById.clear(); var i = 0; for (final object in _chatMessages) { if (object is UnreadHeaderData) { - _autoScrollIndexById[_unreadHeaderId] = i; + chatMessageAutoScrollIndexById[_unreadHeaderId] = i; } else if (object is Map) { final message = object['message']! as types.Message; - _autoScrollIndexById[message.id] = i; + chatMessageAutoScrollIndexById[message.id] = i; } i++; } From e7f001102c0c52aede14fbbbd880de201614416b Mon Sep 17 00:00:00 2001 From: elihaialgoaitech <139055716+elihaialgoaitech@users.noreply.github.com> Date: Wed, 17 Jan 2024 09:50:26 +0200 Subject: [PATCH 3/3] Update chat.dart --- lib/src/widgets/chat.dart | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/src/widgets/chat.dart b/lib/src/widgets/chat.dart index d16e4c08..e1f130d1 100644 --- a/lib/src/widgets/chat.dart +++ b/lib/src/widgets/chat.dart @@ -101,6 +101,7 @@ class Chat extends StatefulWidget { this.useTopSafeAreaInset, this.videoMessageBuilder, this.slidableMessageBuilder, + this.isLeftStatus = false, this.messageWidthRatio = 0.72, }); @@ -326,6 +327,12 @@ class Chat extends StatefulWidget { /// See [Message.slidableMessageBuilder]. final Widget Function(types.Message, Widget msgWidget)? slidableMessageBuilder; + + /// See [Message.isLeftStatus]. + /// If true, status will be shown on the left side of the message. + /// If false, status will be shown on the right side of the message. + /// Default value is false. + final bool isLeftStatus; /// Width ratio for message bubble. final double messageWidthRatio; @@ -462,10 +469,11 @@ class ChatState extends State { messageWidget = widget.systemMessageBuilder?.call(message) ?? SystemMessage(message: message.text); } else { + final maxWidth = widget.theme.messageMaxWidth; final messageWidth = widget.showUserAvatars && message.author.id != widget.user.id - ? min(constraints.maxWidth * widget.messageWidthRatio, 440).floor() - : min(constraints.maxWidth * (widget.messageWidthRatio + 0.06), 440).floor(); + ? min(constraints.maxWidth * widget.messageWidthRatio, maxWidth).floor() + : min(constraints.maxWidth * (widget.messageWidthRatio + 0.06), maxWidth).floor(); final Widget msgWidget = Message( audioMessageBuilder: widget.audioMessageBuilder, avatarBuilder: widget.avatarBuilder, @@ -501,6 +509,7 @@ class ChatState extends State { showAvatar: map['nextMessageInGroup'] == false, showName: map['showName'] == true, showStatus: map['showStatus'] == true, + isLeftStatus: widget.isLeftStatus, showUserAvatars: widget.showUserAvatars, textMessageBuilder: widget.textMessageBuilder, textMessageOptions: widget.textMessageOptions,