diff --git a/packages/flutter_chat_view/lib/flutter_chat_view.dart b/packages/flutter_chat_view/lib/flutter_chat_view.dart index 056699e..1a5fd18 100644 --- a/packages/flutter_chat_view/lib/flutter_chat_view.dart +++ b/packages/flutter_chat_view/lib/flutter_chat_view.dart @@ -8,6 +8,7 @@ export "package:flutter_chat_interface/flutter_chat_interface.dart"; export "src/components/chat_row.dart"; export "src/config/chat_options.dart"; +export "src/config/chat_text_styles.dart"; export "src/config/chat_translations.dart"; export "src/screens/chat_detail_screen.dart"; export "src/screens/chat_profile_screen.dart"; diff --git a/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart b/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart index 395bffd..7b10779 100644 --- a/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart +++ b/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart @@ -14,6 +14,7 @@ class ChatDetailRow extends StatefulWidget { required this.message, required this.userAvatarBuilder, required this.onPressUserProfile, + required this.options, this.usernameBuilder, this.previousMessage, this.showTime = false, @@ -37,16 +38,17 @@ class ChatDetailRow extends StatefulWidget { /// Flag indicating whether to show the time. final bool showTime; + final ChatOptions options; + @override State createState() => _ChatDetailRowState(); } class _ChatDetailRowState extends State { - final DateFormatter _dateFormatter = DateFormatter(); - @override Widget build(BuildContext context) { var theme = Theme.of(context); + var dateFormatter = DateFormatter(options: widget.options); var isNewDate = widget.previousMessage != null && widget.message.timestamp.day != widget.previousMessage?.timestamp.day; @@ -103,17 +105,20 @@ class _ChatDetailRowState extends State { Text( widget.message.sender.fullName ?? widget.translations.anonymousUser, - style: theme.textTheme.titleMedium, + style: widget + .options.textstyles?.senderTextStyle ?? + theme.textTheme.titleMedium, ), ), Padding( padding: const EdgeInsets.only(top: 5.0), child: Text( - _dateFormatter.format( + dateFormatter.format( date: widget.message.timestamp, - showFullDate: false, + showFullDate: true, ), - style: theme.textTheme.labelSmall, + style: widget.options.textstyles?.dateTextStyle ?? + theme.textTheme.labelSmall, ), ), ], @@ -129,7 +134,9 @@ class _ChatDetailRowState extends State { Flexible( child: Text( (widget.message as ChatTextMessageModel).text, - style: theme.textTheme.bodySmall, + style: widget.options.textstyles + ?.messageTextStyle ?? + theme.textTheme.bodySmall, ), ), if (widget.showTime && @@ -137,14 +144,16 @@ class _ChatDetailRowState extends State { !isNewDate && !hasHeader) Text( - _dateFormatter + dateFormatter .format( date: widget.message.timestamp, showFullDate: true, ) .split(" ") .last, - style: theme.textTheme.labelSmall, + style: widget + .options.textstyles?.dateTextStyle ?? + theme.textTheme.labelSmall, textAlign: TextAlign.end, ), ], diff --git a/packages/flutter_chat_view/lib/src/components/chat_row.dart b/packages/flutter_chat_view/lib/src/components/chat_row.dart index fd9414f..044051a 100644 --- a/packages/flutter_chat_view/lib/src/components/chat_row.dart +++ b/packages/flutter_chat_view/lib/src/components/chat_row.dart @@ -3,10 +3,12 @@ // SPDX-License-Identifier: BSD-3-Clause import "package:flutter/material.dart"; +import "package:flutter_chat_view/flutter_chat_view.dart"; class ChatRow extends StatelessWidget { const ChatRow({ required this.title, + required this.options, this.unreadMessages = 0, this.lastUsed, this.subTitle, @@ -29,6 +31,8 @@ class ChatRow extends StatelessWidget { /// The avatar associated with the chat. final Widget? avatar; + final ChatOptions options; + @override Widget build(BuildContext context) { var theme = Theme.of(context); @@ -49,7 +53,8 @@ class ChatRow extends StatelessWidget { title, maxLines: 1, overflow: TextOverflow.ellipsis, - style: theme.textTheme.titleMedium, + style: options.textstyles?.senderTextStyle ?? + theme.textTheme.titleMedium, ), if (subTitle != null) ...[ Padding( @@ -57,10 +62,14 @@ class ChatRow extends StatelessWidget { child: Text( subTitle!, style: unreadMessages > 0 - ? theme.textTheme.bodySmall!.copyWith( - fontWeight: FontWeight.w800, - ) - : theme.textTheme.bodySmall, + ? options.textstyles?.messageTextStyle!.copyWith( + fontWeight: FontWeight.w800, + ) ?? + theme.textTheme.bodySmall!.copyWith( + fontWeight: FontWeight.w800, + ) + : options.textstyles?.messageTextStyle ?? + theme.textTheme.bodySmall, overflow: TextOverflow.ellipsis, maxLines: 2, ), @@ -79,7 +88,8 @@ class ChatRow extends StatelessWidget { padding: const EdgeInsets.only(bottom: 4.0), child: Text( lastUsed!, - style: theme.textTheme.labelSmall, + style: options.textstyles?.dateTextStyle ?? + theme.textTheme.labelSmall, ), ), ], diff --git a/packages/flutter_chat_view/lib/src/config/chat_options.dart b/packages/flutter_chat_view/lib/src/config/chat_options.dart index b055bca..4eeba87 100644 --- a/packages/flutter_chat_view/lib/src/config/chat_options.dart +++ b/packages/flutter_chat_view/lib/src/config/chat_options.dart @@ -13,12 +13,19 @@ class ChatOptions { this.messageInputBuilder = _createMessageInput, this.chatRowContainerBuilder = _createChatRowContainer, this.imagePickerContainerBuilder = _createImagePickerContainer, - this.scaffoldBuilder = _createScaffold, + this.chatScreenScaffoldBuilder = _createChatScreenScaffold, + this.chatDetailScaffoldBuilder = _createChatScreenScaffold, + this.chatProfileScaffoldBuilder = _createChatScreenScaffold, + this.newChatScreenScaffoldBuilder = _createChatScreenScaffold, + this.newGroupChatScreenScaffoldBuilder = _createChatScreenScaffold, + this.newGroupChatOverviewScaffoldBuilder = _createChatScreenScaffold, this.userAvatarBuilder = _createUserAvatar, this.groupAvatarBuilder = _createGroupAvatar, this.noChatsPlaceholderBuilder = _createNoChatsPlaceholder, this.noUsersPlaceholderBuilder = _createNoUsersPlaceholder, this.paddingAroundChatList, + this.textstyles, + this.dateformat, }); /// Builder function for the new chat button. @@ -34,7 +41,23 @@ class ChatOptions { final ImagePickerContainerBuilder imagePickerContainerBuilder; /// Builder function for the scaffold containing the chat view. - final ScaffoldBuilder scaffoldBuilder; + final ScaffoldBuilder chatScreenScaffoldBuilder; + + /// Builder function for the scaffold containing the chat detail view. + final ScaffoldBuilder chatDetailScaffoldBuilder; + + /// Builder function for the scaffold containing the chat profile view. + final ScaffoldBuilder chatProfileScaffoldBuilder; + + /// Builder function for the scaffold containing the new chat view. + final ScaffoldBuilder newChatScreenScaffoldBuilder; + + /// Builder function for the scaffold containing the new groupchat view. + final ScaffoldBuilder newGroupChatScreenScaffoldBuilder; + + /// Builder function for the scaffold containing the new + /// groupchat overview view. + final ScaffoldBuilder newGroupChatOverviewScaffoldBuilder; /// Builder function for the user avatar. final UserAvatarBuilder userAvatarBuilder; @@ -50,6 +73,11 @@ class ChatOptions { /// The padding around the chat list. final EdgeInsets? paddingAroundChatList; + + final ChatTextStyles? textstyles; + + // ignore: avoid_positional_boolean_parameters + final String Function(bool showFullDate, DateTime date)? dateformat; } Widget _createNewChatButton( @@ -182,7 +210,7 @@ Widget _createImagePickerContainer( ); } -Scaffold _createScaffold( +Scaffold _createChatScreenScaffold( AppBar appbar, Widget body, Color backgroundColor, diff --git a/packages/flutter_chat_view/lib/src/config/chat_text_styles.dart b/packages/flutter_chat_view/lib/src/config/chat_text_styles.dart new file mode 100644 index 0000000..6ec6dd7 --- /dev/null +++ b/packages/flutter_chat_view/lib/src/config/chat_text_styles.dart @@ -0,0 +1,13 @@ +import "package:flutter/material.dart"; + +class ChatTextStyles { + ChatTextStyles({ + this.senderTextStyle, + this.messageTextStyle, + this.dateTextStyle, + }); + + final TextStyle? senderTextStyle; + final TextStyle? messageTextStyle; + final TextStyle? dateTextStyle; +} diff --git a/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart b/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart index 5241092..7b7faec 100644 --- a/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart @@ -106,6 +106,7 @@ class _ChatDetailScreenState extends State { for (var message in chatMessages) { detailRows.add( ChatDetailRow( + options: widget.options, showTime: true, message: message, translations: widget.translations, @@ -149,9 +150,8 @@ class _ChatDetailScreenState extends State { : (chatModel is PersonalChatModel) ? chatModel.user.firstName ?? widget.translations.anonymousUser : ""; - - return Scaffold( - appBar: AppBar( + return widget.options.chatDetailScaffoldBuilder( + AppBar( iconTheme: theme.appBarTheme.iconTheme ?? const IconThemeData(color: Colors.white), centerTitle: true, @@ -168,12 +168,11 @@ class _ChatDetailScreenState extends State { child: widget.chatTitleBuilder?.call(chatTitle) ?? Text( chatTitle, - style: theme.textTheme.headlineLarge, overflow: TextOverflow.ellipsis, ), ), ), - body: Stack( + Stack( children: [ Column( children: [ @@ -262,6 +261,7 @@ class _ChatDetailScreenState extends State { ], ], ), + theme.scaffoldBackgroundColor, ); }, ); diff --git a/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart b/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart index af87290..b16ff06 100644 --- a/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart @@ -77,9 +77,8 @@ class _ProfileScreenState extends State { imageUrl: data.imageUrl, ); } - - return Scaffold( - appBar: AppBar( + return widget.options.chatProfileScaffoldBuilder( + AppBar( iconTheme: theme.appBarTheme.iconTheme ?? const IconThemeData(color: Colors.white), title: Text( @@ -90,10 +89,9 @@ class _ProfileScreenState extends State { : (data is GroupChatModel) ? data.title : "", - style: theme.textTheme.headlineLarge, ), ), - body: snapshot.hasData + snapshot.hasData ? Stack( children: [ ListView( @@ -210,7 +208,10 @@ class _ProfileScreenState extends State { ], ], ) - : const Center(child: CircularProgressIndicator()), + : const Center( + child: CircularProgressIndicator(), + ), + theme.scaffoldBackgroundColor, ); }, ); diff --git a/packages/flutter_chat_view/lib/src/screens/chat_screen.dart b/packages/flutter_chat_view/lib/src/screens/chat_screen.dart index fefa53c..d1a387c 100644 --- a/packages/flutter_chat_view/lib/src/screens/chat_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/chat_screen.dart @@ -58,7 +58,6 @@ class ChatScreen extends StatefulWidget { } class _ChatScreenState extends State { - final DateFormatter _dateFormatter = DateFormatter(); bool _hasCalledOnNoChats = false; ScrollController controller = ScrollController(); bool showIndicator = false; @@ -73,13 +72,14 @@ class _ChatScreenState extends State { @override Widget build(BuildContext context) { + var dateFormatter = DateFormatter(options: widget.options); + var translations = widget.translations; var theme = Theme.of(context); - return widget.options.scaffoldBuilder( + return widget.options.chatScreenScaffoldBuilder( AppBar( title: Text( translations.chatsTitle, - style: theme.textTheme.headlineLarge, ), centerTitle: true, actions: [ @@ -202,14 +202,14 @@ class _ChatScreenState extends State { widget: widget, chat: chat, translations: translations, - dateFormatter: _dateFormatter, + dateFormatter: dateFormatter, ), ) : ChatListItem( widget: widget, chat: chat, translations: translations, - dateFormatter: _dateFormatter, + dateFormatter: dateFormatter, ), ), ), @@ -231,7 +231,7 @@ class _ChatScreenState extends State { ), ], ), - theme.colorScheme.surface, + theme.scaffoldBackgroundColor, ); } @@ -331,6 +331,7 @@ class ChatListItem extends StatelessWidget { child: widget.options.chatRowContainerBuilder( (chat is PersonalChatModel) ? ChatRow( + options: widget.options, unreadMessages: chat.unreadMessages ?? 0, avatar: widget.options.userAvatarBuilder( (chat as PersonalChatModel).user, @@ -351,6 +352,7 @@ class ChatListItem extends StatelessWidget { : null, ) : ChatRow( + options: widget.options, title: (chat as GroupChatModel).title, unreadMessages: chat.unreadMessages ?? 0, subTitle: chat.lastMessage != null diff --git a/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart b/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart index 54d68ca..0e7903e 100644 --- a/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart @@ -46,8 +46,8 @@ class _NewChatScreenState extends State { @override Widget build(BuildContext context) { var theme = Theme.of(context); - return Scaffold( - appBar: AppBar( + return widget.options.newChatScreenScaffoldBuilder( + AppBar( iconTheme: theme.appBarTheme.iconTheme ?? const IconThemeData(color: Colors.white), title: _buildSearchField(), @@ -55,7 +55,7 @@ class _NewChatScreenState extends State { _buildSearchIcon(), ], ), - body: Column( + Column( children: [ if (widget.showGroupChatButton && !_isSearching) ...[ Padding( @@ -106,6 +106,7 @@ class _NewChatScreenState extends State { ), ], ), + theme.scaffoldBackgroundColor, ); } @@ -135,7 +136,6 @@ class _NewChatScreenState extends State { ) : Text( widget.translations.newChatTitle, - style: theme.textTheme.headlineLarge, ); } diff --git a/packages/flutter_chat_view/lib/src/screens/new_group_chat_overview_screen.dart b/packages/flutter_chat_view/lib/src/screens/new_group_chat_overview_screen.dart index 5c6dbb2..168ce86 100644 --- a/packages/flutter_chat_view/lib/src/screens/new_group_chat_overview_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/new_group_chat_overview_screen.dart @@ -51,17 +51,16 @@ class _NewGroupChatOverviewScreenState }); } - return Scaffold( - appBar: AppBar( + return widget.options.newGroupChatOverviewScaffoldBuilder( + AppBar( iconTheme: theme.appBarTheme.iconTheme ?? const IconThemeData(color: Colors.white), backgroundColor: theme.appBarTheme.backgroundColor, title: Text( widget.translations.newGroupChatTitle, - style: theme.appBarTheme.titleTextStyle, ), ), - body: Stack( + Stack( children: [ SingleChildScrollView( child: Padding( @@ -286,7 +285,7 @@ class _NewGroupChatOverviewScreenState ), ], ), - // floatingActionButton: FloatingActionButton( + theme.scaffoldBackgroundColor, ); } diff --git a/packages/flutter_chat_view/lib/src/screens/new_group_chat_screen.dart b/packages/flutter_chat_view/lib/src/screens/new_group_chat_screen.dart index ddd34b3..b8b7be2 100644 --- a/packages/flutter_chat_view/lib/src/screens/new_group_chat_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/new_group_chat_screen.dart @@ -30,9 +30,8 @@ class _NewGroupChatScreenState extends State { @override Widget build(BuildContext context) { var theme = Theme.of(context); - return Scaffold( - backgroundColor: theme.colorScheme.surface, - appBar: AppBar( + return widget.options.newGroupChatScreenScaffoldBuilder( + AppBar( iconTheme: theme.appBarTheme.iconTheme ?? const IconThemeData(color: Colors.white), backgroundColor: theme.appBarTheme.backgroundColor, @@ -41,7 +40,7 @@ class _NewGroupChatScreenState extends State { _buildSearchIcon(), ], ), - body: FutureBuilder>( + FutureBuilder>( // ignore: discarded_futures future: widget.service.chatUserService.getAllUsers(), builder: (context, snapshot) { @@ -63,6 +62,7 @@ class _NewGroupChatScreenState extends State { return const SizedBox.shrink(); }, ), + theme.scaffoldBackgroundColor, ); } @@ -92,7 +92,6 @@ class _NewGroupChatScreenState extends State { ) : Text( widget.translations.newGroupChatButton, - style: theme.appBarTheme.titleTextStyle, ); } diff --git a/packages/flutter_chat_view/lib/src/services/date_formatter.dart b/packages/flutter_chat_view/lib/src/services/date_formatter.dart index 4d4f0c1..e1c4352 100644 --- a/packages/flutter_chat_view/lib/src/services/date_formatter.dart +++ b/packages/flutter_chat_view/lib/src/services/date_formatter.dart @@ -2,9 +2,14 @@ // // SPDX-License-Identifier: BSD-3-Clause +import "package:flutter_chat_view/flutter_chat_view.dart"; import "package:intl/intl.dart"; class DateFormatter { + DateFormatter({ + required this.options, + }); + final ChatOptions options; final _now = DateTime.now(); bool _isToday(DateTime date) => @@ -45,17 +50,20 @@ class DateFormatter { required DateTime date, bool showFullDate = false, }) { - if(showFullDate) { - return DateFormat("dd - MM - yyyy HH:mm").format(date); + if (options.dateformat != null) { + return options.dateformat!(showFullDate, date); } if (_isToday(date)) { - return DateFormat("HH:mm").format(date); + return DateFormat( + "HH:mm", + ).format(date); } else if (_isYesterday(date)) { return "yesterday"; } else if (_isThisYear(date)) { - return DateFormat("dd MMMM").format(date); + return DateFormat("dd-MM${showFullDate ? " HH:mm" : ""}").format(date); } else { - return DateFormat("dd - MM - yyyy").format(date); + return DateFormat("dd-MM-yyyy${showFullDate ? " HH:mm" : ""}") + .format(date); } } }