mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-19 02:43:50 +02:00
feat: add chatMessageBuilder to the chatoptions to override default behavior
With the chatMessageBuilder it is possible to run a null whenever you still want to use the default but only want to update the chat in very specific cases. I also slightly refactored the chat_detail_screen.dart to remove duplicate code and make it more readable
This commit is contained in:
parent
7a30621ab9
commit
d60917028a
3 changed files with 202 additions and 225 deletions
|
@ -1,5 +1,6 @@
|
||||||
## 5.0.0 - WIP
|
## 5.0.0 - WIP
|
||||||
- Get the color for the imagepicker from the Theme's primaryColor
|
- Get the color for the imagepicker from the Theme's primaryColor
|
||||||
|
- Added chatMessageBuilder to the userstory configuration to customize the chat messages
|
||||||
|
|
||||||
## 4.0.0
|
## 4.0.0
|
||||||
- Move to the new user story architecture
|
- Move to the new user story architecture
|
||||||
|
|
|
@ -17,6 +17,7 @@ class ChatBuilders {
|
||||||
this.newChatButtonBuilder,
|
this.newChatButtonBuilder,
|
||||||
this.noUsersPlaceholderBuilder,
|
this.noUsersPlaceholderBuilder,
|
||||||
this.chatTitleBuilder,
|
this.chatTitleBuilder,
|
||||||
|
this.chatMessageBuilder,
|
||||||
this.usernameBuilder,
|
this.usernameBuilder,
|
||||||
this.loadingWidgetBuilder,
|
this.loadingWidgetBuilder,
|
||||||
});
|
});
|
||||||
|
@ -62,6 +63,9 @@ class ChatBuilders {
|
||||||
/// The chat title builder
|
/// The chat title builder
|
||||||
final Widget Function(String chatTitle)? chatTitleBuilder;
|
final Widget Function(String chatTitle)? chatTitleBuilder;
|
||||||
|
|
||||||
|
/// The chat message builder
|
||||||
|
final ChatMessageBuilder? chatMessageBuilder;
|
||||||
|
|
||||||
/// The username builder
|
/// The username builder
|
||||||
final Widget Function(String userFullName)? usernameBuilder;
|
final Widget Function(String userFullName)? usernameBuilder;
|
||||||
|
|
||||||
|
@ -108,6 +112,17 @@ typedef ContainerBuilder = Widget Function(
|
||||||
Widget child,
|
Widget child,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// The chat message builder
|
||||||
|
/// This builder is used to override the default chat message widget
|
||||||
|
/// If null is returned, the default chat message widget will be used so you can
|
||||||
|
/// override for specific cases
|
||||||
|
/// [previousMessage] is the previous message in the chat
|
||||||
|
typedef ChatMessageBuilder = Widget? Function(
|
||||||
|
BuildContext context,
|
||||||
|
MessageModel message,
|
||||||
|
MessageModel? previousMessage,
|
||||||
|
);
|
||||||
|
|
||||||
/// The group avatar builder
|
/// The group avatar builder
|
||||||
typedef GroupAvatarBuilder = Widget Function(
|
typedef GroupAvatarBuilder = Widget Function(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
|
|
|
@ -86,15 +86,14 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (widget.chatOptions.builders.baseScreenBuilder == null) {
|
var appBar = _AppBar(
|
||||||
return Scaffold(
|
|
||||||
appBar: _AppBar(
|
|
||||||
chatTitle: chatTitle,
|
chatTitle: chatTitle,
|
||||||
chatOptions: widget.chatOptions,
|
chatOptions: widget.chatOptions,
|
||||||
onPressChatTitle: widget.onPressChatTitle,
|
onPressChatTitle: widget.onPressChatTitle,
|
||||||
chatModel: widget.chat,
|
chatModel: widget.chat,
|
||||||
),
|
);
|
||||||
body: _Body(
|
|
||||||
|
var body = _Body(
|
||||||
chatService: widget.chatService,
|
chatService: widget.chatService,
|
||||||
options: widget.chatOptions,
|
options: widget.chatOptions,
|
||||||
chat: widget.chat,
|
chat: widget.chat,
|
||||||
|
@ -103,29 +102,20 @@ class _ChatDetailScreenState extends State<ChatDetailScreen> {
|
||||||
onUploadImage: widget.onUploadImage,
|
onUploadImage: widget.onUploadImage,
|
||||||
onMessageSubmit: widget.onMessageSubmit,
|
onMessageSubmit: widget.onMessageSubmit,
|
||||||
onReadChat: widget.onReadChat,
|
onReadChat: widget.onReadChat,
|
||||||
),
|
);
|
||||||
|
|
||||||
|
if (widget.chatOptions.builders.baseScreenBuilder == null) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: appBar,
|
||||||
|
body: body,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return widget.chatOptions.builders.baseScreenBuilder!.call(
|
return widget.chatOptions.builders.baseScreenBuilder!.call(
|
||||||
context,
|
context,
|
||||||
widget.mapScreenType,
|
widget.mapScreenType,
|
||||||
_AppBar(
|
appBar,
|
||||||
chatTitle: chatTitle,
|
body,
|
||||||
chatOptions: widget.chatOptions,
|
|
||||||
onPressChatTitle: widget.onPressChatTitle,
|
|
||||||
chatModel: widget.chat,
|
|
||||||
),
|
|
||||||
_Body(
|
|
||||||
chatService: widget.chatService,
|
|
||||||
options: widget.chatOptions,
|
|
||||||
chat: widget.chat,
|
|
||||||
currentUserId: widget.userId,
|
|
||||||
onPressUserProfile: widget.onPressUserProfile,
|
|
||||||
onUploadImage: widget.onUploadImage,
|
|
||||||
onMessageSubmit: widget.onMessageSubmit,
|
|
||||||
onReadChat: widget.onReadChat,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,27 +365,32 @@ class _ChatBottomState extends State<_ChatBottom> {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
|
|
||||||
_textEditingController.addListener(() {
|
_textEditingController.addListener(() {
|
||||||
if (_textEditingController.text.isEmpty) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isTyping = false;
|
_isTyping = _textEditingController.text.isNotEmpty;
|
||||||
});
|
});
|
||||||
} else {
|
});
|
||||||
|
|
||||||
|
Future<void> sendMessage() async {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isTyping = true;
|
_isSending = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
var value = _textEditingController.text;
|
||||||
|
if (value.isNotEmpty) {
|
||||||
|
await widget.onMessageSubmit(value);
|
||||||
|
_textEditingController.clear();
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_isSending = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
return Padding(
|
Future<void> Function()? onClickSendMessage;
|
||||||
padding: const EdgeInsets.symmetric(
|
if (_isTyping && !_isSending) {
|
||||||
horizontal: 12,
|
onClickSendMessage = () async => sendMessage();
|
||||||
vertical: 16,
|
}
|
||||||
),
|
|
||||||
child: SizedBox(
|
var messageSendButtons = Row(
|
||||||
height: 45,
|
|
||||||
child: widget.options.builders.messageInputBuilder?.call(
|
|
||||||
context,
|
|
||||||
_textEditingController,
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
@ -409,30 +404,25 @@ class _ChatBottomState extends State<_ChatBottom> {
|
||||||
IconButton(
|
IconButton(
|
||||||
disabledColor: widget.options.iconDisabledColor,
|
disabledColor: widget.options.iconDisabledColor,
|
||||||
color: widget.options.iconEnabledColor,
|
color: widget.options.iconEnabledColor,
|
||||||
onPressed: _isTyping && !_isSending
|
onPressed: onClickSendMessage,
|
||||||
? () async {
|
|
||||||
setState(() {
|
|
||||||
_isSending = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
var value = _textEditingController.text;
|
|
||||||
|
|
||||||
if (value.isNotEmpty) {
|
|
||||||
await widget.onMessageSubmit(value);
|
|
||||||
_textEditingController.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_isSending = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.send,
|
Icons.send,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 16,
|
||||||
),
|
),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 45,
|
||||||
|
child: widget.options.builders.messageInputBuilder?.call(
|
||||||
|
context,
|
||||||
|
_textEditingController,
|
||||||
|
messageSendButtons,
|
||||||
widget.options.translations,
|
widget.options.translations,
|
||||||
) ??
|
) ??
|
||||||
TextField(
|
TextField(
|
||||||
|
@ -468,43 +458,7 @@ class _ChatBottomState extends State<_ChatBottom> {
|
||||||
),
|
),
|
||||||
borderSide: BorderSide.none,
|
borderSide: BorderSide.none,
|
||||||
),
|
),
|
||||||
suffixIcon: Row(
|
suffixIcon: messageSendButtons,
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: widget.onPressSelectImage,
|
|
||||||
icon: Icon(
|
|
||||||
Icons.image_outlined,
|
|
||||||
color: widget.options.iconEnabledColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
disabledColor: widget.options.iconDisabledColor,
|
|
||||||
color: widget.options.iconEnabledColor,
|
|
||||||
onPressed: _isTyping && !_isSending
|
|
||||||
? () async {
|
|
||||||
setState(() {
|
|
||||||
_isSending = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
var value = _textEditingController.text;
|
|
||||||
|
|
||||||
if (value.isNotEmpty) {
|
|
||||||
await widget.onMessageSubmit(value);
|
|
||||||
_textEditingController.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_isSending = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.send,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -557,7 +511,12 @@ class _ChatBubbleState extends State<_ChatBubble> {
|
||||||
|
|
||||||
var user = snapshot.data!;
|
var user = snapshot.data!;
|
||||||
|
|
||||||
return Padding(
|
return widget.options.builders.chatMessageBuilder?.call(
|
||||||
|
context,
|
||||||
|
widget.message,
|
||||||
|
widget.previousMessage,
|
||||||
|
) ??
|
||||||
|
Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
top: isNewDate || isSameSender ? 25.0 : 0,
|
top: isNewDate || isSameSender ? 25.0 : 0,
|
||||||
),
|
),
|
||||||
|
@ -584,8 +543,9 @@ class _ChatBubbleState extends State<_ChatBubble> {
|
||||||
user: User(
|
user: User(
|
||||||
firstName: user.firstName,
|
firstName: user.firstName,
|
||||||
lastName: user.lastName,
|
lastName: user.lastName,
|
||||||
imageUrl:
|
imageUrl: user.imageUrl != ""
|
||||||
user.imageUrl != "" ? user.imageUrl : null,
|
? user.imageUrl
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
size: 40,
|
size: 40,
|
||||||
),
|
),
|
||||||
|
@ -613,7 +573,8 @@ class _ChatBubbleState extends State<_ChatBubble> {
|
||||||
user.fullname ?? "",
|
user.fullname ?? "",
|
||||||
) ??
|
) ??
|
||||||
Text(
|
Text(
|
||||||
user.fullname ?? translations.anonymousUser,
|
user.fullname ??
|
||||||
|
translations.anonymousUser,
|
||||||
style: theme.textTheme.titleMedium,
|
style: theme.textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue