diff --git a/README.md b/README.md index a7cdef2..8e884ee 100644 --- a/README.md +++ b/README.md @@ -239,7 +239,7 @@ Please file any issues, bugs or feature request as an issue on our [GitHub](http ## Want to contribute -If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_chat/pulls). +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](./CONTRIBUTING.md) and send us your [pull request](https://github.com/Iconica-Development/flutter_chat/pulls). ## Author diff --git a/packages/flutter_chat/lib/src/chat_entry_widget.dart b/packages/flutter_chat/lib/src/chat_entry_widget.dart index 037cecb..394be39 100644 --- a/packages/flutter_chat/lib/src/chat_entry_widget.dart +++ b/packages/flutter_chat/lib/src/chat_entry_widget.dart @@ -3,7 +3,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_chat/flutter_chat.dart'; +/// A widget representing an entry point for a chat UI. class ChatEntryWidget extends StatefulWidget { + /// Constructs a [ChatEntryWidget]. const ChatEntryWidget({ this.chatService, this.onTap, @@ -16,19 +18,35 @@ class ChatEntryWidget extends StatefulWidget { super.key, }); + /// The chat service associated with the widget. final ChatService? chatService; + + /// Background color of the widget. final Color backgroundColor; + + /// Size of the widget. final double widgetSize; + + /// Background color of the counter. final Color counterBackgroundColor; + + /// Callback function triggered when the widget is tapped. final Function()? onTap; + + /// Icon to be displayed. final IconData icon; + + /// Color of the icon. final Color iconColor; + + /// Text style for the counter. final TextStyle? textStyle; @override State createState() => _ChatEntryWidgetState(); } +/// State class for [ChatEntryWidget]. class _ChatEntryWidgetState extends State { ChatService? chatService; @@ -98,13 +116,17 @@ class _ChatEntryWidgetState extends State { ); } +/// Stateful widget representing an animated notification icon. class _AnimatedNotificationIcon extends StatefulWidget { const _AnimatedNotificationIcon({ required this.notifications, required this.icon, }); + /// The number of notifications. final int notifications; + + /// The icon to be displayed. final Icon icon; @override @@ -112,6 +134,7 @@ class _AnimatedNotificationIcon extends StatefulWidget { _AnimatedNotificationIconState(); } +/// State class for [_AnimatedNotificationIcon]. class _AnimatedNotificationIconState extends State<_AnimatedNotificationIcon> with SingleTickerProviderStateMixin { late AnimationController _animationController; 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 0685fce..97f7b7a 100644 --- a/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart +++ b/packages/flutter_chat/lib/src/flutter_chat_navigator_userstory.dart @@ -5,6 +5,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_chat/flutter_chat.dart'; +/// Navigates to the chat user story screen. +/// +/// [context]: The build context. +/// [configuration]: The configuration for the chat user story. Widget chatNavigatorUserStory( BuildContext context, { ChatUserStoryConfiguration? configuration, @@ -18,6 +22,10 @@ Widget chatNavigatorUserStory( context, ); +/// Constructs the chat screen route widget. +/// +/// [configuration]: The configuration for the chat user story. +/// [context]: The build context. Widget _chatScreenRoute( ChatUserStoryConfiguration configuration, BuildContext context, @@ -65,6 +73,11 @@ Widget _chatScreenRoute( translations: configuration.translations, ); +/// Constructs the chat detail screen route widget. +/// +/// [configuration]: The configuration for the chat user story. +/// [context]: The build context. +/// [chatId]: The id of the chat. Widget _chatDetailScreenRoute( ChatUserStoryConfiguration configuration, BuildContext context, @@ -118,6 +131,12 @@ Widget _chatDetailScreenRoute( iconColor: configuration.iconColor, ); +/// Constructs the chat profile screen route widget. +/// +/// [configuration]: The configuration for the chat user story. +/// [context]: The build context. +/// [chatId]: The id of the chat. +/// [userId]: The id of the user. Widget _chatProfileScreenRoute( ChatUserStoryConfiguration configuration, BuildContext context, @@ -147,6 +166,10 @@ Widget _chatProfileScreenRoute( }, ); +/// Constructs the new chat screen route widget. +/// +/// [configuration]: The configuration for the chat user story. +/// [context]: The build context. Widget _newChatScreenRoute( ChatUserStoryConfiguration configuration, BuildContext context, diff --git a/packages/flutter_chat/lib/src/go_router.dart b/packages/flutter_chat/lib/src/go_router.dart index c9113db..92512e1 100644 --- a/packages/flutter_chat/lib/src/go_router.dart +++ b/packages/flutter_chat/lib/src/go_router.dart @@ -5,6 +5,11 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +/// Builds a screen with a fade transition. +/// +/// [context]: The build context. +/// [state]: The state of the GoRouter. +/// [child]: The child widget to be displayed. CustomTransitionPage buildScreenWithFadeTransition({ required BuildContext context, required GoRouterState state, @@ -17,6 +22,11 @@ CustomTransitionPage buildScreenWithFadeTransition({ FadeTransition(opacity: animation, child: child), ); +/// Builds a screen without any transition. +/// +/// [context]: The build context. +/// [state]: The state of the GoRouter. +/// [child]: The child widget to be displayed. CustomTransitionPage buildScreenWithoutTransition({ required BuildContext context, required GoRouterState state, diff --git a/packages/flutter_chat/lib/src/models/chat_configuration.dart b/packages/flutter_chat/lib/src/models/chat_configuration.dart index 8288eeb..f2449df 100644 --- a/packages/flutter_chat/lib/src/models/chat_configuration.dart +++ b/packages/flutter_chat/lib/src/models/chat_configuration.dart @@ -7,8 +7,10 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_chat_view/flutter_chat_view.dart'; +/// `ChatUserStoryConfiguration` is a class that configures the chat user story. @immutable class ChatUserStoryConfiguration { + /// Creates a new instance of `ChatUserStoryConfiguration`. const ChatUserStoryConfiguration({ required this.chatService, required this.chatOptionsBuilder, @@ -30,30 +32,63 @@ class ChatUserStoryConfiguration { this.messagePageSize = 20, this.onPressUserProfile, }); + + /// The service responsible for handling chat-related functionalities. final ChatService chatService; + + /// Callback function triggered when a chat is pressed. final Function(BuildContext, ChatModel)? onPressChat; + + /// Callback function triggered when a chat is deleted. final Function(BuildContext, ChatModel)? onDeleteChat; + + /// Translations for internationalization/localization support. final ChatTranslations translations; + + /// Determines whether dismissing is disabled for permanent chats. final bool disableDismissForPermanentChats; + + /// Callback function for uploading an image. final Future Function(Uint8List image)? onUploadImage; + + /// Callback function for submitting a message. final Future Function(String text)? onMessageSubmit; /// Called after a new message is sent. This can be used to do something /// extra like sending a push notification. final Function(String chatId)? afterMessageSent; + + /// Callback function triggered when a chat is read. final Future Function(ChatModel chat)? onReadChat; + + /// Callback function triggered when creating a chat. final Function(ChatUserModel)? onPressCreateChat; + + /// Builder for chat options based on context. final ChatOptions Function(BuildContext context) chatOptionsBuilder; /// If true, the user will be routed to the new chat screen if there are /// no chats. final bool routeToNewChatIfEmpty; + + /// The size of each page of messages. final int messagePageSize; + /// Dialog for confirming chat deletion. final Future Function(BuildContext, ChatModel)? deleteChatDialog; + + /// Callback function triggered when chat title is pressed. final Function(BuildContext context, ChatModel chat)? onPressChatTitle; + + /// Color of icons. final Color? iconColor; + + /// Builder for the chat page. final Widget Function(BuildContext context, Widget child)? chatPageBuilder; + + /// Callback function triggered when starting a chat. final Function()? onPressStartChat; + + /// Callback function triggered when user profile is pressed. final Function()? onPressUserProfile; } diff --git a/packages/flutter_chat/lib/src/routes.dart b/packages/flutter_chat/lib/src/routes.dart index 32e2a57..cad8ae1 100644 --- a/packages/flutter_chat/lib/src/routes.dart +++ b/packages/flutter_chat/lib/src/routes.dart @@ -2,12 +2,19 @@ // // SPDX-License-Identifier: BSD-3-Clause +/// Provides route paths for the chat user story. mixin ChatUserStoryRoutes { static const String chatScreen = '/chat'; + + /// Constructs the path for the chat detail view. static String chatDetailViewPath(String chatId) => '/chat-detail/$chatId'; + static const String chatDetailScreen = '/chat-detail/:id'; static const String newChatScreen = '/new-chat'; + + /// Constructs the path for the chat profile screen. static String chatProfileScreenPath(String chatId, String? userId) => '/chat-profile/$chatId/$userId'; + static const String chatProfileScreen = '/chat-profile/:id/:userId'; } diff --git a/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart b/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart index 938cd76..1aa0290 100644 --- a/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart +++ b/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart @@ -4,8 +4,10 @@ import 'package:flutter/material.dart'; +/// Options for Firebase chat configuration. @immutable class FirebaseChatOptions { + /// Creates a new instance of `FirebaseChatOptions`. const FirebaseChatOptions({ this.groupChatsCollectionName = 'group_chats', this.chatsCollectionName = 'chats', @@ -15,15 +17,26 @@ class FirebaseChatOptions { this.userChatsCollectionName = 'chats', }); + /// The collection name for group chats. final String groupChatsCollectionName; + + /// The collection name for chats. final String chatsCollectionName; + + /// The collection name for messages. final String messagesCollectionName; + + /// The collection name for users. final String usersCollectionName; + + /// The collection name for chat metadata. final String chatsMetaDataCollectionName; - ///This is the collection inside the user document. + /// The collection name for user chats. final String userChatsCollectionName; + /// Creates a copy of this FirebaseChatOptions but with the given fields + /// replaced with the new values. FirebaseChatOptions copyWith({ String? groupChatsCollectionName, String? chatsCollectionName, diff --git a/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart index 02fd8a1..4a579cc 100644 --- a/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart +++ b/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart @@ -6,8 +6,10 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'package:flutter_chat_firebase/dto/firebase_message_document.dart'; +/// Represents a chat document in Firebase. @immutable class FirebaseChatDocument { + /// Creates a new instance of `FirebaseChatDocument`. const FirebaseChatDocument({ required this.personal, required this.canBeDeleted, @@ -19,6 +21,7 @@ class FirebaseChatDocument { this.lastMessage, }); + /// Constructs a FirebaseChatDocument from JSON. FirebaseChatDocument.fromJson(Map json, this.id) : title = json['title'], imageUrl = json['image_url'], @@ -33,15 +36,31 @@ class FirebaseChatDocument { null, ); + /// The unique identifier of the chat document. final String? id; + + /// The title of the chat. final String? title; + + /// The image URL of the chat. final String? imageUrl; + + /// Indicates if the chat is personal. final bool personal; + + /// Indicates if the chat can be deleted. final bool canBeDeleted; + + /// The timestamp of when the chat was last used. final Timestamp? lastUsed; + + /// The list of users participating in the chat. final List users; + + /// The last message in the chat. final FirebaseMessageDocument? lastMessage; + /// Converts the FirebaseChatDocument to JSON format. Map toJson() => { 'title': title, 'image_url': imageUrl, diff --git a/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart index b396fd3..92cba7b 100644 --- a/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart +++ b/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart @@ -5,8 +5,10 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; +/// Represents a message document in Firebase. @immutable class FirebaseMessageDocument { + /// Creates a new instance of `FirebaseMessageDocument`. const FirebaseMessageDocument({ required this.sender, required this.timestamp, @@ -15,18 +17,29 @@ class FirebaseMessageDocument { this.imageUrl, }); + /// Constructs a FirebaseMessageDocument from JSON. FirebaseMessageDocument.fromJson(Map json, this.id) : sender = json['sender'], text = json['text'], imageUrl = json['image_url'], timestamp = json['timestamp']; + /// The unique identifier of the message document. final String? id; + + /// The sender of the message. final String sender; + + /// The text content of the message. final String? text; + + /// The image URL of the message. final String? imageUrl; + + /// The timestamp of when the message was sent. final Timestamp timestamp; + /// Converts the FirebaseMessageDocument to JSON format. Map toJson() => { 'sender': sender, 'text': text, diff --git a/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart index b3db5ca..8d50464 100644 --- a/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart +++ b/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart @@ -4,8 +4,10 @@ import 'package:flutter/material.dart'; +/// Represents a user document in Firebase. @immutable class FirebaseUserDocument { + /// Creates a new instance of `FirebaseUserDocument`. const FirebaseUserDocument({ this.firstName, this.lastName, @@ -13,6 +15,7 @@ class FirebaseUserDocument { this.id, }); + /// Constructs a FirebaseUserDocument from JSON. FirebaseUserDocument.fromJson( Map json, String id, @@ -26,11 +29,19 @@ class FirebaseUserDocument { json['image_url'] == null ? null : json['image_url']! as String, ); + /// The first name of the user. final String? firstName; + + /// The last name of the user. final String? lastName; + + /// The image URL of the user. final String? imageUrl; + + /// The unique identifier of the user document. final String? id; + /// Converts the FirebaseUserDocument to JSON format. Map toJson() => { 'first_name': firstName, 'last_name': lastName, diff --git a/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart index 6c2de13..287d092 100644 --- a/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart +++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart @@ -13,9 +13,16 @@ import 'package:flutter_chat_firebase/dto/firebase_message_document.dart'; import 'package:flutter_chat_interface/flutter_chat_interface.dart'; import 'package:uuid/uuid.dart'; +/// Service class for managing chat details using Firebase. class FirebaseChatDetailService with ChangeNotifier implements ChatDetailService { + /// Constructor for FirebaseChatDetailService. + /// + /// [userService]: Instance of ChatUserService. + /// [app]: Optional FirebaseApp instance, defaults to Firebase.app(). + /// [options]: Optional FirebaseChatOptions instance, + /// defaults to FirebaseChatOptions(). FirebaseChatDetailService({ required ChatUserService userService, FirebaseApp? app, @@ -123,6 +130,10 @@ class FirebaseChatDetailService } } + /// Sends a text message to a chat. + /// + /// [text]: The text message to send. + /// [chatId]: The ID of the chat where the message will be sent. @override Future sendTextMessage({ required String text, @@ -135,6 +146,10 @@ class FirebaseChatDetailService }, ); + /// Sends an image message to a chat. + /// + /// [chatId]: The ID of the chat where the message will be sent. + /// [image]: The image data to send. @override Future sendImageMessage({ required String chatId, @@ -157,6 +172,9 @@ class FirebaseChatDetailService ); } + /// Retrieves a stream of messages for a chat. + /// + /// [chatId]: The ID of the chat. @override Stream> getMessagesStream(String chatId) { timestampToFilter = DateTime.now(); @@ -227,6 +245,7 @@ class FirebaseChatDetailService return _controller!.stream; } + /// Stops listening for messages. @override Future stopListeningForMessages() async { await _subscription?.cancel(); @@ -235,6 +254,10 @@ class FirebaseChatDetailService _controller = null; } + /// Fetches more messages for a chat. + /// + /// [pageSize]: The number of messages to fetch. + /// [chatId]: The ID of the chat. @override Future fetchMoreMessage(int pageSize, String chatId) async { if (lastChat == null) { @@ -313,6 +336,7 @@ class FirebaseChatDetailService notifyListeners(); } + /// Retrieves the list of messages. @override List getMessages() => _cumulativeMessages; } diff --git a/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart index 93a31ca..a5a15b4 100644 --- a/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart +++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart @@ -12,12 +12,19 @@ import 'package:flutter_chat_firebase/config/firebase_chat_options.dart'; import 'package:flutter_chat_firebase/dto/firebase_chat_document.dart'; import 'package:flutter_chat_interface/flutter_chat_interface.dart'; +/// Service class for managing chat overviews using Firebase. class FirebaseChatOverviewService implements ChatOverviewService { late FirebaseFirestore _db; late FirebaseStorage _storage; late ChatUserService _userService; late FirebaseChatOptions _options; + /// Constructor for FirebaseChatOverviewService. + /// + /// [userService]: Instance of ChatUserService. + /// [app]: Optional FirebaseApp instance, defaults to Firebase.app(). + /// [options]: Optional FirebaseChatOptions instance, defaults + /// to FirebaseChatOptions(). FirebaseChatOverviewService({ required ChatUserService userService, FirebaseApp? app, @@ -45,6 +52,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { return snapshots.data()?['amount_unread_messages']; } + /// Retrieves a stream of chat overviews. @override Stream> getChatsStream() { StreamSubscription? chatSubscription; @@ -199,6 +207,9 @@ class FirebaseChatOverviewService implements ChatOverviewService { return controller.stream; } + /// Retrieves a chat by the given user. + /// + /// [user]: The user associated with the chat. @override Future getChatByUser(ChatUserModel user) async { var currentUser = await _userService.getCurrentUser(); @@ -217,6 +228,9 @@ class FirebaseChatOverviewService implements ChatOverviewService { ); } + /// Retrieves a chat by the given ID. + /// + /// [chatId]: The ID of the chat. @override Future getChatById(String chatId) async { var currentUser = await _userService.getCurrentUser(); @@ -266,6 +280,9 @@ class FirebaseChatOverviewService implements ChatOverviewService { } } + /// Deletes the given chat. + /// + /// [chat]: The chat to be deleted. @override Future deleteChat(ChatModel chat) async { var chatCollection = await _db @@ -308,6 +325,9 @@ class FirebaseChatOverviewService implements ChatOverviewService { } } + /// Stores the given chat if it does not exist already. + /// + /// [chat]: The chat to be stored. @override Future storeChatIfNot(ChatModel chat) async { if (chat.id == null) { @@ -392,6 +412,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { return chat; } + /// Retrieves a stream of the count of unread chats. @override Stream getUnreadChatsCountStream() { // open a stream to the user's chats collection and listen to changes in @@ -428,6 +449,9 @@ class FirebaseChatOverviewService implements ChatOverviewService { return controller.stream; } + /// Marks a chat as read. + /// + /// [chat]: The chat to be marked as read. @override Future readChat(ChatModel chat) async { // set the amount of read chats to the amount of messages in the chat @@ -436,6 +460,7 @@ class FirebaseChatOverviewService implements ChatOverviewService { return; } // set the amount of unread messages to 0 + await _db .collection(_options.usersCollectionName) .doc(currentUser!.id) diff --git a/packages/flutter_chat_firebase/lib/service/firebase_chat_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_service.dart index c3e6d2b..e74a5e5 100644 --- a/packages/flutter_chat_firebase/lib/service/firebase_chat_service.dart +++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_service.dart @@ -3,6 +3,7 @@ import 'package:flutter_chat_firebase/config/firebase_chat_options.dart'; import 'package:flutter_chat_firebase/flutter_chat_firebase.dart'; import 'package:flutter_chat_interface/flutter_chat_interface.dart'; +/// Service class for managing chat services using Firebase. class FirebaseChatService implements ChatService { FirebaseChatService({ this.options, @@ -29,10 +30,19 @@ class FirebaseChatService implements ChatService { ); } + /// The options for configuring Firebase Chat. final FirebaseChatOptions? options; + + /// The Firebase app instance. final FirebaseApp? app; + + /// The service for managing chat details. ChatDetailService? firebaseChatDetailService; + + /// The service for managing chat overviews. ChatOverviewService? firebaseChatOverviewService; + + /// The service for managing chat users. ChatUserService? firebaseChatUserService; @override diff --git a/packages/flutter_chat_firebase/lib/service/firebase_chat_user_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_user_service.dart index 5d81ccb..e7f8a85 100644 --- a/packages/flutter_chat_firebase/lib/service/firebase_chat_user_service.dart +++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_user_service.dart @@ -9,7 +9,12 @@ import 'package:flutter_chat_firebase/config/firebase_chat_options.dart'; import 'package:flutter_chat_firebase/dto/firebase_user_document.dart'; import 'package:flutter_chat_interface/flutter_chat_interface.dart'; +/// Service class for managing chat users using Firebase. class FirebaseChatUserService implements ChatUserService { + /// Constructor for FirebaseChatUserService. + /// + /// [app]: The Firebase app instance. + /// [options]: The options for configuring Firebase Chat. FirebaseChatUserService({ FirebaseApp? app, FirebaseChatOptions? options, @@ -21,13 +26,22 @@ class FirebaseChatUserService implements ChatUserService { _options = options ?? const FirebaseChatOptions(); } + /// The Firebase Firestore instance. late FirebaseFirestore _db; + + /// The Firebase Authentication instance. late FirebaseAuth _auth; + + /// The options for configuring Firebase Chat. late FirebaseChatOptions _options; + /// The current user. ChatUserModel? _currentUser; + + /// Map to cache user models. final Map _users = {}; + /// Collection reference for users. CollectionReference get _userCollection => _db .collection(_options.usersCollectionName) .withConverter( diff --git a/packages/flutter_chat_interface/lib/src/model/chat.dart b/packages/flutter_chat_interface/lib/src/model/chat.dart index fa3bfd9..18636dc 100644 --- a/packages/flutter_chat_interface/lib/src/model/chat.dart +++ b/packages/flutter_chat_interface/lib/src/model/chat.dart @@ -14,7 +14,21 @@ abstract class ChatModelInterface { bool get canBeDeleted; } +/// A concrete implementation of [ChatModelInterface] representing a chat. class ChatModel implements ChatModelInterface { + /// Constructs a [ChatModel] instance. + /// + /// [id]: The ID of the chat. + /// + /// [messages]: The list of messages in the chat. + /// + /// [unreadMessages]: The number of unread messages in the chat. + /// + /// [lastUsed]: The timestamp when the chat was last used. + /// + /// [lastMessage]: The last message sent in the chat. + /// + /// [canBeDeleted]: Indicates whether the chat can be deleted. ChatModel({ this.id, this.messages = const [], @@ -26,14 +40,19 @@ class ChatModel implements ChatModelInterface { @override String? id; + @override final List? messages; + @override final int? unreadMessages; + @override final DateTime? lastUsed; + @override final ChatMessageModel? lastMessage; + @override final bool canBeDeleted; } diff --git a/packages/flutter_chat_interface/lib/src/model/chat_image_message.dart b/packages/flutter_chat_interface/lib/src/model/chat_image_message.dart index 37c2ac3..5fc089b 100644 --- a/packages/flutter_chat_interface/lib/src/model/chat_image_message.dart +++ b/packages/flutter_chat_interface/lib/src/model/chat_image_message.dart @@ -5,25 +5,44 @@ import 'package:flutter_chat_interface/flutter_chat_interface.dart'; +/// An abstract class defining the interface for an image message in a chat. abstract class ChatImageMessageModelInterface extends ChatMessageModel { + /// Constructs a [ChatImageMessageModelInterface] instance. + /// + /// [sender]: The sender of the message. + /// + /// [timestamp]: The timestamp when the message was sent. ChatImageMessageModelInterface({ required super.sender, required super.timestamp, }); + /// Returns the URL of the image associated with the message. String get imageUrl; } +/// A concrete implementation of [ChatImageMessageModelInterface] +/// representing an image message in a chat. class ChatImageMessageModel implements ChatImageMessageModelInterface { + /// Constructs a [ChatImageMessageModel] instance. + /// + /// [sender]: The sender of the message. + /// + /// [timestamp]: The timestamp when the message was sent. + /// + /// [imageUrl]: The URL of the image associated with the message. ChatImageMessageModel({ required this.sender, required this.timestamp, required this.imageUrl, }); + @override final ChatUserModel sender; + @override final DateTime timestamp; + @override final String imageUrl; } diff --git a/packages/flutter_chat_interface/lib/src/model/chat_message.dart b/packages/flutter_chat_interface/lib/src/model/chat_message.dart index b248127..7212144 100644 --- a/packages/flutter_chat_interface/lib/src/model/chat_message.dart +++ b/packages/flutter_chat_interface/lib/src/model/chat_message.dart @@ -10,7 +10,14 @@ abstract class ChatMessageModelInterface { DateTime get timestamp; } +/// A concrete implementation of [ChatMessageModelInterface] +/// representing a chat message. class ChatMessageModel implements ChatMessageModelInterface { + /// Constructs a [ChatMessageModel] instance. + /// + /// [sender]: The sender of the message. + /// + /// [timestamp]: The timestamp when the message was sent. ChatMessageModel({ required this.sender, required this.timestamp, @@ -18,6 +25,7 @@ class ChatMessageModel implements ChatMessageModelInterface { @override final ChatUserModel sender; + @override final DateTime timestamp; } diff --git a/packages/flutter_chat_interface/lib/src/model/chat_text_message.dart b/packages/flutter_chat_interface/lib/src/model/chat_text_message.dart index 18a6cdd..52b7b3d 100644 --- a/packages/flutter_chat_interface/lib/src/model/chat_text_message.dart +++ b/packages/flutter_chat_interface/lib/src/model/chat_text_message.dart @@ -14,16 +14,28 @@ abstract class ChatTextMessageModelInterface extends ChatMessageModel { String get text; } +/// A concrete implementation of [ChatTextMessageModelInterface] +/// representing a text message in a chat. class ChatTextMessageModel implements ChatTextMessageModelInterface { + /// Constructs a [ChatTextMessageModel] instance. + /// + /// [sender]: The sender of the message. + /// + /// [timestamp]: The timestamp when the message was sent. + /// + /// [text]: The text content of the message. ChatTextMessageModel({ required this.sender, required this.timestamp, required this.text, }); + @override final ChatUserModel sender; + @override final DateTime timestamp; + @override final String text; } diff --git a/packages/flutter_chat_interface/lib/src/model/chat_user.dart b/packages/flutter_chat_interface/lib/src/model/chat_user.dart index 68a7e99..e97226a 100644 --- a/packages/flutter_chat_interface/lib/src/model/chat_user.dart +++ b/packages/flutter_chat_interface/lib/src/model/chat_user.dart @@ -12,7 +12,18 @@ abstract class ChatUserModelInterface { String? get fullName; } +/// A concrete implementation of [ChatUserModelInterface] +/// representing a chat user. class ChatUserModel implements ChatUserModelInterface { + /// Constructs a [ChatUserModel] instance. + /// + /// [id]: The ID of the user. + /// + /// [firstName]: The first name of the user. + /// + /// [lastName]: The last name of the user. + /// + /// [imageUrl]: The URL of the user's image. ChatUserModel({ this.id, this.firstName, @@ -22,12 +33,16 @@ class ChatUserModel implements ChatUserModelInterface { @override final String? id; + @override final String? firstName; + @override final String? lastName; + @override final String? imageUrl; + @override String? get fullName { var fullName = ''; diff --git a/packages/flutter_chat_interface/lib/src/model/group_chat.dart b/packages/flutter_chat_interface/lib/src/model/group_chat.dart index 742c102..f94803a 100644 --- a/packages/flutter_chat_interface/lib/src/model/group_chat.dart +++ b/packages/flutter_chat_interface/lib/src/model/group_chat.dart @@ -33,6 +33,25 @@ abstract class GroupChatModelInterface extends ChatModel { } class GroupChatModel implements GroupChatModelInterface { + /// Constructs a [GroupChatModel] instance. + /// + /// [id]: The ID of the chat. + /// + /// [messages]: The list of messages in the chat. + /// + /// [unreadMessages]: The number of unread messages in the chat. + /// + /// [lastUsed]: The timestamp when the chat was last used. + /// + /// [lastMessage]: The last message sent in the chat. + /// + /// [title]: The title of the group chat. + /// + /// [imageUrl]: The URL of the image associated with the group chat. + /// + /// [users]: The list of users participating in the group chat. + /// + /// [canBeDeleted]: Indicates whether the chat can be deleted. GroupChatModel({ required this.canBeDeleted, required this.title, diff --git a/packages/flutter_chat_interface/lib/src/model/personal_chat.dart b/packages/flutter_chat_interface/lib/src/model/personal_chat.dart index 1fd82f5..7ae7732 100644 --- a/packages/flutter_chat_interface/lib/src/model/personal_chat.dart +++ b/packages/flutter_chat_interface/lib/src/model/personal_chat.dart @@ -29,6 +29,21 @@ abstract class PersonalChatModelInterface extends ChatModel { } class PersonalChatModel implements PersonalChatModelInterface { + /// Constructs a [PersonalChatModel] instance. + /// + /// [user]: The user involved in the personal chat. + /// + /// [id]: The ID of the chat. + /// + /// [messages]: The list of messages in the chat. + /// + /// [unreadMessages]: The number of unread messages in the chat. + /// + /// [lastUsed]: The timestamp when the chat was last used. + /// + /// [lastMessage]: The last message sent in the chat. + /// + /// [canBeDeleted]: Indicates whether the chat can be deleted. PersonalChatModel({ required this.user, this.id, diff --git a/packages/flutter_chat_interface/lib/src/service/chat_detail_service.dart b/packages/flutter_chat_interface/lib/src/service/chat_detail_service.dart index d7e9e28..2fb39e3 100644 --- a/packages/flutter_chat_interface/lib/src/service/chat_detail_service.dart +++ b/packages/flutter_chat_interface/lib/src/service/chat_detail_service.dart @@ -2,24 +2,31 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_chat_interface/flutter_chat_interface.dart'; +/// An abstract class defining the interface for a chat detail service. abstract class ChatDetailService with ChangeNotifier { + /// Sends a text message to the specified chat. Future sendTextMessage({ required String chatId, required String text, }); + /// Sends an image message to the specified chat. Future sendImageMessage({ required String chatId, required Uint8List image, }); + /// Retrieves a stream of messages for the specified chat. Stream> getMessagesStream( String chatId, ); + /// Fetches more messages for the specified chat with a given page size. Future fetchMoreMessage(int pageSize, String chatId); + /// Retrieves the list of messages for the chat. List getMessages(); + /// Stops listening for messages. void stopListeningForMessages(); } diff --git a/packages/flutter_chat_local/lib/service/local_chat_detail_service.dart b/packages/flutter_chat_local/lib/service/local_chat_detail_service.dart index abc7458..c9c5cb7 100644 --- a/packages/flutter_chat_local/lib/service/local_chat_detail_service.dart +++ b/packages/flutter_chat_local/lib/service/local_chat_detail_service.dart @@ -4,12 +4,24 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_chat_interface/flutter_chat_interface.dart'; import 'package:flutter_chat_local/local_chat_service.dart'; +/// A class providing local chat detail service implementation. class LocalChatDetailService with ChangeNotifier implements ChatDetailService { + /// Constructs a [LocalChatDetailService] instance. + /// + /// [chatOverviewService]: The chat overview service. LocalChatDetailService({required this.chatOverviewService}); + + /// The chat overview service. final ChatOverviewService chatOverviewService; + + /// The list of cumulative messages. final List _cumulativeMessages = []; + + /// The stream controller for messages. final StreamController> _controller = StreamController>.broadcast(); + + /// The subscription for the stream. late StreamSubscription? _subscription; @override diff --git a/packages/flutter_chat_local/lib/service/local_chat_overview_service.dart b/packages/flutter_chat_local/lib/service/local_chat_overview_service.dart index 2ad3b65..88a3379 100644 --- a/packages/flutter_chat_local/lib/service/local_chat_overview_service.dart +++ b/packages/flutter_chat_local/lib/service/local_chat_overview_service.dart @@ -3,12 +3,17 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter_chat_interface/flutter_chat_interface.dart'; +/// A class providing local chat overview service implementation. class LocalChatOverviewService with ChangeNotifier implements ChatOverviewService { + /// The list of personal chat models. final List _chats = []; + + /// Retrieves the list of personal chat models. List get chats => _chats; + /// The stream controller for chats. final StreamController> _chatsController = StreamController>.broadcast(); diff --git a/packages/flutter_chat_local/lib/service/local_chat_service.dart b/packages/flutter_chat_local/lib/service/local_chat_service.dart index 992c3d5..acacb02 100644 --- a/packages/flutter_chat_local/lib/service/local_chat_service.dart +++ b/packages/flutter_chat_local/lib/service/local_chat_service.dart @@ -3,24 +3,36 @@ import 'package:flutter_chat_local/service/local_chat_detail_service.dart'; import 'package:flutter_chat_local/service/local_chat_overview_service.dart'; import 'package:flutter_chat_local/service/local_chat_user_service.dart'; +/// Service class for managing local chat services. class LocalChatService implements ChatService { + /// Constructor for LocalChatService. + /// + /// [localChatDetailService]: Optional local ChatDetailService instance, + /// defaults to LocalChatDetailService. + /// [localChatOverviewService]: Optional local ChatOverviewService instance, + /// defaults to LocalChatOverviewService. + /// [localChatUserService]: Optional local ChatUserService instance, + /// defaults to LocalChatUserService. LocalChatService({ this.localChatDetailService, this.localChatOverviewService, this.localChatUserService, }) { - { - localChatOverviewService ??= LocalChatOverviewService(); - localChatDetailService ??= LocalChatDetailService( - chatOverviewService: localChatOverviewService!, - ); + localChatOverviewService ??= LocalChatOverviewService(); + localChatDetailService ??= LocalChatDetailService( + chatOverviewService: localChatOverviewService!, + ); - localChatUserService ??= LocalChatUserService(); - } + localChatUserService ??= LocalChatUserService(); } + /// The local chat detail service. ChatDetailService? localChatDetailService; + + /// The local chat overview service. ChatOverviewService? localChatOverviewService; + + /// The local chat user service. ChatUserService? localChatUserService; @override diff --git a/packages/flutter_chat_local/lib/service/local_chat_user_service.dart b/packages/flutter_chat_local/lib/service/local_chat_user_service.dart index b5a69d6..0836b48 100644 --- a/packages/flutter_chat_local/lib/service/local_chat_user_service.dart +++ b/packages/flutter_chat_local/lib/service/local_chat_user_service.dart @@ -1,6 +1,8 @@ import 'package:flutter_chat_interface/flutter_chat_interface.dart'; +/// Service class for managing local chat users. class LocalChatUserService implements ChatUserService { + /// List of predefined chat users. List users = [ ChatUserModel( id: '1', @@ -15,6 +17,7 @@ class LocalChatUserService implements ChatUserService { imageUrl: 'https://picsum.photos/200/300', ), ]; + @override Future> getAllUsers() => Future.value(users); diff --git a/packages/flutter_chat_view/lib/src/components/chat_bottom.dart b/packages/flutter_chat_view/lib/src/components/chat_bottom.dart index b1bc242..31e74d1 100644 --- a/packages/flutter_chat_view/lib/src/components/chat_bottom.dart +++ b/packages/flutter_chat_view/lib/src/components/chat_bottom.dart @@ -16,11 +16,22 @@ class ChatBottom extends StatefulWidget { super.key, }); + /// Callback function invoked when a message is submitted. final Future Function(String text) onMessageSubmit; + + /// The builder function for the message input. final TextInputBuilder messageInputBuilder; + + /// Callback function invoked when the select image button is pressed. final VoidCallback? onPressSelectImage; + + /// The chat model. final ChatModel chat; + + /// The translations for the chat. final ChatTranslations translations; + + /// The color of the icons. final Color? iconColor; @override 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 ca7d370..5838096 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 @@ -18,12 +18,21 @@ class ChatDetailRow extends StatefulWidget { super.key, }); + /// The translations for the chat. final ChatTranslations translations; + + /// The chat message model. final ChatMessageModel message; + + /// The builder function for user avatar. final UserAvatarBuilder userAvatarBuilder; - final bool showTime; + + /// The previous chat message model. final ChatMessageModel? previousMessage; + /// Flag indicating whether to show the time. + final bool showTime; + @override State createState() => _ChatDetailRowState(); } diff --git a/packages/flutter_chat_view/lib/src/components/chat_image.dart b/packages/flutter_chat_view/lib/src/components/chat_image.dart index f10fe08..d89eee4 100644 --- a/packages/flutter_chat_view/lib/src/components/chat_image.dart +++ b/packages/flutter_chat_view/lib/src/components/chat_image.dart @@ -5,14 +5,23 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +/// A stateless widget representing an image in the chat. class ChatImage extends StatelessWidget { + /// Constructs a [ChatImage] widget. + /// + /// [image]: The URL of the image. + /// + /// [size]: The size of the image widget. const ChatImage({ required this.image, this.size = 40, super.key, }); + /// The URL of the image. final String image; + + /// The size of the image widget. final double size; @override @@ -24,7 +33,7 @@ class ChatImage extends StatelessWidget { ), width: size, height: size, - child: image != '' + child: image.isNotEmpty ? CachedNetworkImage( imageUrl: image, fit: BoxFit.cover, 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 5b87f54..5acfc46 100644 --- a/packages/flutter_chat_view/lib/src/components/chat_row.dart +++ b/packages/flutter_chat_view/lib/src/components/chat_row.dart @@ -13,12 +13,22 @@ class ChatRow extends StatelessWidget { this.avatar, super.key, }); + + /// The title of the chat. final String title; + + /// The number of unread messages in the chat. final int unreadMessages; - final Widget? avatar; - final String? subTitle; + + /// The last time the chat was used. final String? lastUsed; + /// The subtitle of the chat. + final String? subTitle; + + /// The avatar associated with the chat. + final Widget? avatar; + @override Widget build(BuildContext context) => Row( crossAxisAlignment: CrossAxisAlignment.center, 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 dc5e1b3..d8c9e43 100644 --- a/packages/flutter_chat_view/lib/src/config/chat_options.dart +++ b/packages/flutter_chat_view/lib/src/config/chat_options.dart @@ -19,13 +19,28 @@ class ChatOptions { this.noChatsPlaceholderBuilder = _createNoChatsPlaceholder, }); + /// Builder function for the new chat button. final ButtonBuilder newChatButtonBuilder; + + /// Builder function for the message input field. final TextInputBuilder messageInputBuilder; + + /// Builder function for the container wrapping each chat row. final ContainerBuilder chatRowContainerBuilder; + + /// Builder function for the container wrapping the image picker. final ImagePickerContainerBuilder imagePickerContainerBuilder; + + /// Builder function for the scaffold containing the chat view. final ScaffoldBuilder scaffoldBuilder; + + /// Builder function for the user avatar. final UserAvatarBuilder userAvatarBuilder; + + /// Builder function for the group avatar. final GroupAvatarBuilder groupAvatarBuilder; + + /// Builder function for the placeholder shown when no chats are available. final NoChatsPlaceholderBuilder noChatsPlaceholderBuilder; } 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 4a1c2fd..2c71f5a 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 @@ -13,10 +13,19 @@ class ChatProfileScreen extends StatefulWidget { super.key, }); + /// Translations for the chat. final ChatTranslations translations; + + /// Chat service instance. final ChatService chatService; + + /// ID of the chat. final String chatId; + + /// ID of the user (optional). final String? userId; + + /// Callback function for tapping on a user. final Function(String userId) onTapUser; @override 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 afae69a..f96f44d 100644 --- a/packages/flutter_chat_view/lib/src/screens/chat_screen.dart +++ b/packages/flutter_chat_view/lib/src/screens/chat_screen.dart @@ -24,19 +24,33 @@ class ChatScreen extends StatefulWidget { super.key, }); + /// Chat options. final ChatOptions options; - final ChatTranslations translations; + + /// Chat service instance. final ChatService service; + + /// Callback function for starting a chat. final Function()? onPressStartChat; - final Function()? onNoChats; - final void Function(ChatModel chat) onDeleteChat; + + /// Callback function for pressing on a chat. final void Function(ChatModel chat) onPressChat; - /// Disable the swipe to dismiss feature for chats that are not deletable + /// Callback function for deleting a chat. + final void Function(ChatModel chat) onDeleteChat; + + /// Callback function for handling when there are no chats. + final Function()? onNoChats; + + /// Method to optionally change the bottom sheet dialog. + final Future Function(BuildContext, ChatModel)? deleteChatDialog; + + /// Translations for the chat. + final ChatTranslations translations; + + /// Disables the swipe to dismiss feature for chats that are not deletable. final bool disableDismissForPermanentChats; - /// Method to optionally change the bottomsheetdialog - final Future Function(BuildContext, ChatModel)? deleteChatDialog; @override State createState() => _ChatScreenState(); } 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 c4eef9b..07b6d79 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 @@ -14,11 +14,18 @@ class NewChatScreen extends StatefulWidget { super.key, }); + /// Chat options. final ChatOptions options; - final ChatTranslations translations; + + /// Chat service instance. final ChatService service; + + /// Callback function for creating a new chat with a user. final Function(ChatUserModel) onPressCreateChat; + /// Translations for the chat. + final ChatTranslations translations; + @override State createState() => _NewChatScreenState(); }