diff --git a/packages/chat_repository_interface/lib/src/services/chat_service.dart b/packages/chat_repository_interface/lib/src/services/chat_service.dart index 601faa8..015f26f 100644 --- a/packages/chat_repository_interface/lib/src/services/chat_service.dart +++ b/packages/chat_repository_interface/lib/src/services/chat_service.dart @@ -16,11 +16,15 @@ import "package:collection/collection.dart"; class ChatService { /// Create a chat service with the given parameters. ChatService({ + required this.userId, ChatRepositoryInterface? chatRepository, UserRepositoryInterface? userRepository, }) : chatRepository = chatRepository ?? LocalChatRepository(), userRepository = userRepository ?? LocalUserRepository(); + /// The user ID of the person currently looking at the chat + final String userId; + /// The chat repository final ChatRepositoryInterface chatRepository; @@ -54,11 +58,9 @@ class ChatService { ); } - /// Get the chats for the given [userId]. + /// Get the chats for the user with the given [userId]. /// Returns a list of [ChatModel] stream. - Stream?> getChats({ - required String userId, - }) => + Stream?> getChats() => chatRepository.getChats(userId: userId); /// Get the chat with the given [chatId]. @@ -129,11 +131,9 @@ class ChatService { /// Returns a list of [MessageModel] stream. /// [pageSize] is the number of messages to be fetched. /// [page] is the page number. - /// [userId] is the user id. /// [chatId] is the chat id. /// Returns a list of [MessageModel] stream. Stream?> getMessages({ - required String userId, required String chatId, required int pageSize, required int page, @@ -183,15 +183,14 @@ class ChatService { /// Returns a list of [UserModel] stream. Stream> getAllUsers() => userRepository.getAllUsers(); - /// Get the unread messages count for the given [userId] and or [chatId]. - /// [userId] is the user id. + /// Get the unread messages count for a user [chatId]. /// [chatId] is the chat id. If not provided, it will return the /// total unread messages count. /// Returns a [Stream] of [int]. Stream getUnreadMessagesCount({ - required String userId, + String? chatId, }) => - chatRepository.getUnreadMessagesCount(userId: userId); + chatRepository.getUnreadMessagesCount(userId: userId, chatId: chatId); /// Upload an image with the given parameters. /// [path] is the image path. @@ -211,7 +210,6 @@ class ChatService { /// Returns a [Future] of [void]. Future markAsRead({ required String chatId, - required String userId, }) async { var chat = await chatRepository.getChat(chatId: chatId).first; diff --git a/packages/flutter_chat/lib/src/config/chat_options.dart b/packages/flutter_chat/lib/src/config/chat_options.dart index a864cca..d73f5f1 100644 --- a/packages/flutter_chat/lib/src/config/chat_options.dart +++ b/packages/flutter_chat/lib/src/config/chat_options.dart @@ -7,7 +7,7 @@ import "package:flutter_chat/src/config/chat_translations.dart"; /// Use this class to configure the chat options. class ChatOptions { /// The chat options constructor - const ChatOptions({ + ChatOptions({ this.dateformat, this.groupChatEnabled = true, this.enableLoadingIndicator = false, @@ -21,7 +21,16 @@ class ChatOptions { this.chatAlignment, this.onNoChats, this.pageSize = 20, - }); + ChatRepositoryInterface? chatRepository, + UserRepositoryInterface? userRepository, + }) : chatRepository = chatRepository ?? LocalChatRepository(), + userRepository = userRepository ?? LocalUserRepository(); + + /// The implementation for communication with persistance layer for chats + final ChatRepositoryInterface chatRepository; + + /// The implementation for communication with persistance layer for users + final UserRepositoryInterface userRepository; /// [dateformat] is a function that formats the date. // ignore: avoid_positional_boolean_parameters diff --git a/packages/flutter_chat/lib/src/flutter_chat_entry_widget.dart b/packages/flutter_chat/lib/src/flutter_chat_entry_widget.dart index a0f1bbd..08d5994 100644 --- a/packages/flutter_chat/lib/src/flutter_chat_entry_widget.dart +++ b/packages/flutter_chat/lib/src/flutter_chat_entry_widget.dart @@ -8,7 +8,6 @@ class FlutterChatEntryWidget extends StatefulWidget { /// Constructs a [FlutterChatEntryWidget]. const FlutterChatEntryWidget({ required this.userId, - this.chatService, this.options, this.onTap, this.widgetSize = 75, @@ -20,9 +19,6 @@ class FlutterChatEntryWidget extends StatefulWidget { super.key, }); - /// The chat service associated with the widget. - final ChatService? chatService; - /// The user ID of the person currently looking at the chat final String userId; @@ -56,12 +52,29 @@ class FlutterChatEntryWidget extends StatefulWidget { /// State class for [FlutterChatEntryWidget]. class _FlutterChatEntryWidgetState extends State { - ChatService? chatService; + late ChatService chatService; @override void initState() { super.initState(); - chatService ??= widget.chatService ?? ChatService(); + _initChatService(); + } + + @override + void didUpdateWidget(covariant FlutterChatEntryWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.userId != widget.userId || + oldWidget.options != widget.options) { + _initChatService(); + } + } + + void _initChatService() { + chatService = ChatService( + userId: widget.userId, + chatRepository: widget.options?.chatRepository, + userRepository: widget.options?.userRepository, + ); } @override @@ -72,13 +85,12 @@ class _FlutterChatEntryWidgetState extends State { MaterialPageRoute( builder: (context) => FlutterChatNavigatorUserstory( userId: widget.userId, - chatService: chatService, - chatOptions: widget.options, + options: widget.options ?? ChatOptions(), ), ), ), child: StreamBuilder( - stream: chatService!.getUnreadMessagesCount(userId: widget.userId), + stream: chatService.getUnreadMessagesCount(), builder: (BuildContext context, snapshot) => Stack( alignment: Alignment.center, children: [ diff --git a/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart b/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart index 06ff351..c0fe01d 100644 --- a/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart +++ b/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart @@ -25,19 +25,15 @@ class FlutterChatNavigatorUserstory extends StatefulWidget { /// Constructs a [FlutterChatNavigatorUserstory]. const FlutterChatNavigatorUserstory({ required this.userId, - this.chatService, - this.chatOptions, + required this.options, super.key, }); /// The user ID of the person currently looking at the chat final String userId; - /// The chat service associated with the widget. - final ChatService? chatService; - /// The chat options - final ChatOptions? chatOptions; + final ChatOptions options; @override State createState() => @@ -46,14 +42,18 @@ class FlutterChatNavigatorUserstory extends StatefulWidget { class _FlutterChatNavigatorUserstoryState extends State { - late ChatService _service = widget.chatService ?? ChatService(); + late ChatService _service = ChatService( + userId: widget.userId, + chatRepository: widget.options.chatRepository, + userRepository: widget.options.userRepository, + ); late final PopHandler _popHandler = PopHandler(); @override Widget build(BuildContext context) => ChatScope( userId: widget.userId, - options: widget.chatOptions ?? const ChatOptions(), + options: widget.options, service: _service, popHandler: _popHandler, child: NavigatorPopHandler( @@ -67,7 +67,7 @@ class _FlutterChatNavigatorUserstoryState builder: (context) => _NavigatorWrapper( userId: widget.userId, chatService: _service, - chatOptions: widget.chatOptions ?? const ChatOptions(), + chatOptions: widget.options, ), ), ), @@ -79,9 +79,13 @@ class _FlutterChatNavigatorUserstoryState super.didUpdateWidget(oldWidget); if (oldWidget.userId != widget.userId || - oldWidget.chatOptions != widget.chatOptions) { + oldWidget.options != widget.options) { setState(() { - _service = widget.chatService ?? ChatService(); + _service = ChatService( + userId: widget.userId, + chatRepository: widget.options.chatRepository, + userRepository: widget.options.userRepository, + ); }); } } @@ -102,7 +106,6 @@ class _NavigatorWrapper extends StatelessWidget { Widget build(BuildContext context) => chatScreen(context); Widget chatScreen(BuildContext context) => ChatScreen( - userId: userId, chatService: chatService, chatOptions: chatOptions, onPressChat: (chat) => route(context, chatDetailScreen(context, chat)), @@ -115,8 +118,7 @@ class _NavigatorWrapper extends StatelessWidget { Widget chatDetailScreen(BuildContext context, ChatModel chat) => ChatDetailScreen( chat: chat, - onReadChat: (chat) async => - chatService.markAsRead(chatId: chat.id, userId: userId), + onReadChat: (chat) async => chatService.markAsRead(chatId: chat.id), onPressChatTitle: (chat) async { if (chat.isGroupChat) { return route(context, chatProfileScreen(context, null, chat)); diff --git a/packages/flutter_chat/lib/src/screens/chat_detail/chat_detail_screen.dart b/packages/flutter_chat/lib/src/screens/chat_detail/chat_detail_screen.dart index 9ae7611..a2c0aae 100644 --- a/packages/flutter_chat/lib/src/screens/chat_detail/chat_detail_screen.dart +++ b/packages/flutter_chat/lib/src/screens/chat_detail/chat_detail_screen.dart @@ -204,7 +204,6 @@ class _BodyState extends State<_Body> { var chatScope = ChatScope.of(context); var options = chatScope.options; var service = chatScope.service; - var userId = chatScope.userId; void handleScroll(PointerMoveEvent event) { if (!showIndicator && @@ -233,7 +232,6 @@ class _BodyState extends State<_Body> { alignment: options.chatAlignment ?? Alignment.bottomCenter, child: StreamBuilder?>( stream: service.getMessages( - userId: userId, chatId: widget.chat.id, pageSize: pageSize, page: page, diff --git a/packages/flutter_chat/lib/src/screens/chat_screen.dart b/packages/flutter_chat/lib/src/screens/chat_screen.dart index 88d6e8d..672f861 100644 --- a/packages/flutter_chat/lib/src/screens/chat_screen.dart +++ b/packages/flutter_chat/lib/src/screens/chat_screen.dart @@ -4,6 +4,7 @@ import "package:flutter_chat/src/config/chat_options.dart"; import "package:flutter_chat/src/config/chat_translations.dart"; import "package:flutter_chat/src/config/screen_types.dart"; import "package:flutter_chat/src/services/date_formatter.dart"; +import "package:flutter_chat/src/util/scope.dart"; import "package:flutter_profile/flutter_profile.dart"; /// The chat screen @@ -11,7 +12,6 @@ import "package:flutter_profile/flutter_profile.dart"; class ChatScreen extends StatelessWidget { /// Constructs a [ChatScreen] const ChatScreen({ - required this.userId, required this.chatService, required this.chatOptions, required this.onPressChat, @@ -20,9 +20,6 @@ class ChatScreen extends StatelessWidget { super.key, }); - /// The user ID of the person currently looking at the chat - final String userId; - /// The chat service final ChatService chatService; @@ -43,12 +40,10 @@ class ChatScreen extends StatelessWidget { if (chatOptions.builders.baseScreenBuilder == null) { return Scaffold( appBar: _AppBar( - userId: userId, chatOptions: chatOptions, chatService: chatService, ), body: _Body( - userId: userId, chatOptions: chatOptions, chatService: chatService, onPressChat: onPressChat, @@ -62,12 +57,10 @@ class ChatScreen extends StatelessWidget { context, mapScreenType, _AppBar( - userId: userId, chatOptions: chatOptions, chatService: chatService, ), _Body( - userId: userId, chatOptions: chatOptions, chatService: chatService, onPressChat: onPressChat, @@ -80,12 +73,10 @@ class ChatScreen extends StatelessWidget { class _AppBar extends StatelessWidget implements PreferredSizeWidget { const _AppBar({ - required this.userId, required this.chatOptions, required this.chatService, }); - final String userId; final ChatOptions chatOptions; final ChatService chatService; @@ -100,7 +91,7 @@ class _AppBar extends StatelessWidget implements PreferredSizeWidget { ), actions: [ StreamBuilder( - stream: chatService.getUnreadMessagesCount(userId: userId), + stream: chatService.getUnreadMessagesCount(), builder: (BuildContext context, snapshot) => Align( alignment: Alignment.centerRight, child: Visibility( @@ -127,7 +118,6 @@ class _AppBar extends StatelessWidget implements PreferredSizeWidget { class _Body extends StatefulWidget { const _Body({ - required this.userId, required this.chatOptions, required this.chatService, required this.onPressChat, @@ -135,7 +125,6 @@ class _Body extends StatefulWidget { this.onPressStartChat, }); - final String userId; final ChatOptions chatOptions; final ChatService chatService; final Function(ChatModel chat) onPressChat; @@ -163,7 +152,7 @@ class _BodyState extends State<_Body> { padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 28), children: [ StreamBuilder?>( - stream: widget.chatService.getChats(userId: widget.userId), + stream: widget.chatService.getChats(), builder: (BuildContext context, snapshot) { if (snapshot.connectionState == ConnectionState.done && (snapshot.data?.isEmpty ?? true) || @@ -251,7 +240,6 @@ class _BodyState extends State<_Body> { service: widget.chatService, chat: chat, chatOptions: widget.chatOptions, - userId: widget.userId, onPressChat: widget.onPressChat, ), ) @@ -259,7 +247,6 @@ class _BodyState extends State<_Body> { service: widget.chatService, chat: chat, chatOptions: widget.chatOptions, - userId: widget.userId, onPressChat: widget.onPressChat, ), ), @@ -308,14 +295,12 @@ class _ChatItem extends StatelessWidget { required this.chat, required this.chatOptions, required this.service, - required this.userId, required this.onPressChat, }); final ChatModel chat; final ChatOptions chatOptions; final ChatService service; - final String userId; final Function(ChatModel chat) onPressChat; @override @@ -335,7 +320,6 @@ class _ChatItem extends StatelessWidget { options: chatOptions, dateFormatter: dateFormatter, chatService: service, - currentUserId: userId, ), ) ?? DecoratedBox( @@ -355,7 +339,6 @@ class _ChatItem extends StatelessWidget { options: chatOptions, dateFormatter: dateFormatter, chatService: service, - currentUserId: userId, ), ), ), @@ -368,18 +351,18 @@ class _ChatListItem extends StatelessWidget { required this.chat, required this.options, required this.dateFormatter, - required this.currentUserId, required this.chatService, }); final ChatModel chat; final ChatOptions options; final DateFormatter dateFormatter; - final String currentUserId; final ChatService chatService; @override Widget build(BuildContext context) { + var scope = ChatScope.of(context); + var currentUserId = scope.userId; var translations = options.translations; if (chat.isGroupChat) { return StreamBuilder(