feat: group chat UI changes

This commit is contained in:
Freek van de Ven 2023-03-31 14:20:28 +02:00
parent b99bdfd081
commit 35d89faf04
4 changed files with 170 additions and 110 deletions

View file

@ -18,13 +18,21 @@ class MyStatefulWidget extends StatefulWidget {
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
static final messages = [
ChatTextMessageModel(
sender: ChatUserModel(
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: pietUser,
text: 'Hoe gaat het?',
timestamp: DateTime.now(),
),
@ -48,13 +56,19 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
messages: messages,
);
Stream<List<PersonalChatModel>> get chatStream => (() {
late StreamController<List<PersonalChatModel>> controller;
controller = StreamController<List<PersonalChatModel>>(
static final groupChat = GroupChatModel(
title: 'Group chat',
imageUrl: 'https://xsgames.co/randomusers/avatar.php?g=male',
users: [pietUser, janUser],
messages: messages);
Stream<List<ChatModel>> get chatStream => (() {
late StreamController<List<ChatModel>> controller;
controller = StreamController<List<ChatModel>>(
onListen: () {
controller.add([
chat,
chat,
groupChat,
chat,
]);
},

View file

@ -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,
);

View file

@ -22,7 +22,7 @@ class ChatDetailScreen extends StatelessWidget {
super.key,
});
final PersonalChatModel? chat;
final ChatModel? chat;
final ChatOptions options;
final ChatTranslations translations;
final Stream<List<ChatMessageModel>>? chatMessages;
@ -64,15 +64,27 @@ class ChatDetailScreen extends StatelessWidget {
children: chat == null
? []
: [
options.userAvatarBuilder(
chat!.user,
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),
),
),

View file

@ -19,10 +19,10 @@ class ChatScreen extends StatefulWidget {
final ChatOptions options;
final ChatTranslations translations;
final Stream<List<PersonalChatModel>> chats;
final Stream<List<ChatModel>> 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<ChatScreen> createState() => _ChatScreenState();
@ -32,7 +32,8 @@ class _ChatScreenState extends State<ChatScreen> {
final DateFormatter _dateFormatter = DateFormatter();
@override
Widget build(BuildContext context) => widget.options.scaffoldBuilder(
Widget build(BuildContext context) {
return widget.options.scaffoldBuilder(
AppBar(
title: Text(widget.translations.chatsTitle),
),
@ -42,11 +43,11 @@ class _ChatScreenState extends State<ChatScreen> {
child: ListView(
padding: const EdgeInsets.only(top: 15.0),
children: [
StreamBuilder<List<PersonalChatModel>>(
StreamBuilder<List<ChatModel>>(
stream: widget.chats,
builder: (BuildContext context, snapshot) => Column(
children: [
for (PersonalChatModel chat in snapshot.data ?? [])
for (ChatModel chat in snapshot.data ?? []) ...[
Builder(
builder: (context) => Dismissible(
confirmDismiss: (_) => showDialog(
@ -56,14 +57,13 @@ class _ChatScreenState extends State<ChatScreen> {
widget.translations.deleteChatModalTitle,
),
content: Text(
widget.translations
.deleteChatModalDescription,
widget
.translations.deleteChatModalDescription,
),
actions: [
TextButton(
child: Text(
widget
.translations.deleteChatModalCancel,
widget.translations.deleteChatModalCancel,
),
onPressed: () =>
Navigator.of(context).pop(false),
@ -72,8 +72,8 @@ class _ChatScreenState extends State<ChatScreen> {
onPressed: () =>
Navigator.of(context).pop(true),
child: Text(
widget.translations
.deleteChatModalConfirm,
widget
.translations.deleteChatModalConfirm,
),
),
],
@ -92,36 +92,54 @@ class _ChatScreenState extends State<ChatScreen> {
),
),
),
key: Key(
key: ValueKey(
chat.id.toString(),
),
child: GestureDetector(
onTap: () => widget.onPressChat(chat),
child: widget.options.chatRowContainerBuilder(
ChatRow(
avatar: widget.options.userAvatarBuilder(
(chat is PersonalChatModel)
? ChatRow(
avatar:
widget.options.userAvatarBuilder(
chat.user,
40.0,
),
title: chat.user.fullName,
subTitle: chat.lastMessage != null
? chat.lastMessage
subTitle: chat.lastMessage != null &&
chat.lastMessage
is ChatTextMessageModel
? (chat.lastMessage!
as ChatTextMessageModel)
.text
: '📷 ${widget.translations.image}'
: null,
: '📷 ${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,
),
),
),
),
),
),
],
],
),
),
@ -137,4 +155,5 @@ class _ChatScreenState extends State<ChatScreen> {
],
),
);
}
}