mirror of
https://github.com/Iconica-Development/flutter_chat.git
synced 2025-05-18 18:33:49 +02:00
feat: show amount of unread messages
This commit is contained in:
parent
f6a2a26def
commit
5e41f3885f
6 changed files with 150 additions and 35 deletions
|
@ -29,6 +29,24 @@ class FirebaseChatService implements ChatService {
|
|||
_options = options ?? const FirebaseChatOptions();
|
||||
}
|
||||
|
||||
StreamSubscription<DocumentSnapshot> _addUnreadChatSubscription(
|
||||
String chatId,
|
||||
String userId,
|
||||
Function(int) onUnreadChatsUpdated,
|
||||
) {
|
||||
var snapshots = _db
|
||||
.collection(_options.usersCollectionName)
|
||||
.doc(userId)
|
||||
.collection('chats')
|
||||
.doc(chatId)
|
||||
.snapshots();
|
||||
|
||||
return snapshots.listen((snapshot) {
|
||||
var data = snapshot.data();
|
||||
onUnreadChatsUpdated(data?['amount_unread_messages'] ?? 0);
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription<QuerySnapshot> _addChatSubscription(
|
||||
List<String> chatIds,
|
||||
Function(List<ChatModel>) onReceivedChats,
|
||||
|
@ -79,6 +97,8 @@ class FirebaseChatService implements ChatService {
|
|||
);
|
||||
}
|
||||
}
|
||||
ChatModel? chatModel;
|
||||
|
||||
if (chatData.personal) {
|
||||
var otherUserId = List<String>.from(chatData.users).firstWhere(
|
||||
(element) => element != currentUser?.id,
|
||||
|
@ -86,18 +106,16 @@ class FirebaseChatService implements ChatService {
|
|||
var otherUser = await _userService.getUser(otherUserId);
|
||||
|
||||
if (otherUser != null) {
|
||||
chats.add(
|
||||
PersonalChatModel(
|
||||
id: chatDoc.id,
|
||||
user: otherUser,
|
||||
lastMessage: messages.isNotEmpty ? messages.last : null,
|
||||
messages: messages,
|
||||
lastUsed: chatData.lastUsed == null
|
||||
? null
|
||||
: DateTime.fromMillisecondsSinceEpoch(
|
||||
chatData.lastUsed!.millisecondsSinceEpoch,
|
||||
),
|
||||
),
|
||||
chatModel = PersonalChatModel(
|
||||
id: chatDoc.id,
|
||||
user: otherUser,
|
||||
lastMessage: messages.isNotEmpty ? messages.last : null,
|
||||
messages: messages,
|
||||
lastUsed: chatData.lastUsed == null
|
||||
? null
|
||||
: DateTime.fromMillisecondsSinceEpoch(
|
||||
chatData.lastUsed!.millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -109,22 +127,39 @@ class FirebaseChatService implements ChatService {
|
|||
users.add(user);
|
||||
}
|
||||
}
|
||||
chats.add(
|
||||
GroupChatModel(
|
||||
id: chatDoc.id,
|
||||
title: chatData.title ?? '',
|
||||
imageUrl: chatData.imageUrl ?? '',
|
||||
lastMessage: messages.isNotEmpty ? messages.last : null,
|
||||
messages: messages,
|
||||
users: users,
|
||||
lastUsed: chatData.lastUsed == null
|
||||
? null
|
||||
: DateTime.fromMillisecondsSinceEpoch(
|
||||
chatData.lastUsed!.millisecondsSinceEpoch,
|
||||
),
|
||||
),
|
||||
chatModel = GroupChatModel(
|
||||
id: chatDoc.id,
|
||||
title: chatData.title ?? '',
|
||||
imageUrl: chatData.imageUrl ?? '',
|
||||
lastMessage: messages.isNotEmpty ? messages.last : null,
|
||||
messages: messages,
|
||||
users: users,
|
||||
lastUsed: chatData.lastUsed == null
|
||||
? null
|
||||
: DateTime.fromMillisecondsSinceEpoch(
|
||||
chatData.lastUsed!.millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (chatModel != null) {
|
||||
_addUnreadChatSubscription(chatModel.id ?? '', currentUser?.id ?? '',
|
||||
(unreadMessages) {
|
||||
// the chatmodel should be updated to reflect the amount of unread messages
|
||||
if (chatModel is PersonalChatModel) {
|
||||
chatModel = (chatModel as PersonalChatModel)
|
||||
.copyWith(unreadMessages: unreadMessages);
|
||||
} else if (chatModel is GroupChatModel) {
|
||||
chatModel = (chatModel as GroupChatModel)
|
||||
.copyWith(unreadMessages: unreadMessages);
|
||||
}
|
||||
|
||||
chats = chats
|
||||
.map((chat) => chat.id == chatModel?.id ? chatModel! : chat)
|
||||
.toList();
|
||||
onReceivedChats(chats);
|
||||
});
|
||||
chats.add(chatModel!);
|
||||
}
|
||||
}
|
||||
onReceivedChats(chats);
|
||||
});
|
||||
|
|
|
@ -8,12 +8,14 @@ abstract class ChatModel {
|
|||
ChatModel({
|
||||
this.id,
|
||||
this.messages = const [],
|
||||
this.unreadMessages,
|
||||
this.lastUsed,
|
||||
this.lastMessage,
|
||||
});
|
||||
|
||||
String? id;
|
||||
List<ChatMessageModel>? messages;
|
||||
int? unreadMessages;
|
||||
DateTime? lastUsed;
|
||||
ChatMessageModel? lastMessage;
|
||||
}
|
||||
|
|
|
@ -13,9 +13,31 @@ class GroupChatModel extends ChatModel {
|
|||
super.messages,
|
||||
super.lastUsed,
|
||||
super.lastMessage,
|
||||
super.unreadMessages,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final String imageUrl;
|
||||
final List<ChatUserModel> users;
|
||||
|
||||
GroupChatModel copyWith({
|
||||
String? id,
|
||||
List<ChatMessageModel>? messages,
|
||||
int? unreadMessages,
|
||||
DateTime? lastUsed,
|
||||
ChatMessageModel? lastMessage,
|
||||
String? title,
|
||||
String? imageUrl,
|
||||
List<ChatUserModel>? users,
|
||||
}) =>
|
||||
GroupChatModel(
|
||||
id: id ?? this.id,
|
||||
messages: messages ?? this.messages,
|
||||
unreadMessages: unreadMessages ?? this.unreadMessages,
|
||||
lastUsed: lastUsed ?? this.lastUsed,
|
||||
lastMessage: lastMessage ?? this.lastMessage,
|
||||
title: title ?? this.title,
|
||||
imageUrl: imageUrl ?? this.imageUrl,
|
||||
users: users ?? this.users,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,9 +9,27 @@ class PersonalChatModel extends ChatModel {
|
|||
required this.user,
|
||||
super.id,
|
||||
super.messages,
|
||||
super.unreadMessages,
|
||||
super.lastUsed,
|
||||
super.lastMessage,
|
||||
});
|
||||
|
||||
final ChatUserModel user;
|
||||
|
||||
PersonalChatModel copyWith({
|
||||
String? id,
|
||||
List<ChatMessageModel>? messages,
|
||||
int? unreadMessages,
|
||||
DateTime? lastUsed,
|
||||
ChatMessageModel? lastMessage,
|
||||
ChatUserModel? user,
|
||||
}) =>
|
||||
PersonalChatModel(
|
||||
id: id ?? this.id,
|
||||
messages: messages ?? this.messages,
|
||||
unreadMessages: unreadMessages ?? this.unreadMessages,
|
||||
lastUsed: lastUsed ?? this.lastUsed,
|
||||
lastMessage: lastMessage ?? this.lastMessage,
|
||||
user: user ?? this.user,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,12 +7,14 @@ import 'package:flutter/material.dart';
|
|||
class ChatRow extends StatelessWidget {
|
||||
const ChatRow({
|
||||
required this.title,
|
||||
this.unreadMessages = 0,
|
||||
this.lastUsed,
|
||||
this.subTitle,
|
||||
this.avatar,
|
||||
super.key,
|
||||
});
|
||||
final String title;
|
||||
final int unreadMessages;
|
||||
final Widget? avatar;
|
||||
final String? subTitle;
|
||||
final String? lastUsed;
|
||||
|
@ -35,9 +37,11 @@ class ChatRow extends StatelessWidget {
|
|||
title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontWeight: unreadMessages > 0
|
||||
? FontWeight.w600
|
||||
: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
if (subTitle != null)
|
||||
|
@ -45,8 +49,11 @@ class ChatRow extends StatelessWidget {
|
|||
padding: const EdgeInsets.only(top: 3.0),
|
||||
child: Text(
|
||||
subTitle!,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: unreadMessages > 0
|
||||
? FontWeight.w600
|
||||
: FontWeight.w400,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
|
@ -56,12 +63,39 @@ class ChatRow extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
lastUsed ?? '',
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFBBBBBB),
|
||||
fontSize: 14,
|
||||
),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
lastUsed ?? '',
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFBBBBBB),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
if (unreadMessages > 0) ...[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
unreadMessages.toString(),
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
@ -99,6 +99,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||
child: widget.options.chatRowContainerBuilder(
|
||||
(chat is PersonalChatModel)
|
||||
? ChatRow(
|
||||
unreadMessages:
|
||||
chat.unreadMessages ?? 0,
|
||||
avatar:
|
||||
widget.options.userAvatarBuilder(
|
||||
chat.user,
|
||||
|
@ -122,6 +124,8 @@ class _ChatScreenState extends State<ChatScreen> {
|
|||
)
|
||||
: ChatRow(
|
||||
title: (chat as GroupChatModel).title,
|
||||
unreadMessages:
|
||||
chat.unreadMessages ?? 0,
|
||||
subTitle: chat.lastMessage != null
|
||||
? chat.lastMessage
|
||||
is ChatTextMessageModel
|
||||
|
|
Loading…
Reference in a new issue