diff --git a/packages/flutter_community_chat_view/example/lib/main.dart b/packages/flutter_community_chat_view/example/lib/main.dart index 9c3a27e..773fd95 100644 --- a/packages/flutter_community_chat_view/example/lib/main.dart +++ b/packages/flutter_community_chat_view/example/lib/main.dart @@ -18,13 +18,21 @@ class MyStatefulWidget extends StatefulWidget { } class _MyStatefulWidgetState extends State { + static final pietUser = ChatUserModel( + firstName: 'Piet', + lastName: 'Jansen', + imageUrl: 'https://xsgames.co/randomusers/avatar.php?g=female', + ); + + static final janUser = ChatUserModel( + firstName: 'Jan', + lastName: 'Jansen', + imageUrl: 'https://xsgames.co/randomusers/avatar.php?g=male', + ); + static final messages = [ ChatTextMessageModel( - sender: ChatUserModel( - firstName: 'Piet', - lastName: 'Jansen', - imageUrl: 'https://xsgames.co/randomusers/avatar.php?g=female', - ), + sender: pietUser, text: 'Hoe gaat het?', timestamp: DateTime.now(), ), @@ -48,13 +56,19 @@ class _MyStatefulWidgetState extends State { messages: messages, ); - Stream> get chatStream => (() { - late StreamController> controller; - controller = StreamController>( + static final groupChat = GroupChatModel( + title: 'Group chat', + imageUrl: 'https://xsgames.co/randomusers/avatar.php?g=male', + users: [pietUser, janUser], + messages: messages); + + Stream> get chatStream => (() { + late StreamController> controller; + controller = StreamController>( onListen: () { controller.add([ chat, - chat, + groupChat, chat, ]); }, diff --git a/packages/flutter_community_chat_view/lib/src/config/chat_options.dart b/packages/flutter_community_chat_view/lib/src/config/chat_options.dart index b97d530..f75a928 100644 --- a/packages/flutter_community_chat_view/lib/src/config/chat_options.dart +++ b/packages/flutter_community_chat_view/lib/src/config/chat_options.dart @@ -15,6 +15,7 @@ class ChatOptions { this.imagePickerContainerBuilder = _createImagePickerContainer, this.scaffoldBuilder = _createScaffold, this.userAvatarBuilder = _createUserAvatar, + this.groupAvatarBuilder = _createGroupAvatar, this.noChatsPlaceholderBuilder = _createNoChatsPlaceholder, }); @@ -24,6 +25,7 @@ class ChatOptions { final ImagePickerContainerBuilder imagePickerContainerBuilder; final ScaffoldBuilder scaffoldBuilder; final UserAvatarBuilder userAvatarBuilder; + final GroupAvatarBuilder groupAvatarBuilder; final NoChatsPlaceholderBuilder noChatsPlaceholderBuilder; } @@ -101,6 +103,14 @@ Widget _createUserAvatar( image: user.imageUrl, size: size, ); +Widget _createGroupAvatar( + String imageUrl, + double size, +) => + ChatImage( + image: imageUrl, + size: size, + ); Widget _createNoChatsPlaceholder( ChatTranslations translations, @@ -147,6 +157,11 @@ typedef UserAvatarBuilder = Widget Function( double size, ); +typedef GroupAvatarBuilder = Widget Function( + String imageUrl, + double size, +); + typedef NoChatsPlaceholderBuilder = Widget Function( ChatTranslations translations, ); diff --git a/packages/flutter_community_chat_view/lib/src/screens/chat_detail_screen.dart b/packages/flutter_community_chat_view/lib/src/screens/chat_detail_screen.dart index de9e278..1cc4cfb 100644 --- a/packages/flutter_community_chat_view/lib/src/screens/chat_detail_screen.dart +++ b/packages/flutter_community_chat_view/lib/src/screens/chat_detail_screen.dart @@ -22,7 +22,7 @@ class ChatDetailScreen extends StatelessWidget { super.key, }); - final PersonalChatModel? chat; + final ChatModel? chat; final ChatOptions options; final ChatTranslations translations; final Stream>? chatMessages; @@ -64,15 +64,27 @@ class ChatDetailScreen extends StatelessWidget { children: chat == null ? [] : [ - options.userAvatarBuilder( - chat!.user, - 36.0, - ), + if (chat is GroupChatModel) ...[ + options.groupAvatarBuilder( + (chat! as GroupChatModel).imageUrl, + 36.0, + ), + ] else if (chat is PersonalChatModel) ...[ + options.userAvatarBuilder( + (chat! as PersonalChatModel).user, + 36.0, + ), + ] else + ...[], Expanded( child: Padding( padding: const EdgeInsets.only(left: 15.5), child: Text( - chat!.user.fullName, + (chat is GroupChatModel) + ? (chat! as GroupChatModel).title + : (chat is PersonalChatModel) + ? (chat! as PersonalChatModel).user.fullName + : '', style: const TextStyle(fontSize: 18), ), ), diff --git a/packages/flutter_community_chat_view/lib/src/screens/chat_screen.dart b/packages/flutter_community_chat_view/lib/src/screens/chat_screen.dart index 5ba7541..6d67d0f 100644 --- a/packages/flutter_community_chat_view/lib/src/screens/chat_screen.dart +++ b/packages/flutter_community_chat_view/lib/src/screens/chat_screen.dart @@ -19,10 +19,10 @@ class ChatScreen extends StatefulWidget { final ChatOptions options; final ChatTranslations translations; - final Stream> chats; + final Stream> chats; final VoidCallback? onPressStartChat; - final void Function(PersonalChatModel chat) onDeleteChat; - final void Function(PersonalChatModel chat) onPressChat; + final void Function(ChatModel chat) onDeleteChat; + final void Function(ChatModel chat) onPressChat; @override State createState() => _ChatScreenState(); @@ -32,109 +32,128 @@ class _ChatScreenState extends State { final DateFormatter _dateFormatter = DateFormatter(); @override - Widget build(BuildContext context) => widget.options.scaffoldBuilder( - AppBar( - title: Text(widget.translations.chatsTitle), - ), - Column( - children: [ - Expanded( - child: ListView( - padding: const EdgeInsets.only(top: 15.0), - children: [ - StreamBuilder>( - stream: widget.chats, - builder: (BuildContext context, snapshot) => Column( - children: [ - for (PersonalChatModel chat in snapshot.data ?? []) - Builder( - builder: (context) => Dismissible( - confirmDismiss: (_) => showDialog( - context: context, - builder: (BuildContext context) => AlertDialog( - title: Text( - widget.translations.deleteChatModalTitle, - ), - content: Text( - widget.translations - .deleteChatModalDescription, - ), - actions: [ - TextButton( - child: Text( - widget - .translations.deleteChatModalCancel, - ), - onPressed: () => - Navigator.of(context).pop(false), - ), - ElevatedButton( - onPressed: () => - Navigator.of(context).pop(true), - child: Text( - widget.translations - .deleteChatModalConfirm, - ), - ), - ], + Widget build(BuildContext context) { + return widget.options.scaffoldBuilder( + AppBar( + title: Text(widget.translations.chatsTitle), + ), + Column( + children: [ + Expanded( + child: ListView( + padding: const EdgeInsets.only(top: 15.0), + children: [ + StreamBuilder>( + stream: widget.chats, + builder: (BuildContext context, snapshot) => Column( + children: [ + for (ChatModel chat in snapshot.data ?? []) ...[ + Builder( + builder: (context) => Dismissible( + confirmDismiss: (_) => showDialog( + context: context, + builder: (BuildContext context) => AlertDialog( + title: Text( + widget.translations.deleteChatModalTitle, ), - ), - onDismissed: (_) => widget.onDeleteChat(chat), - background: Container( - color: Colors.red, - child: Align( - alignment: Alignment.centerRight, - child: Padding( - padding: const EdgeInsets.all(8.0), + content: Text( + widget + .translations.deleteChatModalDescription, + ), + actions: [ + TextButton( child: Text( - widget.translations.deleteChatButton, + widget.translations.deleteChatModalCancel, + ), + onPressed: () => + Navigator.of(context).pop(false), + ), + ElevatedButton( + onPressed: () => + Navigator.of(context).pop(true), + child: Text( + widget + .translations.deleteChatModalConfirm, ), ), - ), + ], ), - key: Key( - chat.id.toString(), - ), - child: GestureDetector( - onTap: () => widget.onPressChat(chat), - child: widget.options.chatRowContainerBuilder( - ChatRow( - avatar: widget.options.userAvatarBuilder( - chat.user, - 40.0, - ), - title: chat.user.fullName, - subTitle: chat.lastMessage != null - ? chat.lastMessage - is ChatTextMessageModel - ? (chat.lastMessage! - as ChatTextMessageModel) - .text - : '📷 ${widget.translations.image}' - : null, - lastUsed: chat.lastUsed != null - ? _dateFormatter.format( - date: chat.lastUsed!, - ) - : null, + ), + onDismissed: (_) => widget.onDeleteChat(chat), + background: Container( + color: Colors.red, + child: Align( + alignment: Alignment.centerRight, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + widget.translations.deleteChatButton, ), ), ), ), + key: ValueKey( + chat.id.toString(), + ), + child: GestureDetector( + onTap: () => widget.onPressChat(chat), + child: widget.options.chatRowContainerBuilder( + (chat is PersonalChatModel) + ? ChatRow( + avatar: + widget.options.userAvatarBuilder( + chat.user, + 40.0, + ), + title: chat.user.fullName, + subTitle: chat.lastMessage != null && + chat.lastMessage + is ChatTextMessageModel + ? (chat.lastMessage! + as ChatTextMessageModel) + .text + : '📷 ${widget.translations.image}', + lastUsed: chat.lastUsed != null + ? _dateFormatter.format( + date: chat.lastUsed!, + ) + : null, + ) + : ChatRow( + title: (chat as GroupChatModel).title, + subTitle: chat.lastMessage != null && + chat.lastMessage + is ChatTextMessageModel + ? (chat.lastMessage! + as ChatTextMessageModel) + .text + : '📷 ' + '${widget.translations.image}', + avatar: + widget.options.groupAvatarBuilder( + chat.imageUrl, + 40.0, + ), + ), + ), + ), ), + ), ], - ), + ], ), - ], - ), + ), + ], ), - if (widget.onPressStartChat != null) - widget.options.newChatButtonBuilder( - context, - widget.onPressStartChat!, - widget.translations, - ), - ], - ), - ); + ), + if (widget.onPressStartChat != null) + widget.options.newChatButtonBuilder( + context, + widget.onPressStartChat!, + widget.translations, + ), + ], + ), + ); + } }