diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 90c096a..4404fba 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -2,22 +2,21 @@ version: 2
updates:
- package-ecosystem: "pub"
- directory: "/packages/flutter_community_chat"
+ directory: "/packages/flutter_chat"
schedule:
interval: "weekly"
- package-ecosystem: "pub"
- directory: "/packages/flutter_community_chat_firebase"
+ directory: "/packages/flutter_chat_firebase"
schedule:
interval: "weekly"
- package-ecosystem: "pub"
- directory: "/packages/flutter_community_chat_interface"
+ directory: "/packages/flutter_chat_interface"
schedule:
interval: "weekly"
- package-ecosystem: "pub"
- directory: "/packages/flutter_community_chat_view"
+ directory: "/packages/flutter_chat_view"
schedule:
interval: "weekly"
-
diff --git a/.gitignore b/.gitignore
index ec070e9..7a871bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,9 +37,9 @@ build/
.metadata
pubspec.lock
-packages/flutter_community_chat/pubspec.lock
-packages/flutter_community_chat_firebase/pubspec.lock
-packages/flutter_community_chat_interface/pubspec.lock
-packages/flutter_community_chat_view/pubspec.lock
+packages/flutter_chat/pubspec.lock
+packages/flutter_chat_firebase/pubspec.lock
+packages/flutter_chat_interface/pubspec.lock
+packages/flutter_chat_view/pubspec.lock
pubspec_overrides.yaml
diff --git a/README.md b/README.md
index ac12805..bb0fe2e 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1,52 @@
-# Flutter Community Chat
+# Flutter Chat
-Flutter Community Chat is a package which gives the possibility to add a (personal or group) chat to your Flutter-application. Default this package adds support for a Firebase back-end. You can add your custom back-end (like a Websocket-API) by extending the `CommunityChatInterface` interface from the `flutter_community_chat_interface` package.
+Flutter Chat is a package which gives the possibility to add a (personal or group) chat to your Flutter-application. Default this package adds support for a Firebase back-end. You can add your custom back-end (like a Websocket-API) by extending the `ChatInterface` interface from the `flutter_chat_interface` package.
-
+
Figma Design that defines this component (only accessible for Iconica developers): https://www.figma.com/file/4WkjwynOz5wFeFBRqTHPeP/Iconica-Design-System?type=design&node-id=357%3A3342&mode=design&t=XulkAJNPQ32ARxWh-1
Figma clickable prototype that demonstrates this component (only accessible for Iconica developers): https://www.figma.com/proto/PRJoVXQ5aOjAICfkQdAq2A/Iconica-User-Stories?page-id=1%3A2&type=design&node-id=56-6837&viewport=279%2C2452%2C0.2&t=E7Al3Xng2WXnbCEQ-1&scaling=scale-down&starting-point-node-id=56%3A6837&mode=design
## Setup
-To use this package, add flutter_community_chat as a dependency in your pubspec.yaml file:
+To use this package, add flutter_chat as a dependency in your pubspec.yaml file:
```
- flutter_community_chat:
+ flutter_chat:
git:
- url: https://github.com/Iconica-Development/flutter_community_chat.git
- path: packages/flutter_community_chat
+ url: https://github.com/Iconica-Development/flutter_chat
+ path: packages/flutter_chat
```
If you are going to use Firebase as the back-end of the Community Chat, you should also add the following package as a dependency to your pubspec.yaml file:
```
- flutter_community_chat_firebase:
+ flutter_chat_firebase:
git:
- url: https://github.com/Iconica-Development/flutter_community_chat.git
- path: packages/flutter_community_chat_firebase
+ url: https://github.com/Iconica-Development/flutter_chat
+ path: packages/flutter_chat_firebase
```
Create a Firebase project for your application and add firebase firestore and storage.
+To use the camera or photo library to send photos add the following to your project:
+
+For ios add the following lines to your info.plist:
+
+```
+ NSCameraUsageDescription
+ Access camera
+ NSPhotoLibraryUsageDescription
+ Library
+```
+
+For android add the following lines to your AndroidManifest.xml:
+
+```
+
+
+```
+
## How to use
To use the module within your Flutter-application with predefined `Go_router` routes you should add the following:
@@ -37,18 +55,15 @@ Add go_router as dependency to your project.
Add the following configuration to your flutter_application:
```
-List getCommunityChatRoutes() => getCommunityChatStoryRoutes(
- CommunityChatUserStoryConfiguration(
- service: FirebaseChatService(userService: FirebaseUserService()),
- userService: FirebaseUserService(),
- messageService:
- FirebaseMessageService(userService: FirebaseUserService()),
+List getChatRoutes() => getChatStoryRoutes(
+ ChatUserStoryConfiguration(
+ chatService: chatService,
chatOptionsBuilder: (ctx) => const ChatOptions(),
),
);
```
-Add the `getCommunityChatRoutes()` to your go_router routes like so:
+Add the `getChatRoutes()` to your go_router routes like so:
```
final GoRouter _router = GoRouter(
@@ -61,13 +76,14 @@ final GoRouter _router = GoRouter(
);
},
),
- ...getCommunityChatRoutes()
+ ...getChatRoutes()
],
);
```
To use the module within your Flutter-application without predefined `Go_router` routes add the following code to the build-method of a chosen widget:
+The `ChatScreen` shows all chats that you currently have with their latest messages.
To add the `ChatScreen` add the following code:
````
@@ -81,6 +97,7 @@ ChatScreen(
);
```
+The `ChatDetailScreen` shows the messages that are in the current chat you selected.
To add the `ChatDetailScreen` add the following code:
```
@@ -90,12 +107,10 @@ ChatDetailScreen(
onUploadImage: onUploadImage,
onReadChat: onReadChat,
service: service,
- chatUserService: chatUserService,
- messageService: messageService,
- pageSize: pageSize,
);
```
+On the `NewChatScreen` you can select a person to chat.
To add the `NewChatScreen` add the following code:
```
@@ -103,10 +118,23 @@ NewChatScreen(
options: options,
onPressCreateChat: onPressCreateChat,
service: service,
- userService: userService,
);
```
+The `ChatEntryWidget` is a widget you can put anywhere in your app.
+It displays the amount of unread messages you currently have.
+You can choose to add a onTap to the `ChatEntryWidget` so it routes to the `ChatScreen`,
+where all your chats are shown.
+
+To add the `ChatEntryWidget` add the follwoing code:
+
+```
+ChatEntryWidget(
+ chatService: chatService,
+ onTap: onTap,
+);
+```
+
The `ChatOptions` has its own parameters, as specified below:
| Parameter | Explanation |
|-----------|-------------|
@@ -121,13 +149,13 @@ The `ImagePickerTheme` also has its own parameters, how to use these parameters
## Issues
-Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Iconica-Development/flutter_community_chat/pulls) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [support@iconica.nl](mailto:support@iconica.nl).
+Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Iconica-Development/flutter_chat/pulls) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [support@iconica.nl](mailto:support@iconica.nl).
## 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_community_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
-This `flutter_community_chat` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at
+This `flutter_chat` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at
````
diff --git a/melos.yaml b/melos.yaml
index 64b1af5..c49d6d4 100644
--- a/melos.yaml
+++ b/melos.yaml
@@ -1,4 +1,4 @@
-name: flutter_community_chat
+name: flutter_chat
packages:
- packages/**
@@ -21,7 +21,7 @@ scripts:
run: melos exec -c 1 -- "flutter pub upgrade"
create:
- # run create in the example folder of flutter_community_chat_view
+ # run create in the example folder of flutter_chat_view
run: melos exec --scope="*example*" -c 1 -- "flutter create ."
analyze:
diff --git a/packages/flutter_community_chat/analysis_options.yaml b/packages/flutter_chat/analysis_options.yaml
similarity index 100%
rename from packages/flutter_community_chat/analysis_options.yaml
rename to packages/flutter_chat/analysis_options.yaml
diff --git a/packages/flutter_chat/lib/flutter_chat.dart b/packages/flutter_chat/lib/flutter_chat.dart
new file mode 100644
index 0000000..7082893
--- /dev/null
+++ b/packages/flutter_chat/lib/flutter_chat.dart
@@ -0,0 +1,11 @@
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+library flutter_chat;
+
+export 'package:flutter_chat_view/flutter_chat_view.dart';
+export 'package:flutter_chat_interface/flutter_chat_interface.dart';
+export 'package:flutter_chat/src/routes.dart';
+export 'package:flutter_chat/src/models/chat_configuration.dart';
+export 'package:flutter_chat/src/flutter_chat_userstory.dart';
diff --git a/packages/flutter_community_chat/lib/src/flutter_community_chat_userstory.dart b/packages/flutter_chat/lib/src/flutter_chat_userstory.dart
similarity index 52%
rename from packages/flutter_community_chat/lib/src/flutter_community_chat_userstory.dart
rename to packages/flutter_chat/lib/src/flutter_chat_userstory.dart
index 9fc0052..c92b79f 100644
--- a/packages/flutter_community_chat/lib/src/flutter_community_chat_userstory.dart
+++ b/packages/flutter_chat/lib/src/flutter_chat_userstory.dart
@@ -3,40 +3,35 @@
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat/src/models/community_chat_configuration.dart';
-import 'package:flutter_community_chat/src/go_router.dart';
-import 'package:flutter_community_chat/src/routes.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
+import 'package:flutter_chat/flutter_chat.dart';
+import 'package:flutter_chat/src/go_router.dart';
import 'package:go_router/go_router.dart';
-List getCommunityChatStoryRoutes(
- CommunityChatUserStoryConfiguration configuration,
+List getChatStoryRoutes(
+ ChatUserStoryConfiguration configuration,
) =>
[
GoRoute(
- path: CommunityChatUserStoryRoutes.chatScreen,
+ path: ChatUserStoryRoutes.chatScreen,
pageBuilder: (context, state) {
var chatScreen = ChatScreen(
- pageSize: configuration.pageSize,
- service: configuration.service,
+ service: configuration.chatService,
options: configuration.chatOptionsBuilder(context),
onNoChats: () async =>
- await context.push(CommunityChatUserStoryRoutes.newChatScreen),
+ await context.push(ChatUserStoryRoutes.newChatScreen),
onPressStartChat: () async {
if (configuration.onPressStartChat != null) {
return await configuration.onPressStartChat?.call();
}
- return await context
- .push(CommunityChatUserStoryRoutes.newChatScreen);
+ return await context.push(ChatUserStoryRoutes.newChatScreen);
},
onPressChat: (chat) =>
configuration.onPressChat?.call(context, chat) ??
- context.push(
- CommunityChatUserStoryRoutes.chatDetailViewPath(chat.id!)),
+ context.push(ChatUserStoryRoutes.chatDetailViewPath(chat.id!)),
onDeleteChat: (chat) =>
configuration.onDeleteChat?.call(context, chat) ??
- configuration.service.deleteChat(chat),
+ configuration.chatService.chatOverviewService.deleteChat(chat),
deleteChatDialog: configuration.deleteChatDialog,
translations: configuration.translations,
);
@@ -54,35 +49,38 @@ List getCommunityChatStoryRoutes(
},
),
GoRoute(
- path: CommunityChatUserStoryRoutes.chatDetailScreen,
+ path: ChatUserStoryRoutes.chatDetailScreen,
pageBuilder: (context, state) {
var chatId = state.pathParameters['id'];
- var chat = PersonalChatModel(user: ChatUserModel(), id: chatId);
var chatDetailScreen = ChatDetailScreen(
pageSize: configuration.messagePageSize,
options: configuration.chatOptionsBuilder(context),
translations: configuration.translations,
- chatUserService: configuration.userService,
- service: configuration.service,
- messageService: configuration.messageService,
- chat: chat,
+ service: configuration.chatService,
+ chatId: chatId!,
onMessageSubmit: (message) async {
configuration.onMessageSubmit?.call(message) ??
- configuration.messageService
- .sendTextMessage(chat: chat, text: message);
- configuration.afterMessageSent?.call(chat);
+ configuration.chatService.chatDetailService
+ .sendTextMessage(chatId: chatId, text: message);
+ configuration.afterMessageSent?.call(chatId);
},
onUploadImage: (image) async {
configuration.onUploadImage?.call(image) ??
- configuration.messageService
- .sendImageMessage(chat: chat, image: image);
- configuration.afterMessageSent?.call(chat);
+ configuration.chatService.chatDetailService
+ .sendImageMessage(chatId: chatId, image: image);
+ configuration.afterMessageSent?.call(chatId);
},
onReadChat: (chat) =>
configuration.onReadChat?.call(chat) ??
- configuration.service.readChat(chat),
- onPressChatTitle: (context, chat) =>
- configuration.onPressChatTitle?.call(context, chat),
+ configuration.chatService.chatOverviewService.readChat(chat),
+ onPressChatTitle: (context, chat) {
+ if (configuration.onPressChatTitle?.call(context, chat) != null) {
+ return configuration.onPressChatTitle?.call(context, chat);
+ }
+
+ return context.push(
+ ChatUserStoryRoutes.chatProfileScreenPath(chat.id!, null));
+ },
iconColor: configuration.iconColor,
);
return buildScreenWithoutTransition(
@@ -99,19 +97,20 @@ List getCommunityChatStoryRoutes(
},
),
GoRoute(
- path: CommunityChatUserStoryRoutes.newChatScreen,
+ path: ChatUserStoryRoutes.newChatScreen,
pageBuilder: (context, state) {
var newChatScreen = NewChatScreen(
options: configuration.chatOptionsBuilder(context),
translations: configuration.translations,
- service: configuration.service,
- userService: configuration.userService,
+ service: configuration.chatService,
onPressCreateChat: (user) async {
configuration.onPressCreateChat?.call(user);
if (configuration.onPressChat != null) return;
- var chat = await configuration.service.getChatByUser(user);
+ var chat = await configuration.chatService.chatOverviewService
+ .getChatByUser(user);
if (chat.id == null) {
- chat = await configuration.service.storeChatIfNot(
+ chat = await configuration.chatService.chatOverviewService
+ .storeChatIfNot(
PersonalChatModel(
user: user,
),
@@ -119,8 +118,7 @@ List getCommunityChatStoryRoutes(
}
if (context.mounted) {
await context.push(
- CommunityChatUserStoryRoutes.chatDetailViewPath(
- chat.id ?? ''));
+ ChatUserStoryRoutes.chatDetailViewPath(chat.id ?? ''));
}
});
return buildScreenWithoutTransition(
@@ -136,4 +134,38 @@ List getCommunityChatStoryRoutes(
);
},
),
+ GoRoute(
+ path: ChatUserStoryRoutes.chatProfileScreen,
+ pageBuilder: (context, state) {
+ var chatId = state.pathParameters['id'];
+ var userId = state.pathParameters['userId'];
+ var id = userId == 'null' ? null : userId;
+ var profileScreen = ChatProfileScreen(
+ translations: configuration.translations,
+ chatService: configuration.chatService,
+ chatId: chatId!,
+ userId: id,
+ onTapUser: (user) async {
+ if (configuration.onPressUserProfile != null) {
+ return configuration.onPressUserProfile!.call();
+ }
+
+ return await context.push(
+ ChatUserStoryRoutes.chatProfileScreenPath(chatId, user),
+ );
+ },
+ );
+ return buildScreenWithoutTransition(
+ context: context,
+ state: state,
+ child: configuration.chatPageBuilder?.call(
+ context,
+ profileScreen,
+ ) ??
+ Scaffold(
+ body: profileScreen,
+ ),
+ );
+ },
+ ),
];
diff --git a/packages/flutter_community_chat/lib/src/go_router.dart b/packages/flutter_chat/lib/src/go_router.dart
similarity index 100%
rename from packages/flutter_community_chat/lib/src/go_router.dart
rename to packages/flutter_chat/lib/src/go_router.dart
diff --git a/packages/flutter_community_chat/lib/src/models/community_chat_configuration.dart b/packages/flutter_chat/lib/src/models/chat_configuration.dart
similarity index 81%
rename from packages/flutter_community_chat/lib/src/models/community_chat_configuration.dart
rename to packages/flutter_chat/lib/src/models/chat_configuration.dart
index 6d8e04d..93c6e97 100644
--- a/packages/flutter_community_chat/lib/src/models/community_chat_configuration.dart
+++ b/packages/flutter_chat/lib/src/models/chat_configuration.dart
@@ -5,14 +5,12 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
@immutable
-class CommunityChatUserStoryConfiguration {
- const CommunityChatUserStoryConfiguration({
- required this.userService,
- required this.messageService,
- required this.service,
+class ChatUserStoryConfiguration {
+ const ChatUserStoryConfiguration({
+ required this.chatService,
required this.chatOptionsBuilder,
this.pageSize = 10,
this.onPressStartChat,
@@ -31,10 +29,9 @@ class CommunityChatUserStoryConfiguration {
this.onPressChatTitle,
this.afterMessageSent,
this.messagePageSize = 20,
+ this.onPressUserProfile,
});
- final ChatService service;
- final ChatUserService userService;
- final MessageService messageService;
+ final ChatService chatService;
final Function(BuildContext, ChatModel)? onPressChat;
final Function(BuildContext, ChatModel)? onDeleteChat;
final ChatTranslations translations;
@@ -43,7 +40,7 @@ class CommunityChatUserStoryConfiguration {
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(ChatModel chat)? afterMessageSent;
+ final Function(String chatId)? afterMessageSent;
final Future Function(ChatModel chat)? onReadChat;
final Function(ChatUserModel)? onPressCreateChat;
final ChatOptions Function(BuildContext context) chatOptionsBuilder;
@@ -58,4 +55,5 @@ class CommunityChatUserStoryConfiguration {
final Color? iconColor;
final Widget Function(BuildContext context, Widget child)? chatPageBuilder;
final Function()? onPressStartChat;
+ final Function()? onPressUserProfile;
}
diff --git a/packages/flutter_community_chat/lib/src/routes.dart b/packages/flutter_chat/lib/src/routes.dart
similarity index 60%
rename from packages/flutter_community_chat/lib/src/routes.dart
rename to packages/flutter_chat/lib/src/routes.dart
index d77e8aa..32e2a57 100644
--- a/packages/flutter_community_chat/lib/src/routes.dart
+++ b/packages/flutter_chat/lib/src/routes.dart
@@ -2,9 +2,12 @@
//
// SPDX-License-Identifier: BSD-3-Clause
-mixin CommunityChatUserStoryRoutes {
+mixin ChatUserStoryRoutes {
static const String chatScreen = '/chat';
static String chatDetailViewPath(String chatId) => '/chat-detail/$chatId';
static const String chatDetailScreen = '/chat-detail/:id';
static const String newChatScreen = '/new-chat';
+ static String chatProfileScreenPath(String chatId, String? userId) =>
+ '/chat-profile/$chatId/$userId';
+ static const String chatProfileScreen = '/chat-profile/:id/:userId';
}
diff --git a/packages/flutter_community_chat/pubspec.yaml b/packages/flutter_chat/pubspec.yaml
similarity index 52%
rename from packages/flutter_community_chat/pubspec.yaml
rename to packages/flutter_chat/pubspec.yaml
index ca93837..d5fdb59 100644
--- a/packages/flutter_community_chat/pubspec.yaml
+++ b/packages/flutter_chat/pubspec.yaml
@@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-name: flutter_community_chat
+name: flutter_chat
description: A new Flutter package project.
version: 1.0.0
@@ -16,15 +16,15 @@ dependencies:
flutter:
sdk: flutter
go_router: any
- flutter_community_chat_view:
+ flutter_chat_view:
git:
- url: https://github.com/Iconica-Development/flutter_community_chat
- path: packages/flutter_community_chat_view
+ url: https://github.com/Iconica-Development/flutter_chat
+ path: packages/flutter_chat_view
ref: 1.0.0
- flutter_community_chat_interface:
+ flutter_chat_interface:
git:
- url: https://github.com/Iconica-Development/flutter_community_chat
- path: packages/flutter_community_chat_interface
+ url: https://github.com/Iconica-Development/flutter_chat
+ path: packages/flutter_chat_interface
ref: 1.0.0
dev_dependencies:
diff --git a/packages/flutter_community_chat_firebase/analysis_options.yaml b/packages/flutter_chat_firebase/analysis_options.yaml
similarity index 100%
rename from packages/flutter_community_chat_firebase/analysis_options.yaml
rename to packages/flutter_chat_firebase/analysis_options.yaml
diff --git a/packages/flutter_community_chat_firebase/lib/config/firebase_chat_options.dart b/packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart
similarity index 100%
rename from packages/flutter_community_chat_firebase/lib/config/firebase_chat_options.dart
rename to packages/flutter_chat_firebase/lib/config/firebase_chat_options.dart
diff --git a/packages/flutter_community_chat_firebase/lib/dto/firebase_chat_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart
similarity index 94%
rename from packages/flutter_community_chat_firebase/lib/dto/firebase_chat_document.dart
rename to packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart
index 410a390..12c5002 100644
--- a/packages/flutter_community_chat_firebase/lib/dto/firebase_chat_document.dart
+++ b/packages/flutter_chat_firebase/lib/dto/firebase_chat_document.dart
@@ -4,7 +4,7 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_firebase/dto/firebase_message_document.dart';
+import 'package:flutter_chat_firebase/dto/firebase_message_document.dart';
@immutable
class FirebaseChatDocument {
diff --git a/packages/flutter_community_chat_firebase/lib/dto/firebase_message_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart
similarity index 100%
rename from packages/flutter_community_chat_firebase/lib/dto/firebase_message_document.dart
rename to packages/flutter_chat_firebase/lib/dto/firebase_message_document.dart
diff --git a/packages/flutter_community_chat_firebase/lib/dto/firebase_user_document.dart b/packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart
similarity index 100%
rename from packages/flutter_community_chat_firebase/lib/dto/firebase_user_document.dart
rename to packages/flutter_chat_firebase/lib/dto/firebase_user_document.dart
diff --git a/packages/flutter_chat_firebase/lib/flutter_chat_firebase.dart b/packages/flutter_chat_firebase/lib/flutter_chat_firebase.dart
new file mode 100644
index 0000000..7ad2e3a
--- /dev/null
+++ b/packages/flutter_chat_firebase/lib/flutter_chat_firebase.dart
@@ -0,0 +1,7 @@
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+library flutter_chat_firebase;
+
+export 'package:flutter_chat_firebase/service/service.dart';
diff --git a/packages/flutter_community_chat_firebase/lib/service/firebase_message_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart
similarity index 54%
rename from packages/flutter_community_chat_firebase/lib/service/firebase_message_service.dart
rename to packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart
index 6ad72c8..b5a23ed 100644
--- a/packages/flutter_community_chat_firebase/lib/service/firebase_message_service.dart
+++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_detail_service.dart
@@ -8,12 +8,14 @@ import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_firebase/config/firebase_chat_options.dart';
-import 'package:flutter_community_chat_firebase/dto/firebase_message_document.dart';
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
+import 'package:flutter_chat_firebase/config/firebase_chat_options.dart';
+import 'package:flutter_chat_firebase/dto/firebase_message_document.dart';
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
import 'package:uuid/uuid.dart';
-class FirebaseMessageService with ChangeNotifier implements MessageService {
+class FirebaseChatDetailService
+ with ChangeNotifier
+ implements ChatDetailService {
late final FirebaseFirestore _db;
late final FirebaseStorage _storage;
late final ChatUserService _userService;
@@ -23,11 +25,11 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
StreamSubscription? _subscription;
DocumentSnapshot? lastMessage;
List _cumulativeMessages = [];
- ChatModel? lastChat;
+ String? lastChat;
int? chatPageSize;
DateTime timestampToFilter = DateTime.now();
- FirebaseMessageService({
+ FirebaseChatDetailService({
required ChatUserService userService,
FirebaseApp? app,
FirebaseChatOptions? options,
@@ -40,10 +42,10 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
_options = options ?? const FirebaseChatOptions();
}
- Future _sendMessage(ChatModel chat, Map data) async {
+ Future _sendMessage(String chatId, Map data) async {
var currentUser = await _userService.getCurrentUser();
- if (chat.id == null || currentUser == null) {
+ if (currentUser == null) {
return;
}
@@ -57,7 +59,7 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
.collection(
_options.chatsCollectionName,
)
- .doc(chat.id);
+ .doc(chatId);
var newMessage = await chatReference
.collection(
@@ -78,21 +80,13 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
.collection(
_options.chatsMetaDataCollectionName,
)
- .doc(chat.id);
+ .doc(chatId);
await metadataReference.update({
'last_used': DateTime.now(),
'last_message': message,
});
- if (_controller != null) {
- if (chat.id != null &&
- _controller!.hasListener &&
- (_subscription == null)) {
- _subscription = _startListeningForMessages(chat);
- }
- }
-
// update the chat counter for the other users
// get all users from the chat
// there is a field in the chat document called users that has a list of user ids
@@ -107,7 +101,7 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
)
.doc(userId)
.collection(_options.userChatsCollectionName)
- .doc(chat.id);
+ .doc(chatId);
// what if the amount_unread_messages field does not exist?
// it should be created when the chat is create
if ((await userReference.get())
@@ -120,7 +114,7 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
} else {
await userReference.set({
'amount_unread_messages': 1,
- });
+ }, SetOptions(merge: true));
}
}
}
@@ -129,10 +123,10 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
@override
Future sendTextMessage({
required String text,
- required ChatModel chat,
+ required String chatId,
}) {
return _sendMessage(
- chat,
+ chatId,
{
'text': text,
},
@@ -141,21 +135,17 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
@override
Future sendImageMessage({
- required ChatModel chat,
+ required String chatId,
required Uint8List image,
}) async {
- if (chat.id == null) {
- return;
- }
-
var ref = _storage
- .ref('${_options.chatsCollectionName}/${chat.id}/${const Uuid().v4()}');
+ .ref('${_options.chatsCollectionName}/$chatId/${const Uuid().v4()}');
return ref.putData(image).then(
(_) => ref.getDownloadURL().then(
(url) {
_sendMessage(
- chat,
+ chatId,
{
'image_url': url,
},
@@ -165,52 +155,16 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
);
}
- Query _getMessagesQuery(ChatModel chat) {
- if (lastChat == null) {
- lastChat = chat;
- } else if (lastChat?.id != chat.id) {
- _cumulativeMessages = [];
- lastChat = chat;
- lastMessage = null;
- }
-
- var query = _db
- .collection(_options.chatsCollectionName)
- .doc(chat.id)
- .collection(_options.messagesCollectionName)
- .orderBy('timestamp', descending: true)
- .limit(chatPageSize!);
-
- if (lastMessage == null) {
- return query.withConverter(
- fromFirestore: (snapshot, _) =>
- FirebaseMessageDocument.fromJson(snapshot.data()!, snapshot.id),
- toFirestore: (user, _) => user.toJson(),
- );
- }
- return query
- .startAfterDocument(lastMessage!)
- .withConverter(
- fromFirestore: (snapshot, _) =>
- FirebaseMessageDocument.fromJson(snapshot.data()!, snapshot.id),
- toFirestore: (user, _) => user.toJson(),
- );
- }
-
@override
- Stream> getMessagesStream(ChatModel chat) {
+ Stream> getMessagesStream(String chatId) {
+ timestampToFilter = DateTime.now();
+ var messages = [];
_controller = StreamController>(
onListen: () {
var messagesCollection = _db
.collection(_options.chatsCollectionName)
- .doc(chat.id)
+ .doc(chatId)
.collection(_options.messagesCollectionName)
- .withConverter(
- fromFirestore: (snapshot, _) => FirebaseMessageDocument.fromJson(
- snapshot.data()!, snapshot.id),
- toFirestore: (user, _) => user.toJson(),
- );
- var query = messagesCollection
.where(
'timestamp',
isGreaterThan: timestampToFilter,
@@ -219,67 +173,45 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
fromFirestore: (snapshot, _) => FirebaseMessageDocument.fromJson(
snapshot.data()!, snapshot.id),
toFirestore: (user, _) => user.toJson(),
- );
+ )
+ .snapshots();
- var stream = query.snapshots();
- // Subscribe to the stream and process the updates
- _subscription = stream.listen((snapshot) async {
- var messages = [];
-
- for (var messageDoc in snapshot.docs) {
- var messageData = messageDoc.data();
+ _subscription = messagesCollection.listen((event) async {
+ for (var message in event.docChanges) {
+ var data = message.doc.data();
+ var sender = await _userService.getUser(data!.sender);
var timestamp = DateTime.fromMillisecondsSinceEpoch(
- (messageData.timestamp).millisecondsSinceEpoch,
+ (data.timestamp).millisecondsSinceEpoch,
);
- // Check if the message is already in the list to avoid duplicates
- if (timestampToFilter.isBefore(timestamp)) {
- if (!messages.any((message) {
- var timestamp = DateTime.fromMillisecondsSinceEpoch(
- (messageData.timestamp).millisecondsSinceEpoch,
- );
- return timestamp == message.timestamp;
- })) {
- var sender = await _userService.getUser(messageData.sender);
-
- if (sender != null) {
- var timestamp = DateTime.fromMillisecondsSinceEpoch(
- (messageData.timestamp).millisecondsSinceEpoch,
- );
-
- messages.add(
- messageData.imageUrl != null
- ? ChatImageMessageModel(
- sender: sender,
- imageUrl: messageData.imageUrl!,
- timestamp: timestamp,
- )
- : ChatTextMessageModel(
- sender: sender,
- text: messageData.text!,
- timestamp: timestamp,
- ),
- );
- }
- }
+ if (timestamp.isBefore(timestampToFilter)) {
+ return;
}
+ messages.add(
+ data.imageUrl != null
+ ? ChatImageMessageModel(
+ sender: sender!,
+ imageUrl: data.imageUrl!,
+ timestamp: timestamp,
+ )
+ : ChatTextMessageModel(
+ sender: sender!,
+ text: data.text!,
+ timestamp: timestamp,
+ ),
+ );
+ timestampToFilter = DateTime.now();
}
-
- // Add the filtered messages to the controller
- _controller?.add(messages);
_cumulativeMessages = [
..._cumulativeMessages,
...messages,
];
-
- // remove all double elements
List uniqueObjects =
_cumulativeMessages.toSet().toList();
_cumulativeMessages = uniqueObjects;
_cumulativeMessages
.sort((a, b) => a.timestamp.compareTo(b.timestamp));
notifyListeners();
- timestampToFilter = DateTime.now();
});
},
onCancel: () {
@@ -288,72 +220,25 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
debugPrint('Canceling messages stream');
},
);
+
return _controller!.stream;
}
- StreamSubscription _startListeningForMessages(ChatModel chat) {
- debugPrint('Start listening for messages in chat ${chat.id}');
- var snapshots = _getMessagesQuery(chat).snapshots();
- return snapshots.listen(
- (snapshot) async {
- List messages =
- List.from(_cumulativeMessages);
-
- if (snapshot.docs.isNotEmpty) {
- lastMessage = snapshot.docs.last;
-
- for (var messageDoc in snapshot.docs) {
- var messageData = messageDoc.data();
-
- // Check if the message is already in the list to avoid duplicates
- if (!messages.any((message) {
- var timestamp = DateTime.fromMillisecondsSinceEpoch(
- (messageData.timestamp).millisecondsSinceEpoch,
- );
- return timestamp == message.timestamp;
- })) {
- var sender = await _userService.getUser(messageData.sender);
-
- if (sender != null) {
- var timestamp = DateTime.fromMillisecondsSinceEpoch(
- (messageData.timestamp).millisecondsSinceEpoch,
- );
-
- messages.add(
- messageData.imageUrl != null
- ? ChatImageMessageModel(
- sender: sender,
- imageUrl: messageData.imageUrl!,
- timestamp: timestamp,
- )
- : ChatTextMessageModel(
- sender: sender,
- text: messageData.text!,
- timestamp: timestamp,
- ),
- );
- }
- }
- }
- }
-
- _cumulativeMessages = messages;
-
- messages.sort((a, b) => a.timestamp.compareTo(b.timestamp));
-
- _controller?.add(messages);
- notifyListeners();
- },
- );
+ @override
+ void stopListeningForMessages() {
+ _subscription?.cancel();
+ _subscription = null;
+ _controller?.close();
+ _controller = null;
}
@override
- Future fetchMoreMessage(int pageSize, ChatModel chat) async {
+ Future fetchMoreMessage(int pageSize, String chatId) async {
if (lastChat == null) {
- lastChat = chat;
- } else if (lastChat?.id != chat.id) {
+ lastChat = chatId;
+ } else if (lastChat != chatId) {
_cumulativeMessages = [];
- lastChat = chat;
+ lastChat = chatId;
lastMessage = null;
}
// get the x amount of last messages from the oldest message that is in cumulative messages and add that to the list
@@ -361,7 +246,7 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
QuerySnapshot? messagesQuerySnapshot;
var query = _db
.collection(_options.chatsCollectionName)
- .doc(chat.id)
+ .doc(chatId)
.collection(_options.messagesCollectionName)
.orderBy('timestamp', descending: true)
.limit(pageSize);
@@ -393,7 +278,6 @@ class FirebaseMessageService with ChangeNotifier implements MessageService {
List messageDocuments = messagesQuerySnapshot.docs
.map((QueryDocumentSnapshot doc) => doc.data())
.toList();
-
for (var message in messageDocuments) {
var sender = await _userService.getUser(message.sender);
if (sender != null) {
diff --git a/packages/flutter_community_chat_firebase/lib/service/firebase_chat_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart
similarity index 50%
rename from packages/flutter_community_chat_firebase/lib/service/firebase_chat_service.dart
rename to packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart
index cd6178e..9510149 100644
--- a/packages/flutter_community_chat_firebase/lib/service/firebase_chat_service.dart
+++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_overview_service.dart
@@ -1,26 +1,24 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'dart:async';
+
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
-import 'package:flutter_community_chat_firebase/config/firebase_chat_options.dart';
-import 'package:flutter_community_chat_firebase/dto/firebase_chat_document.dart';
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
+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';
-class FirebaseChatService implements ChatService {
+class FirebaseChatOverviewService implements ChatOverviewService {
late FirebaseFirestore _db;
late FirebaseStorage _storage;
late ChatUserService _userService;
late FirebaseChatOptions _options;
- DocumentSnapshot? lastUserDocument;
- String? lastGroupId;
- List chatIds = [];
- int pageNumber = 1;
- FirebaseChatService({
+ FirebaseChatOverviewService({
required ChatUserService userService,
FirebaseApp? app,
FirebaseChatOptions? options,
@@ -33,266 +31,152 @@ class FirebaseChatService implements ChatService {
_options = options ?? const FirebaseChatOptions();
}
- StreamSubscription _addUnreadChatSubscription(
+ Future _addUnreadChatSubscription(
String chatId,
String userId,
- Function(int) onUnreadChatsUpdated,
- ) {
- var snapshots = _db
+ ) async {
+ var snapshots = await _db
.collection(_options.usersCollectionName)
.doc(userId)
.collection(_options.userChatsCollectionName)
.doc(chatId)
- .snapshots();
+ .get();
- return snapshots.listen((snapshot) {
- var data = snapshot.data();
- onUnreadChatsUpdated(data?['amount_unread_messages'] ?? 0);
- });
- }
-
- StreamSubscription _addChatSubscription(
- List chatIds,
- Function(List) onReceivedChats,
- ) {
- var snapshots = _db
- .collection(_options.chatsMetaDataCollectionName)
- .where(
- FieldPath.documentId,
- whereIn: chatIds,
- )
- .withConverter(
- fromFirestore: (snapshot, _) =>
- FirebaseChatDocument.fromJson(snapshot.data()!, snapshot.id),
- toFirestore: (chat, _) => chat.toJson(),
- )
- .snapshots();
-
- return snapshots.listen((snapshot) async {
- var currentUser = await _userService.getCurrentUser();
- var chats = [];
-
- for (var chatDoc in snapshot.docs) {
- var chatData = chatDoc.data();
-
- var messages = [];
-
- if (chatData.lastMessage != null) {
- var messageData = chatData.lastMessage!;
- var sender = await _userService.getUser(messageData.sender);
-
- if (sender != null) {
- var timestamp = DateTime.fromMillisecondsSinceEpoch(
- messageData.timestamp.millisecondsSinceEpoch,
- );
-
- messages.add(
- messageData.imageUrl != null
- ? ChatImageMessageModel(
- sender: sender,
- imageUrl: messageData.imageUrl!,
- timestamp: timestamp,
- )
- : ChatTextMessageModel(
- sender: sender,
- text: messageData.text!,
- timestamp: timestamp,
- ),
- );
- }
- }
- ChatModel? chatModel;
-
- if (chatData.personal) {
- var otherUserId = List.from(chatData.users).firstWhere(
- (element) => element != currentUser?.id,
- );
- var otherUser = await _userService.getUser(otherUserId);
-
- if (otherUser != null) {
- chatModel = PersonalChatModel(
- id: chatDoc.id,
- user: otherUser,
- lastMessage: messages.isNotEmpty ? messages.last : null,
- messages: messages,
- canBeDeleted: chatData.canBeDeleted,
- lastUsed: chatData.lastUsed == null
- ? null
- : DateTime.fromMillisecondsSinceEpoch(
- chatData.lastUsed!.millisecondsSinceEpoch,
- ),
- );
- }
- } else {
- // group chat
- var users = [];
- for (var userId in chatData.users) {
- var user = await _userService.getUser(userId);
- if (user != null) {
- users.add(user);
- }
- }
- chatModel = GroupChatModel(
- id: chatDoc.id,
- title: chatData.title ?? '',
- imageUrl: chatData.imageUrl ?? '',
- lastMessage: messages.isNotEmpty ? messages.last : null,
- messages: messages,
- users: users,
- canBeDeleted: chatData.canBeDeleted,
- 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);
- });
- }
-
- List> _splitChatIds({
- required List chatIds,
- int chunkSize = 10,
- }) {
- var result = >[];
- var length = chatIds.length;
-
- for (var i = 0; i < length; i += chunkSize) {
- var lastIndex = i + chunkSize;
- result.add(
- chatIds.sublist(i, lastIndex > length ? length : lastIndex),
- );
- }
-
- return result;
- }
-
- Stream> _getSpecificChatsStream(List chatIds) {
- late StreamController> controller;
- List> subscriptions = [];
- var splittedChatIds = _splitChatIds(chatIds: chatIds);
-
- controller = StreamController>(
- onListen: () {
- var chats = >{};
-
- for (var chatIdPair in splittedChatIds.asMap().entries) {
- subscriptions.add(
- _addChatSubscription(
- chatIdPair.value,
- (data) {
- chats[chatIdPair.key] = data;
-
- var mergedChats = [];
-
- mergedChats.addAll(
- chats.values.expand((element) => element),
- );
-
- mergedChats.sort(
- (a, b) => (b.lastUsed ?? DateTime.now()).compareTo(
- a.lastUsed ?? DateTime.now(),
- ),
- );
-
- controller.add(mergedChats);
- },
- ),
- );
- }
- },
- onCancel: () {
- for (var subscription in subscriptions) {
- subscription.cancel();
- }
- },
- );
- return controller.stream;
+ return snapshots.data()?['amount_unread_messages'];
}
@override
- Stream> getChatsStream(int pageSize) {
+ Stream> getChatsStream() {
+ StreamSubscription? chatSubscription;
late StreamController> controller;
- StreamSubscription? chatsSubscription;
controller = StreamController(
onListen: () async {
- QuerySnapshot> userSnapshot;
- List userChatIds;
var currentUser = await _userService.getCurrentUser();
-
- var userQuery = _db
+ var userSnapshot = _db
.collection(_options.usersCollectionName)
.doc(currentUser?.id)
- .collection(_options.userChatsCollectionName);
- if (lastUserDocument == null) {
- userSnapshot = await userQuery.limit(pageSize).get();
- userChatIds = userSnapshot.docs.map((chat) => chat.id).toList();
- } else {
- userSnapshot = await userQuery
- .limit(pageSize)
- .startAfterDocument(lastUserDocument!)
- .get();
- userChatIds = userSnapshot.docs.map((chat) => chat.id).toList();
- }
+ .collection(_options.userChatsCollectionName)
+ .snapshots();
- var userGroupChatIds = await _db
- .collection(_options.usersCollectionName)
- .doc(currentUser?.id)
- .get()
- .then((userCollection) =>
- userCollection.data()?[_options.groupChatsCollectionName])
- .then((groupChatLabels) => groupChatLabels?.cast())
- .then((groupChatIds) {
- var startIndex = (pageNumber - 1) * pageSize;
- var endIndex = startIndex + pageSize;
+ userSnapshot.listen((event) {
+ var chatIds = event.docs.map((e) => e.id).toList();
+ var chatSnapshot = _db
+ .collection(_options.chatsMetaDataCollectionName)
+ .where(
+ FieldPath.documentId,
+ whereIn: chatIds,
+ )
+ .withConverter(
+ fromFirestore: (snapshot, _) => FirebaseChatDocument.fromJson(
+ snapshot.data()!, snapshot.id),
+ toFirestore: (chat, _) => chat.toJson(),
+ )
+ .snapshots();
+ List chats = [];
+ ChatModel? chatModel;
- if (groupChatIds != null) {
- if (startIndex >= groupChatIds.length) {
- return [];
+ chatSubscription = chatSnapshot.listen((event) async {
+ for (var element in event.docChanges) {
+ var chat = element.doc.data();
+ if (chat == null) return;
+ var otherUser = await _userService.getUser(
+ chat.users.firstWhere(
+ (element) => element != currentUser?.id,
+ ),
+ );
+ int? unread =
+ await _addUnreadChatSubscription(chat.id!, currentUser!.id!);
+
+ if (chat.personal) {
+ chatModel = PersonalChatModel(
+ id: chat.id,
+ user: otherUser!,
+ unreadMessages: unread,
+ lastUsed: chat.lastUsed == null
+ ? null
+ : DateTime.fromMillisecondsSinceEpoch(
+ chat.lastUsed!.millisecondsSinceEpoch,
+ ),
+ lastMessage: chat.lastMessage != null &&
+ chat.lastMessage!.imageUrl != null
+ ? ChatImageMessageModel(
+ sender: otherUser,
+ imageUrl: chat.lastMessage!.imageUrl!,
+ timestamp: DateTime.fromMillisecondsSinceEpoch(
+ chat.lastMessage!.timestamp.millisecondsSinceEpoch,
+ ),
+ )
+ : chat.lastMessage != null
+ ? ChatTextMessageModel(
+ sender: otherUser,
+ text: chat.lastMessage!.text!,
+ timestamp: DateTime.fromMillisecondsSinceEpoch(
+ chat.lastMessage!.timestamp
+ .millisecondsSinceEpoch,
+ ),
+ )
+ : null,
+ );
+ } else {
+ var users = [];
+ for (var userId in chat.users) {
+ var user = await _userService.getUser(userId);
+ if (user != null) {
+ users.add(user);
+ }
+ }
+ chatModel = GroupChatModel(
+ id: chat.id,
+ title: chat.title ?? '',
+ imageUrl: chat.imageUrl ?? '',
+ unreadMessages: unread,
+ users: users,
+ lastMessage: chat.lastMessage != null &&
+ chat.lastMessage!.imageUrl == null
+ ? ChatTextMessageModel(
+ sender: otherUser!,
+ text: chat.lastMessage!.text!,
+ timestamp: DateTime.fromMillisecondsSinceEpoch(
+ chat.lastMessage!.timestamp.millisecondsSinceEpoch,
+ ),
+ )
+ : ChatImageMessageModel(
+ sender: otherUser!,
+ imageUrl: chat.lastMessage!.imageUrl!,
+ timestamp: DateTime.fromMillisecondsSinceEpoch(
+ chat.lastMessage!.timestamp.millisecondsSinceEpoch,
+ ),
+ ),
+ canBeDeleted: chat.canBeDeleted,
+ lastUsed: chat.lastUsed == null
+ ? null
+ : DateTime.fromMillisecondsSinceEpoch(
+ chat.lastUsed!.millisecondsSinceEpoch,
+ ),
+ );
+ }
+ chats.add(chatModel!);
}
- var groupIds = groupChatIds.sublist(
- startIndex, endIndex.clamp(0, groupChatIds.length));
- lastGroupId = groupIds.last;
- return groupIds;
- }
- return [];
- });
+ Set uniqueIds = {};
+ List uniqueChatModels = [];
- if (userSnapshot.docs.isNotEmpty) {
- lastUserDocument = userSnapshot.docs.last;
- }
+ for (ChatModel chatModel in chats) {
+ if (uniqueIds.add(chatModel.id!)) {
+ uniqueChatModels.add(chatModel);
+ }
+ }
+ uniqueChatModels.sort(
+ (a, b) => (b.lastUsed ?? DateTime.now()).compareTo(
+ a.lastUsed ?? DateTime.now(),
+ ),
+ );
- pageNumber++;
- chatIds.addAll([...userChatIds, ...userGroupChatIds]);
- var chatsStream = _getSpecificChatsStream(chatIds);
-
- chatsSubscription = chatsStream.listen((event) {
- controller.add(event);
+ controller.add(uniqueChatModels);
+ });
});
},
onCancel: () {
- chatsSubscription?.cancel();
+ chatSubscription?.cancel();
},
);
return controller.stream;
@@ -338,7 +222,7 @@ class FirebaseChatService implements ChatService {
);
} else {
var groupChatCollection = await _db
- .collection(_options.chatsCollectionName)
+ .collection(_options.chatsMetaDataCollectionName)
.doc(chatId)
.withConverter(
fromFirestore: (snapshot, _) =>
@@ -442,11 +326,10 @@ class FirebaseChatService implements ChatService {
.doc(userId)
.collection(_options.userChatsCollectionName)
.doc(reference.id)
- .set({'users': userIds});
+ .set({'users': userIds}, SetOptions(merge: true));
}
chat.id = reference.id;
- chatIds.add(chat.id!);
} else if (chat is GroupChatModel) {
if (currentUser?.id == null) {
return chat;
@@ -479,11 +362,10 @@ class FirebaseChatService implements ChatService {
.doc(userId)
.collection(_options.groupChatsCollectionName)
.doc(reference.id)
- .set({'users': userIds});
+ .set({'users': userIds}, SetOptions(merge: true));
}
chat.id = reference.id;
- chatIds.add(chat.id!);
} else {
throw Exception('Chat type not supported for firebase');
}
diff --git a/packages/flutter_community_chat_firebase/lib/service/firebase_user_service.dart b/packages/flutter_chat_firebase/lib/service/firebase_chat_user_service.dart
similarity index 87%
rename from packages/flutter_community_chat_firebase/lib/service/firebase_user_service.dart
rename to packages/flutter_chat_firebase/lib/service/firebase_chat_user_service.dart
index e417f95..5d81ccb 100644
--- a/packages/flutter_community_chat_firebase/lib/service/firebase_user_service.dart
+++ b/packages/flutter_chat_firebase/lib/service/firebase_chat_user_service.dart
@@ -5,12 +5,12 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
-import 'package:flutter_community_chat_firebase/config/firebase_chat_options.dart';
-import 'package:flutter_community_chat_firebase/dto/firebase_user_document.dart';
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
+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';
-class FirebaseUserService implements ChatUserService {
- FirebaseUserService({
+class FirebaseChatUserService implements ChatUserService {
+ FirebaseChatUserService({
FirebaseApp? app,
FirebaseChatOptions? options,
}) {
diff --git a/packages/flutter_chat_firebase/lib/service/service.dart b/packages/flutter_chat_firebase/lib/service/service.dart
new file mode 100644
index 0000000..99331f3
--- /dev/null
+++ b/packages/flutter_chat_firebase/lib/service/service.dart
@@ -0,0 +1,3 @@
+export 'package:flutter_chat_firebase/service/firebase_chat_user_service.dart';
+export 'package:flutter_chat_firebase/service/firebase_chat_detail_service.dart';
+export 'package:flutter_chat_firebase/service/firebase_chat_overview_service.dart';
diff --git a/packages/flutter_community_chat_firebase/pubspec.yaml b/packages/flutter_chat_firebase/pubspec.yaml
similarity index 69%
rename from packages/flutter_community_chat_firebase/pubspec.yaml
rename to packages/flutter_chat_firebase/pubspec.yaml
index c0d976c..db7b393 100644
--- a/packages/flutter_community_chat_firebase/pubspec.yaml
+++ b/packages/flutter_chat_firebase/pubspec.yaml
@@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-name: flutter_community_chat_firebase
+name: flutter_chat_firebase
description: A new Flutter package project.
version: 1.0.0
publish_to: none
@@ -19,10 +19,10 @@ dependencies:
firebase_storage: ^11.0.5
firebase_auth: ^4.1.2
uuid: ^4.0.0
- flutter_community_chat_interface:
+ flutter_chat_interface:
git:
- url: https://github.com/Iconica-Development/flutter_community_chat
- path: packages/flutter_community_chat_interface
+ url: https://github.com/Iconica-Development/flutter_chat
+ path: packages/flutter_chat_interface
ref: 1.0.0
dev_dependencies:
diff --git a/packages/flutter_community_chat_interface/analysis_options.yaml b/packages/flutter_chat_interface/analysis_options.yaml
similarity index 100%
rename from packages/flutter_community_chat_interface/analysis_options.yaml
rename to packages/flutter_chat_interface/analysis_options.yaml
diff --git a/packages/flutter_chat_interface/lib/flutter_chat_interface.dart b/packages/flutter_chat_interface/lib/flutter_chat_interface.dart
new file mode 100644
index 0000000..986f170
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/flutter_chat_interface.dart
@@ -0,0 +1,9 @@
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+library flutter_chat_interface;
+
+export 'package:flutter_chat_interface/src/model/model.dart';
+export 'package:flutter_chat_interface/src/service/service.dart';
+export 'package:flutter_chat_interface/src/chat_data_provider.dart';
diff --git a/packages/flutter_community_chat_interface/lib/src/chat_data_provider.dart b/packages/flutter_chat_interface/lib/src/chat_data_provider.dart
similarity index 72%
rename from packages/flutter_community_chat_interface/lib/src/chat_data_provider.dart
rename to packages/flutter_chat_interface/lib/src/chat_data_provider.dart
index a152c49..61bc4de 100644
--- a/packages/flutter_community_chat_interface/lib/src/chat_data_provider.dart
+++ b/packages/flutter_chat_interface/lib/src/chat_data_provider.dart
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: BSD-3-Clause
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
import 'package:flutter_data_interface/flutter_data_interface.dart';
class ChatDataProvider extends DataInterface {
@@ -14,6 +14,6 @@ class ChatDataProvider extends DataInterface {
static final Object _token = Object();
final ChatUserService userService;
- final ChatService chatService;
- final MessageService messageService;
+ final ChatOverviewService chatService;
+ final ChatDetailService messageService;
}
diff --git a/packages/flutter_chat_interface/lib/src/model/chat.dart b/packages/flutter_chat_interface/lib/src/model/chat.dart
new file mode 100644
index 0000000..fa3bfd9
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/src/model/chat.dart
@@ -0,0 +1,39 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
+
+abstract class ChatModelInterface {
+ String? get id;
+ List? get messages;
+ int? get unreadMessages;
+ DateTime? get lastUsed;
+ ChatMessageModel? get lastMessage;
+ bool get canBeDeleted;
+}
+
+class ChatModel implements ChatModelInterface {
+ ChatModel({
+ this.id,
+ this.messages = const [],
+ this.unreadMessages,
+ this.lastUsed,
+ this.lastMessage,
+ this.canBeDeleted = true,
+ });
+
+ @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
new file mode 100644
index 0000000..37c2ac3
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/src/model/chat_image_message.dart
@@ -0,0 +1,29 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
+
+abstract class ChatImageMessageModelInterface extends ChatMessageModel {
+ ChatImageMessageModelInterface({
+ required super.sender,
+ required super.timestamp,
+ });
+
+ String get imageUrl;
+}
+
+class ChatImageMessageModel implements ChatImageMessageModelInterface {
+ 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
new file mode 100644
index 0000000..b248127
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/src/model/chat_message.dart
@@ -0,0 +1,23 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+import 'package:flutter_chat_interface/src/model/chat_user.dart';
+
+abstract class ChatMessageModelInterface {
+ ChatUserModel get sender;
+ DateTime get timestamp;
+}
+
+class ChatMessageModel implements ChatMessageModelInterface {
+ ChatMessageModel({
+ required this.sender,
+ required this.timestamp,
+ });
+
+ @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
new file mode 100644
index 0000000..18a6cdd
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/src/model/chat_text_message.dart
@@ -0,0 +1,29 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
+
+abstract class ChatTextMessageModelInterface extends ChatMessageModel {
+ ChatTextMessageModelInterface({
+ required super.sender,
+ required super.timestamp,
+ });
+
+ String get text;
+}
+
+class ChatTextMessageModel implements ChatTextMessageModelInterface {
+ 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_community_chat_interface/lib/src/model/chat_user.dart b/packages/flutter_chat_interface/lib/src/model/chat_user.dart
similarity index 64%
rename from packages/flutter_community_chat_interface/lib/src/model/chat_user.dart
rename to packages/flutter_chat_interface/lib/src/model/chat_user.dart
index 6b28765..68a7e99 100644
--- a/packages/flutter_community_chat_interface/lib/src/model/chat_user.dart
+++ b/packages/flutter_chat_interface/lib/src/model/chat_user.dart
@@ -1,8 +1,18 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
-class ChatUserModel {
+abstract class ChatUserModelInterface {
+ String? get id;
+ String? get firstName;
+ String? get lastName;
+ String? get imageUrl;
+
+ String? get fullName;
+}
+
+class ChatUserModel implements ChatUserModelInterface {
ChatUserModel({
this.id,
this.firstName,
@@ -10,11 +20,15 @@ class ChatUserModel {
this.imageUrl,
});
+ @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
new file mode 100644
index 0000000..80b0ddf
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/src/model/group_chat.dart
@@ -0,0 +1,91 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
+
+abstract class GroupChatModelInterface extends ChatModel {
+ GroupChatModelInterface({
+ super.id,
+ super.messages,
+ super.lastUsed,
+ super.lastMessage,
+ super.unreadMessages,
+ super.canBeDeleted,
+ });
+
+ String get title;
+ String get imageUrl;
+ List get users;
+
+ GroupChatModelInterface copyWith({
+ String? id,
+ List? messages,
+ int? unreadMessages,
+ DateTime? lastUsed,
+ ChatMessageModel? lastMessage,
+ String? title,
+ String? imageUrl,
+ List? users,
+ bool? canBeDeleted,
+ });
+}
+
+class GroupChatModel implements GroupChatModelInterface {
+ GroupChatModel({
+ this.id,
+ this.messages,
+ this.unreadMessages,
+ this.lastUsed,
+ this.lastMessage,
+ required this.canBeDeleted,
+ required this.title,
+ required this.imageUrl,
+ required this.users,
+ });
+
+ @override
+ String? id;
+ @override
+ final List? messages;
+ @override
+ final int? unreadMessages;
+ @override
+ final DateTime? lastUsed;
+ @override
+ final ChatMessageModel? lastMessage;
+ @override
+ final bool canBeDeleted;
+ @override
+ final String title;
+ @override
+ final String imageUrl;
+ @override
+ final List users;
+
+ @override
+ GroupChatModel copyWith({
+ String? id,
+ List? messages,
+ int? unreadMessages,
+ DateTime? lastUsed,
+ ChatMessageModel? lastMessage,
+ bool? canBeDeleted,
+ String? title,
+ String? imageUrl,
+ List? users,
+ }) {
+ return GroupChatModel(
+ id: id ?? this.id,
+ messages: messages ?? this.messages,
+ unreadMessages: unreadMessages ?? this.unreadMessages,
+ lastUsed: lastUsed ?? this.lastUsed,
+ lastMessage: lastMessage ?? this.lastMessage,
+ canBeDeleted: canBeDeleted ?? this.canBeDeleted,
+ title: title ?? this.title,
+ imageUrl: imageUrl ?? this.imageUrl,
+ users: users ?? this.users,
+ );
+ }
+}
diff --git a/packages/flutter_community_chat_interface/lib/src/model/model.dart b/packages/flutter_chat_interface/lib/src/model/model.dart
similarity index 100%
rename from packages/flutter_community_chat_interface/lib/src/model/model.dart
rename to packages/flutter_chat_interface/lib/src/model/model.dart
diff --git a/packages/flutter_chat_interface/lib/src/model/personal_chat.dart b/packages/flutter_chat_interface/lib/src/model/personal_chat.dart
new file mode 100644
index 0000000..a264ab4
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/src/model/personal_chat.dart
@@ -0,0 +1,78 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
+
+abstract class PersonalChatModelInterface extends ChatModel {
+ PersonalChatModelInterface({
+ super.id,
+ super.messages,
+ super.unreadMessages,
+ super.lastUsed,
+ super.lastMessage,
+ super.canBeDeleted,
+ });
+
+ ChatUserModel get user;
+
+ PersonalChatModel copyWith({
+ String? id,
+ List? messages,
+ int? unreadMessages,
+ DateTime? lastUsed,
+ ChatMessageModel? lastMessage,
+ ChatUserModel? user,
+ bool? canBeDeleted,
+ });
+}
+
+class PersonalChatModel implements PersonalChatModelInterface {
+ PersonalChatModel({
+ this.id,
+ this.messages = const [],
+ this.unreadMessages,
+ this.lastUsed,
+ this.lastMessage,
+ this.canBeDeleted = true,
+ required this.user,
+ });
+
+ @override
+ String? id;
+ @override
+ final List? messages;
+ @override
+ final int? unreadMessages;
+ @override
+ final DateTime? lastUsed;
+ @override
+ final ChatMessageModel? lastMessage;
+ @override
+ final bool canBeDeleted;
+
+ @override
+ final ChatUserModel user;
+
+ @override
+ PersonalChatModel copyWith({
+ String? id,
+ List? messages,
+ int? unreadMessages,
+ DateTime? lastUsed,
+ ChatMessageModel? lastMessage,
+ bool? canBeDeleted,
+ ChatUserModel? user,
+ }) {
+ return 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,
+ canBeDeleted: canBeDeleted ?? this.canBeDeleted,
+ );
+ }
+}
diff --git a/packages/flutter_community_chat_interface/lib/src/service/message_service.dart b/packages/flutter_chat_interface/lib/src/service/chat_detail_service.dart
similarity index 50%
rename from packages/flutter_community_chat_interface/lib/src/service/message_service.dart
rename to packages/flutter_chat_interface/lib/src/service/chat_detail_service.dart
index d317b17..d7e9e28 100644
--- a/packages/flutter_community_chat_interface/lib/src/service/message_service.dart
+++ b/packages/flutter_chat_interface/lib/src/service/chat_detail_service.dart
@@ -1,23 +1,25 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
-abstract class MessageService with ChangeNotifier {
+abstract class ChatDetailService with ChangeNotifier {
Future sendTextMessage({
- required ChatModel chat,
+ required String chatId,
required String text,
});
Future sendImageMessage({
- required ChatModel chat,
+ required String chatId,
required Uint8List image,
});
Stream> getMessagesStream(
- ChatModel chat,
+ String chatId,
);
- Future fetchMoreMessage(int pageSize, ChatModel chat);
+ Future fetchMoreMessage(int pageSize, String chatId);
List getMessages();
+
+ void stopListeningForMessages();
}
diff --git a/packages/flutter_community_chat_interface/lib/src/service/chat_service.dart b/packages/flutter_chat_interface/lib/src/service/chat_overview_service.dart
similarity index 61%
rename from packages/flutter_community_chat_interface/lib/src/service/chat_service.dart
rename to packages/flutter_chat_interface/lib/src/service/chat_overview_service.dart
index e0e668b..2f7d2e9 100644
--- a/packages/flutter_community_chat_interface/lib/src/service/chat_service.dart
+++ b/packages/flutter_chat_interface/lib/src/service/chat_overview_service.dart
@@ -1,7 +1,7 @@
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
-abstract class ChatService {
- Stream> getChatsStream(int pageSize);
+abstract class ChatOverviewService {
+ Stream> getChatsStream();
Future getChatByUser(ChatUserModel user);
Future getChatById(String id);
Future deleteChat(ChatModel chat);
diff --git a/packages/flutter_chat_interface/lib/src/service/chat_service.dart b/packages/flutter_chat_interface/lib/src/service/chat_service.dart
new file mode 100644
index 0000000..c6b87f0
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/src/service/chat_service.dart
@@ -0,0 +1,14 @@
+// ignore_for_file: public_member_api_docs, sort_constructors_first
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
+
+class ChatService {
+ final ChatUserService chatUserService;
+ final ChatOverviewService chatOverviewService;
+ final ChatDetailService chatDetailService;
+
+ ChatService({
+ required this.chatUserService,
+ required this.chatOverviewService,
+ required this.chatDetailService,
+ });
+}
diff --git a/packages/flutter_chat_interface/lib/src/service/service.dart b/packages/flutter_chat_interface/lib/src/service/service.dart
new file mode 100644
index 0000000..a65b80e
--- /dev/null
+++ b/packages/flutter_chat_interface/lib/src/service/service.dart
@@ -0,0 +1,4 @@
+export 'chat_overview_service.dart';
+export 'user_service.dart';
+export 'chat_detail_service.dart';
+export 'chat_service.dart';
diff --git a/packages/flutter_community_chat_interface/lib/src/service/user_service.dart b/packages/flutter_chat_interface/lib/src/service/user_service.dart
similarity index 65%
rename from packages/flutter_community_chat_interface/lib/src/service/user_service.dart
rename to packages/flutter_chat_interface/lib/src/service/user_service.dart
index 372689f..ba65fd6 100644
--- a/packages/flutter_community_chat_interface/lib/src/service/user_service.dart
+++ b/packages/flutter_chat_interface/lib/src/service/user_service.dart
@@ -1,4 +1,4 @@
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
+import 'package:flutter_chat_interface/flutter_chat_interface.dart';
abstract class ChatUserService {
Future getUser(String id);
diff --git a/packages/flutter_community_chat_interface/pubspec.yaml b/packages/flutter_chat_interface/pubspec.yaml
similarity index 91%
rename from packages/flutter_community_chat_interface/pubspec.yaml
rename to packages/flutter_chat_interface/pubspec.yaml
index 73753b7..5f96d22 100644
--- a/packages/flutter_community_chat_interface/pubspec.yaml
+++ b/packages/flutter_chat_interface/pubspec.yaml
@@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-name: flutter_community_chat_interface
+name: flutter_chat_interface
description: A new Flutter package project.
version: 1.0.0
publish_to: none
diff --git a/packages/flutter_community_chat_view/analysis_options.yaml b/packages/flutter_chat_view/analysis_options.yaml
similarity index 100%
rename from packages/flutter_community_chat_view/analysis_options.yaml
rename to packages/flutter_chat_view/analysis_options.yaml
diff --git a/packages/flutter_community_chat_view/example/.gitignore b/packages/flutter_chat_view/example/.gitignore
similarity index 100%
rename from packages/flutter_community_chat_view/example/.gitignore
rename to packages/flutter_chat_view/example/.gitignore
diff --git a/packages/flutter_community_chat_view/example/README.md b/packages/flutter_chat_view/example/README.md
similarity index 100%
rename from packages/flutter_community_chat_view/example/README.md
rename to packages/flutter_chat_view/example/README.md
diff --git a/packages/flutter_community_chat_view/example/analysis_options.yaml b/packages/flutter_chat_view/example/analysis_options.yaml
similarity index 100%
rename from packages/flutter_community_chat_view/example/analysis_options.yaml
rename to packages/flutter_chat_view/example/analysis_options.yaml
diff --git a/packages/flutter_community_chat_view/example/lib/main.dart b/packages/flutter_chat_view/example/lib/main.dart
similarity index 98%
rename from packages/flutter_community_chat_view/example/lib/main.dart
rename to packages/flutter_chat_view/example/lib/main.dart
index 0aca106..35b723e 100644
--- a/packages/flutter_community_chat_view/example/lib/main.dart
+++ b/packages/flutter_chat_view/example/lib/main.dart
@@ -4,7 +4,7 @@
import 'dart:async';
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
void main() {
runApp(const MaterialApp(home: MyStatefulWidget()));
diff --git a/packages/flutter_community_chat_view/example/pubspec.yaml b/packages/flutter_chat_view/example/pubspec.yaml
similarity index 85%
rename from packages/flutter_community_chat_view/example/pubspec.yaml
rename to packages/flutter_chat_view/example/pubspec.yaml
index 29a9f3d..754f658 100644
--- a/packages/flutter_community_chat_view/example/pubspec.yaml
+++ b/packages/flutter_chat_view/example/pubspec.yaml
@@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-name: flutter_community_chat_view_example
+name: flutter_chat_view_example
description: A standard flutter package.
publish_to: "none" # Remove this line if you wish to publish to pub.dev
@@ -14,7 +14,7 @@ environment:
dependencies:
flutter:
sdk: flutter
- flutter_community_chat_view:
+ flutter_chat_view:
path: ..
dev_dependencies:
diff --git a/packages/flutter_community_chat_view/example/test/widget_test.dart b/packages/flutter_chat_view/example/test/widget_test.dart
similarity index 100%
rename from packages/flutter_community_chat_view/example/test/widget_test.dart
rename to packages/flutter_chat_view/example/test/widget_test.dart
diff --git a/packages/flutter_community_chat_view/ios/Flutter/Generated.xcconfig b/packages/flutter_chat_view/ios/Flutter/Generated.xcconfig
similarity index 89%
rename from packages/flutter_community_chat_view/ios/Flutter/Generated.xcconfig
rename to packages/flutter_chat_view/ios/Flutter/Generated.xcconfig
index 1167b5a..8778ec4 100644
--- a/packages/flutter_community_chat_view/ios/Flutter/Generated.xcconfig
+++ b/packages/flutter_chat_view/ios/Flutter/Generated.xcconfig
@@ -1,6 +1,6 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/opt/homebrew/Caskroom/flutter/3.10.2/flutter
-FLUTTER_APPLICATION_PATH=/Users/mikedoornenbal/Documents/iconica/flutter_community_chat/packages/flutter_community_chat_view
+FLUTTER_APPLICATION_PATH=/Users/mikedoornenbal/Documents/iconica/flutter_chat/packages/flutter_chat_view
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib/main.dart
FLUTTER_BUILD_DIR=build
diff --git a/packages/flutter_community_chat_view/ios/Flutter/flutter_export_environment.sh b/packages/flutter_chat_view/ios/Flutter/flutter_export_environment.sh
similarity index 88%
rename from packages/flutter_community_chat_view/ios/Flutter/flutter_export_environment.sh
rename to packages/flutter_chat_view/ios/Flutter/flutter_export_environment.sh
index 8559eeb..5b36b6b 100755
--- a/packages/flutter_community_chat_view/ios/Flutter/flutter_export_environment.sh
+++ b/packages/flutter_chat_view/ios/Flutter/flutter_export_environment.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/opt/homebrew/Caskroom/flutter/3.10.2/flutter"
-export "FLUTTER_APPLICATION_PATH=/Users/mikedoornenbal/Documents/iconica/flutter_community_chat/packages/flutter_community_chat_view"
+export "FLUTTER_APPLICATION_PATH=/Users/mikedoornenbal/Documents/iconica/flutter_chat/packages/flutter_chat_view"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
diff --git a/packages/flutter_community_chat_view/ios/Podfile b/packages/flutter_chat_view/ios/Podfile
similarity index 100%
rename from packages/flutter_community_chat_view/ios/Podfile
rename to packages/flutter_chat_view/ios/Podfile
diff --git a/packages/flutter_community_chat_view/ios/Runner/GeneratedPluginRegistrant.h b/packages/flutter_chat_view/ios/Runner/GeneratedPluginRegistrant.h
similarity index 100%
rename from packages/flutter_community_chat_view/ios/Runner/GeneratedPluginRegistrant.h
rename to packages/flutter_chat_view/ios/Runner/GeneratedPluginRegistrant.h
diff --git a/packages/flutter_community_chat_view/ios/Runner/GeneratedPluginRegistrant.m b/packages/flutter_chat_view/ios/Runner/GeneratedPluginRegistrant.m
similarity index 100%
rename from packages/flutter_community_chat_view/ios/Runner/GeneratedPluginRegistrant.m
rename to packages/flutter_chat_view/ios/Runner/GeneratedPluginRegistrant.m
diff --git a/packages/flutter_community_chat_view/lib/flutter_community_chat_view.dart b/packages/flutter_chat_view/lib/flutter_chat_view.dart
similarity index 64%
rename from packages/flutter_community_chat_view/lib/flutter_community_chat_view.dart
rename to packages/flutter_chat_view/lib/flutter_chat_view.dart
index f855097..063ac8b 100644
--- a/packages/flutter_community_chat_view/lib/flutter_community_chat_view.dart
+++ b/packages/flutter_chat_view/lib/flutter_chat_view.dart
@@ -2,13 +2,15 @@
//
// SPDX-License-Identifier: BSD-3-Clause
-library flutter_community_chat_view;
+library flutter_chat_view;
-export 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
+export 'package:flutter_chat_interface/flutter_chat_interface.dart';
export 'src/components/chat_row.dart';
export 'src/config/chat_options.dart';
export 'src/config/chat_translations.dart';
export 'src/screens/chat_detail_screen.dart';
+export 'src/screens/chat_entry_widget.dart';
+export 'src/screens/chat_profile_screen.dart';
export 'src/screens/chat_screen.dart';
export 'src/screens/new_chat_screen.dart';
diff --git a/packages/flutter_community_chat_view/lib/src/components/chat_bottom.dart b/packages/flutter_chat_view/lib/src/components/chat_bottom.dart
similarity index 96%
rename from packages/flutter_community_chat_view/lib/src/components/chat_bottom.dart
rename to packages/flutter_chat_view/lib/src/components/chat_bottom.dart
index e9fb8dd..df56ea4 100644
--- a/packages/flutter_community_chat_view/lib/src/components/chat_bottom.dart
+++ b/packages/flutter_chat_view/lib/src/components/chat_bottom.dart
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
class ChatBottom extends StatefulWidget {
const ChatBottom({
diff --git a/packages/flutter_community_chat_view/lib/src/components/chat_detail_row.dart b/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart
similarity index 96%
rename from packages/flutter_community_chat_view/lib/src/components/chat_detail_row.dart
rename to packages/flutter_chat_view/lib/src/components/chat_detail_row.dart
index 217b037..d296920 100644
--- a/packages/flutter_community_chat_view/lib/src/components/chat_detail_row.dart
+++ b/packages/flutter_chat_view/lib/src/components/chat_detail_row.dart
@@ -4,9 +4,9 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
-import 'package:flutter_community_chat_view/src/components/chat_image.dart';
-import 'package:flutter_community_chat_view/src/services/date_formatter.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
+import 'package:flutter_chat_view/src/components/chat_image.dart';
+import 'package:flutter_chat_view/src/services/date_formatter.dart';
class ChatDetailRow extends StatefulWidget {
const ChatDetailRow({
diff --git a/packages/flutter_community_chat_view/lib/src/components/chat_image.dart b/packages/flutter_chat_view/lib/src/components/chat_image.dart
similarity index 100%
rename from packages/flutter_community_chat_view/lib/src/components/chat_image.dart
rename to packages/flutter_chat_view/lib/src/components/chat_image.dart
diff --git a/packages/flutter_community_chat_view/lib/src/components/chat_row.dart b/packages/flutter_chat_view/lib/src/components/chat_row.dart
similarity index 100%
rename from packages/flutter_community_chat_view/lib/src/components/chat_row.dart
rename to packages/flutter_chat_view/lib/src/components/chat_row.dart
diff --git a/packages/flutter_community_chat_view/lib/src/components/image_loading_snackbar.dart b/packages/flutter_chat_view/lib/src/components/image_loading_snackbar.dart
similarity index 86%
rename from packages/flutter_community_chat_view/lib/src/components/image_loading_snackbar.dart
rename to packages/flutter_chat_view/lib/src/components/image_loading_snackbar.dart
index 18e42e0..68e1ac0 100644
--- a/packages/flutter_community_chat_view/lib/src/components/image_loading_snackbar.dart
+++ b/packages/flutter_chat_view/lib/src/components/image_loading_snackbar.dart
@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
SnackBar getImageLoadingSnackbar(ChatTranslations translations) => SnackBar(
duration: const Duration(minutes: 1),
diff --git a/packages/flutter_community_chat_view/lib/src/config/chat_options.dart b/packages/flutter_chat_view/lib/src/config/chat_options.dart
similarity index 96%
rename from packages/flutter_community_chat_view/lib/src/config/chat_options.dart
rename to packages/flutter_chat_view/lib/src/config/chat_options.dart
index ad72a7d..dc5e1b3 100644
--- a/packages/flutter_community_chat_view/lib/src/config/chat_options.dart
+++ b/packages/flutter_chat_view/lib/src/config/chat_options.dart
@@ -3,8 +3,8 @@
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
-import 'package:flutter_community_chat_view/src/components/chat_image.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
+import 'package:flutter_chat_view/src/components/chat_image.dart';
import 'package:flutter_image_picker/flutter_image_picker.dart';
class ChatOptions {
diff --git a/packages/flutter_community_chat_view/lib/src/config/chat_translations.dart b/packages/flutter_chat_view/lib/src/config/chat_translations.dart
similarity index 95%
rename from packages/flutter_community_chat_view/lib/src/config/chat_translations.dart
rename to packages/flutter_chat_view/lib/src/config/chat_translations.dart
index da8fd9a..f4a2d56 100644
--- a/packages/flutter_community_chat_view/lib/src/config/chat_translations.dart
+++ b/packages/flutter_chat_view/lib/src/config/chat_translations.dart
@@ -22,6 +22,7 @@ class ChatTranslations {
this.noUsersFound = 'No users found',
this.anonymousUser = 'Anonymous user',
this.chatCantBeDeleted = 'This chat can\'t be deleted',
+ this.chatProfileUsers = 'Users:',
});
final String chatsTitle;
@@ -40,6 +41,7 @@ class ChatTranslations {
final String deleteChatModalConfirm;
final String noUsersFound;
final String chatCantBeDeleted;
+ final String chatProfileUsers;
/// Shown when the user has no name
final String anonymousUser;
diff --git a/packages/flutter_community_chat_view/lib/src/screens/chat_detail_screen.dart b/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart
similarity index 82%
rename from packages/flutter_community_chat_view/lib/src/screens/chat_detail_screen.dart
rename to packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart
index 26f6ae5..288f7ab 100644
--- a/packages/flutter_community_chat_view/lib/src/screens/chat_detail_screen.dart
+++ b/packages/flutter_chat_view/lib/src/screens/chat_detail_screen.dart
@@ -7,10 +7,10 @@ import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
-import 'package:flutter_community_chat_view/src/components/chat_bottom.dart';
-import 'package:flutter_community_chat_view/src/components/chat_detail_row.dart';
-import 'package:flutter_community_chat_view/src/components/image_loading_snackbar.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
+import 'package:flutter_chat_view/src/components/chat_bottom.dart';
+import 'package:flutter_chat_view/src/components/chat_detail_row.dart';
+import 'package:flutter_chat_view/src/components/image_loading_snackbar.dart';
class ChatDetailScreen extends StatefulWidget {
const ChatDetailScreen({
@@ -19,18 +19,16 @@ class ChatDetailScreen extends StatefulWidget {
required this.onUploadImage,
required this.onReadChat,
required this.service,
- required this.chatUserService,
- required this.messageService,
required this.pageSize,
+ required this.chatId,
this.translations = const ChatTranslations(),
- this.chat,
this.onPressChatTitle,
this.iconColor,
this.showTime = false,
super.key,
});
- final ChatModel? chat;
+ final String chatId;
/// The id of the current user that is viewing the chat.
@@ -47,8 +45,6 @@ class ChatDetailScreen extends StatefulWidget {
final Color? iconColor;
final bool showTime;
final ChatService service;
- final ChatUserService chatUserService;
- final MessageService messageService;
final int pageSize;
@override
@@ -60,36 +56,39 @@ class _ChatDetailScreenState extends State {
ChatUserModel? currentUser;
ScrollController controller = ScrollController();
bool showIndicator = false;
- late MessageService messageSubscription;
+ late ChatDetailService messageSubscription;
Stream>? stream;
ChatMessageModel? previousMessage;
List detailRows = [];
+ ChatModel? chat;
@override
void initState() {
super.initState();
- messageSubscription = widget.messageService;
+ messageSubscription = widget.service.chatDetailService;
messageSubscription.addListener(onListen);
- if (widget.chat != null) {
- stream = widget.messageService.getMessagesStream(widget.chat!);
- stream?.listen((event) {});
- Future.delayed(Duration.zero, () async {
- if (detailRows.isEmpty) {
- await widget.messageService
- .fetchMoreMessage(widget.pageSize, widget.chat!);
- }
- });
- }
- WidgetsBinding.instance.addPostFrameCallback((_) {
- if (widget.chat != null) {
- widget.onReadChat(widget.chat!);
+ Future.delayed(Duration.zero, () async {
+ chat =
+ await widget.service.chatOverviewService.getChatById(widget.chatId);
+
+ if (detailRows.isEmpty) {
+ await widget.service.chatDetailService.fetchMoreMessage(
+ widget.pageSize,
+ chat!.id!,
+ );
}
+ stream = widget.service.chatDetailService.getMessagesStream(chat!.id!);
+ stream?.listen((event) {});
+
+ WidgetsBinding.instance.addPostFrameCallback((_) async {
+ await widget.onReadChat(chat!);
+ });
});
}
void onListen() {
var chatMessages = [];
- chatMessages = widget.messageService.getMessages();
+ chatMessages = widget.service.chatDetailService.getMessages();
detailRows = [];
previousMessage = null;
for (var message in chatMessages) {
@@ -106,8 +105,11 @@ class _ChatDetailScreenState extends State {
}
detailRows = detailRows.reversed.toList();
- widget.onReadChat(widget.chat!);
if (mounted) {
+ WidgetsBinding.instance.addPostFrameCallback((_) async {
+ await widget.onReadChat(chat!);
+ });
+
setState(() {});
}
}
@@ -115,6 +117,7 @@ class _ChatDetailScreenState extends State {
@override
void dispose() {
messageSubscription.removeListener(onListen);
+ widget.service.chatDetailService.stopListeningForMessages();
super.dispose();
}
@@ -132,18 +135,19 @@ class _ChatDetailScreenState extends State {
var messenger = ScaffoldMessenger.of(context)
..showSnackBar(
getImageLoadingSnackbar(widget.translations),
- );
-
+ )
+ ..activate();
if (image != null) {
await widget.onUploadImage(image);
}
-
- messenger.hideCurrentSnackBar();
+ Future.delayed(const Duration(seconds: 1), () {
+ messenger.hideCurrentSnackBar();
+ });
},
);
return FutureBuilder(
- future: widget.service.getChatById(widget.chat?.id ?? ''),
+ future: widget.service.chatOverviewService.getChatById(widget.chatId),
builder: (context, AsyncSnapshot snapshot) {
var chatModel = snapshot.data;
return Scaffold(
@@ -153,7 +157,7 @@ class _ChatDetailScreenState extends State {
onTap: () => widget.onPressChatTitle?.call(context, chatModel!),
child: Row(
mainAxisSize: MainAxisSize.min,
- children: widget.chat == null
+ children: chat == null
? []
: [
if (chatModel is GroupChatModel) ...[
@@ -202,8 +206,8 @@ class _ChatDetailScreenState extends State {
setState(() {
showIndicator = true;
});
- await widget.messageService
- .fetchMoreMessage(widget.pageSize, widget.chat!);
+ await widget.service.chatDetailService
+ .fetchMoreMessage(widget.pageSize, widget.chatId);
Future.delayed(const Duration(seconds: 2), () {
if (mounted) {
setState(() {
diff --git a/packages/flutter_chat_view/lib/src/screens/chat_entry_widget.dart b/packages/flutter_chat_view/lib/src/screens/chat_entry_widget.dart
new file mode 100644
index 0000000..3be4ad2
--- /dev/null
+++ b/packages/flutter_chat_view/lib/src/screens/chat_entry_widget.dart
@@ -0,0 +1,146 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
+
+class ChatEntryWidget extends StatefulWidget {
+ const ChatEntryWidget({
+ required this.chatService,
+ required this.onTap,
+ this.widgetSize = 75,
+ this.backgroundColor = Colors.grey,
+ this.icon = Icons.chat,
+ this.iconColor = Colors.black,
+ this.counterBackgroundColor = Colors.red,
+ this.textStyle,
+ super.key,
+ });
+
+ final ChatService chatService;
+ final Color backgroundColor;
+ final double widgetSize;
+ final Color counterBackgroundColor;
+ final Function() onTap;
+ final IconData icon;
+ final Color iconColor;
+ final TextStyle? textStyle;
+
+ @override
+ State createState() => _ChatEntryWidgetState();
+}
+
+class _ChatEntryWidgetState extends State {
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: () => widget.onTap.call(),
+ child: StreamBuilder(
+ stream:
+ widget.chatService.chatOverviewService.getUnreadChatsCountStream(),
+ builder: (BuildContext context, snapshot) {
+ return Stack(
+ alignment: Alignment.center,
+ children: [
+ Container(
+ width: widget.widgetSize,
+ height: widget.widgetSize,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: widget.backgroundColor,
+ ),
+ child: _AnimatedNotificationIcon(
+ icon: Icon(
+ widget.icon,
+ color: widget.iconColor,
+ size: widget.widgetSize / 1.5,
+ ),
+ notifications: snapshot.data ?? 0,
+ ),
+ ),
+ Positioned(
+ right: 0.0,
+ top: 0.0,
+ child: Container(
+ width: widget.widgetSize / 2,
+ height: widget.widgetSize / 2,
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: widget.counterBackgroundColor,
+ ),
+ child: Center(
+ child: Text(
+ '${snapshot.data ?? 0}',
+ style: widget.textStyle,
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+ },
+ ),
+ );
+ }
+}
+
+class _AnimatedNotificationIcon extends StatefulWidget {
+ const _AnimatedNotificationIcon({
+ required this.notifications,
+ required this.icon,
+ });
+
+ final int notifications;
+ final Icon icon;
+
+ @override
+ State<_AnimatedNotificationIcon> createState() =>
+ _AnimatedNotificationIconState();
+}
+
+class _AnimatedNotificationIconState extends State<_AnimatedNotificationIcon>
+ with SingleTickerProviderStateMixin {
+ late AnimationController _animationController;
+
+ @override
+ void initState() {
+ _animationController = AnimationController(
+ vsync: this,
+ duration: const Duration(milliseconds: 500),
+ );
+
+ if (widget.notifications != 0) {
+ unawaited(_runAnimation());
+ }
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ _animationController.dispose();
+ }
+
+ @override
+ void didUpdateWidget(covariant _AnimatedNotificationIcon oldWidget) {
+ super.didUpdateWidget(oldWidget);
+
+ if (oldWidget.notifications != widget.notifications) {
+ _runAnimation();
+ }
+ }
+
+ Future _runAnimation() async {
+ await _animationController.forward();
+ await _animationController.reverse();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return RotationTransition(
+ turns: Tween(begin: 0.0, end: -.1)
+ .chain(CurveTween(curve: Curves.elasticIn))
+ .animate(_animationController),
+ child: widget.icon,
+ );
+ }
+}
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
new file mode 100644
index 0000000..f432231
--- /dev/null
+++ b/packages/flutter_chat_view/lib/src/screens/chat_profile_screen.dart
@@ -0,0 +1,129 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
+import 'package:flutter_chat_view/src/services/profile_service.dart';
+import 'package:flutter_profile/flutter_profile.dart';
+
+class ChatProfileScreen extends StatefulWidget {
+ const ChatProfileScreen({
+ required this.chatService,
+ required this.chatId,
+ required this.translations,
+ required this.onTapUser,
+ this.userId,
+ super.key,
+ });
+
+ final ChatTranslations translations;
+ final ChatService chatService;
+ final String chatId;
+ final String? userId;
+ final Function(String userId) onTapUser;
+
+ @override
+ State createState() => _ProfileScreenState();
+}
+
+class _ProfileScreenState extends State {
+ @override
+ Widget build(BuildContext context) {
+ var size = MediaQuery.of(context).size;
+ var hasUser = widget.userId == null;
+ return FutureBuilder(
+ future: hasUser
+ ? widget.chatService.chatOverviewService.getChatById(widget.chatId)
+ : widget.chatService.chatUserService.getUser(widget.userId!),
+ builder: (context, snapshot) {
+ var data = snapshot.data;
+ User? user;
+
+ if (data is ChatUserModel) {
+ user = User(
+ firstName: data.firstName,
+ lastName: data.lastName,
+ imageUrl: data.imageUrl,
+ );
+ }
+ if (data is PersonalChatModel) {
+ user = User(
+ firstName: data.user.firstName,
+ lastName: data.user.lastName,
+ imageUrl: data.user.imageUrl,
+ );
+ } else if (data is GroupChatModel) {
+ user = User(
+ firstName: data.title,
+ imageUrl: data.imageUrl,
+ );
+ }
+
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(
+ (data is ChatUserModel)
+ ? '${data.firstName ?? ''} ${data.lastName ?? ''}'
+ : (data is PersonalChatModel)
+ ? data.user.fullName ?? ''
+ : (data is GroupChatModel)
+ ? data.title
+ : '',
+ ),
+ ),
+ body: snapshot.hasData
+ ? ListView(
+ children: [
+ const SizedBox(
+ height: 10,
+ ),
+ SizedBox(
+ height: 200,
+ width: size.width,
+ child: ProfilePage(
+ user: user!,
+ service: ChatProfileService(),
+ ),
+ ),
+ if (data is GroupChatModel) ...[
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 100),
+ child: Text(
+ widget.translations.chatProfileUsers,
+ style: const TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ ...data.users.map((e) {
+ var user = User(
+ firstName: e.firstName ?? '',
+ lastName: e.lastName ?? '',
+ imageUrl: e.imageUrl,
+ );
+ return Padding(
+ padding: const EdgeInsets.symmetric(vertical: 4.0),
+ child: GestureDetector(
+ onTap: () => widget.onTapUser.call(e.id!),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Avatar(
+ user: user,
+ ),
+ Text(
+ user.firstName!,
+ ),
+ ],
+ ),
+ ),
+ );
+ }),
+ ],
+ ],
+ )
+ : const Center(child: CircularProgressIndicator()),
+ );
+ },
+ );
+ }
+}
diff --git a/packages/flutter_chat_view/lib/src/screens/chat_screen.dart b/packages/flutter_chat_view/lib/src/screens/chat_screen.dart
new file mode 100644
index 0000000..192a2da
--- /dev/null
+++ b/packages/flutter_chat_view/lib/src/screens/chat_screen.dart
@@ -0,0 +1,312 @@
+// SPDX-FileCopyrightText: 2022 Iconica
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+// ignore_for_file: lines_longer_than_80_chars
+
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
+import 'package:flutter_chat_view/src/services/date_formatter.dart';
+
+class ChatScreen extends StatefulWidget {
+ const ChatScreen({
+ required this.options,
+ required this.onPressStartChat,
+ required this.onPressChat,
+ required this.onDeleteChat,
+ required this.service,
+ this.onNoChats,
+ this.deleteChatDialog,
+ this.translations = const ChatTranslations(),
+ this.disableDismissForPermanentChats = false,
+ super.key,
+ });
+
+ final ChatOptions options;
+ final ChatTranslations translations;
+ final ChatService service;
+ final Function()? onPressStartChat;
+ final Function()? onNoChats;
+ final void Function(ChatModel chat) onDeleteChat;
+ final void Function(ChatModel chat) onPressChat;
+
+ /// Disable 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();
+}
+
+class _ChatScreenState extends State {
+ final DateFormatter _dateFormatter = DateFormatter();
+ bool _hasCalledOnNoChats = false;
+ ScrollController controller = ScrollController();
+ bool showIndicator = false;
+ Stream>? chats;
+ List deletedChats = [];
+
+ @override
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ var translations = widget.translations;
+ return widget.options.scaffoldBuilder(
+ AppBar(
+ title: Text(translations.chatsTitle),
+ centerTitle: true,
+ actions: [
+ StreamBuilder(
+ stream:
+ widget.service.chatOverviewService.getUnreadChatsCountStream(),
+ builder: (BuildContext context, snapshot) => Align(
+ alignment: Alignment.centerRight,
+ child: Padding(
+ padding: const EdgeInsets.only(right: 22.0),
+ child: Text(
+ '${snapshot.data ?? 0} ${translations.chatsUnread}',
+ style: const TextStyle(
+ color: Color(0xFFBBBBBB),
+ fontSize: 14,
+ ),
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ Column(
+ children: [
+ Expanded(
+ child: ListView(
+ controller: controller,
+ physics: const AlwaysScrollableScrollPhysics(),
+ padding: const EdgeInsets.only(top: 15.0),
+ children: [
+ StreamBuilder>(
+ stream: widget.service.chatOverviewService.getChatsStream(),
+ builder: (BuildContext context, snapshot) {
+ // if the stream is done, empty and noChats is set we should call that
+ if (snapshot.connectionState == ConnectionState.done &&
+ (snapshot.data?.isEmpty ?? true)) {
+ if (widget.onNoChats != null && !_hasCalledOnNoChats) {
+ _hasCalledOnNoChats = true; // Set the flag to true
+ WidgetsBinding.instance.addPostFrameCallback((_) async {
+ await widget.onNoChats!.call();
+ });
+ }
+ } else {
+ _hasCalledOnNoChats =
+ false; // Reset the flag if there are chats
+ }
+ return Column(
+ children: [
+ for (ChatModel chat in (snapshot.data ?? []).where(
+ (chat) => !deletedChats.contains(chat.id),
+ )) ...[
+ Builder(
+ builder: (context) => !(widget
+ .disableDismissForPermanentChats &&
+ !chat.canBeDeleted)
+ ? Dismissible(
+ confirmDismiss: (_) async =>
+ widget.deleteChatDialog
+ ?.call(context, chat) ??
+ showModalBottomSheet(
+ context: context,
+ builder: (BuildContext context) =>
+ Container(
+ padding: const EdgeInsets.all(16.0),
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Text(
+ chat.canBeDeleted
+ ? translations
+ .deleteChatModalTitle
+ : translations
+ .chatCantBeDeleted,
+ style: const TextStyle(
+ fontSize: 20,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ const SizedBox(height: 16),
+ if (chat.canBeDeleted)
+ Text(
+ translations
+ .deleteChatModalDescription,
+ style: const TextStyle(
+ fontSize: 16,
+ ),
+ ),
+ const SizedBox(height: 16),
+ Row(
+ mainAxisAlignment:
+ MainAxisAlignment.center,
+ children: [
+ TextButton(
+ child: Text(
+ translations
+ .deleteChatModalCancel,
+ style: const TextStyle(
+ fontSize: 16,
+ ),
+ ),
+ onPressed: () =>
+ Navigator.of(
+ context,
+ ).pop(false),
+ ),
+ if (chat.canBeDeleted)
+ ElevatedButton(
+ onPressed: () =>
+ Navigator.of(
+ context,
+ ).pop(true),
+ child: Text(
+ translations
+ .deleteChatModalConfirm,
+ style:
+ const TextStyle(
+ fontSize: 16,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ onDismissed: (_) {
+ setState(() {
+ deletedChats.add(chat.id!);
+ });
+ widget.onDeleteChat(chat);
+ },
+ background: Container(
+ color: Colors.red,
+ child: Align(
+ alignment: Alignment.centerRight,
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Text(
+ translations.deleteChatButton,
+ ),
+ ),
+ ),
+ ),
+ key: ValueKey(
+ chat.id.toString(),
+ ),
+ child: ChatListItem(
+ widget: widget,
+ chat: chat,
+ translations: translations,
+ dateFormatter: _dateFormatter,
+ ),
+ )
+ : ChatListItem(
+ widget: widget,
+ chat: chat,
+ translations: translations,
+ dateFormatter: _dateFormatter,
+ ),
+ ),
+ ],
+ ],
+ );
+ },
+ ),
+ ],
+ ),
+ ),
+ if (widget.onPressStartChat != null)
+ widget.options.newChatButtonBuilder(
+ context,
+ () async {
+ await widget.onPressStartChat!.call();
+ },
+ translations,
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class ChatListItem extends StatelessWidget {
+ const ChatListItem({
+ required this.widget,
+ required this.chat,
+ required this.translations,
+ required DateFormatter dateFormatter,
+ super.key,
+ }) : _dateFormatter = dateFormatter;
+
+ final ChatScreen widget;
+ final ChatModel chat;
+ final ChatTranslations translations;
+ final DateFormatter _dateFormatter;
+
+ @override
+ Widget build(BuildContext context) {
+ return GestureDetector(
+ onTap: () => widget.onPressChat(chat),
+ child: Container(
+ color: Colors.transparent,
+ child: widget.options.chatRowContainerBuilder(
+ (chat is PersonalChatModel)
+ ? ChatRow(
+ unreadMessages: chat.unreadMessages ?? 0,
+ avatar: widget.options.userAvatarBuilder(
+ (chat as PersonalChatModel).user,
+ 40.0,
+ ),
+ title: (chat as PersonalChatModel).user.fullName ??
+ translations.anonymousUser,
+ subTitle: chat.lastMessage != null
+ ? chat.lastMessage is ChatTextMessageModel
+ ? (chat.lastMessage! as ChatTextMessageModel).text
+ : '📷 '
+ '${translations.image}'
+ : '',
+ lastUsed: chat.lastUsed != null
+ ? _dateFormatter.format(
+ date: chat.lastUsed!,
+ )
+ : null,
+ )
+ : ChatRow(
+ title: (chat as GroupChatModel).title,
+ unreadMessages: chat.unreadMessages ?? 0,
+ subTitle: chat.lastMessage != null
+ ? chat.lastMessage is ChatTextMessageModel
+ ? (chat.lastMessage! as ChatTextMessageModel).text
+ : '📷 '
+ '${translations.image}'
+ : '',
+ avatar: widget.options.groupAvatarBuilder(
+ (chat as GroupChatModel).title,
+ (chat as GroupChatModel).imageUrl,
+ 40.0,
+ ),
+ lastUsed: chat.lastUsed != null
+ ? _dateFormatter.format(
+ date: chat.lastUsed!,
+ )
+ : null,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/packages/flutter_community_chat_view/lib/src/screens/new_chat_screen.dart b/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart
similarity index 94%
rename from packages/flutter_community_chat_view/lib/src/screens/new_chat_screen.dart
rename to packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart
index 80f0610..b18395a 100644
--- a/packages/flutter_community_chat_view/lib/src/screens/new_chat_screen.dart
+++ b/packages/flutter_chat_view/lib/src/screens/new_chat_screen.dart
@@ -3,14 +3,13 @@
// SPDX-License-Identifier: BSD-3-Clause
import 'package:flutter/material.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
+import 'package:flutter_chat_view/flutter_chat_view.dart';
class NewChatScreen extends StatefulWidget {
const NewChatScreen({
required this.options,
required this.onPressCreateChat,
required this.service,
- required this.userService,
this.translations = const ChatTranslations(),
super.key,
});
@@ -18,7 +17,6 @@ class NewChatScreen extends StatefulWidget {
final ChatOptions options;
final ChatTranslations translations;
final ChatService service;
- final ChatUserService userService;
final Function(ChatUserModel) onPressCreateChat;
@override
@@ -40,7 +38,7 @@ class _NewChatScreenState extends State {
],
),
body: FutureBuilder>(
- future: widget.userService.getAllUsers(),
+ future: widget.service.chatUserService.getAllUsers(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
diff --git a/packages/flutter_community_chat_view/lib/src/services/date_formatter.dart b/packages/flutter_chat_view/lib/src/services/date_formatter.dart
similarity index 100%
rename from packages/flutter_community_chat_view/lib/src/services/date_formatter.dart
rename to packages/flutter_chat_view/lib/src/services/date_formatter.dart
diff --git a/packages/flutter_chat_view/lib/src/services/profile_service.dart b/packages/flutter_chat_view/lib/src/services/profile_service.dart
new file mode 100644
index 0000000..644e10a
--- /dev/null
+++ b/packages/flutter_chat_view/lib/src/services/profile_service.dart
@@ -0,0 +1,24 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_profile/flutter_profile.dart';
+
+class ChatProfileService extends ProfileService {
+ @override
+ FutureOr editProfile(User user, String key, String? value) {
+ throw UnimplementedError();
+ }
+
+ @override
+ FutureOr pageBottomAction() {
+ throw UnimplementedError();
+ }
+
+ @override
+ FutureOr uploadImage(
+ BuildContext context, {
+ required Function(bool isUploading) onUploadStateChanged,
+ }) {
+ throw UnimplementedError();
+ }
+}
diff --git a/packages/flutter_community_chat_view/pubspec.yaml b/packages/flutter_chat_view/pubspec.yaml
similarity index 66%
rename from packages/flutter_community_chat_view/pubspec.yaml
rename to packages/flutter_chat_view/pubspec.yaml
index ba3f64c..68ac749 100644
--- a/packages/flutter_community_chat_view/pubspec.yaml
+++ b/packages/flutter_chat_view/pubspec.yaml
@@ -2,7 +2,7 @@
#
# SPDX-License-Identifier: GPL-3.0-or-later
-name: flutter_community_chat_view
+name: flutter_chat_view
description: A standard flutter package.
version: 1.0.0
@@ -16,16 +16,20 @@ dependencies:
flutter:
sdk: flutter
intl: any
- flutter_community_chat_interface:
+ flutter_chat_interface:
git:
- url: https://github.com/Iconica-Development/flutter_community_chat
- path: packages/flutter_community_chat_interface
+ url: https://github.com/Iconica-Development/flutter_chat
+ path: packages/flutter_chat_interface
ref: 1.0.0
cached_network_image: ^3.2.2
flutter_image_picker:
git:
url: https://github.com/Iconica-Development/flutter_image_picker
ref: 1.0.4
+ flutter_profile:
+ git:
+ ref: 1.1.5
+ url: https://github.com/Iconica-Development/flutter_profile
dev_dependencies:
flutter_test:
diff --git a/packages/flutter_community_chat_view/test/flutter_community_chat_test.dart b/packages/flutter_chat_view/test/flutter_community_chat_test.dart
similarity index 100%
rename from packages/flutter_community_chat_view/test/flutter_community_chat_test.dart
rename to packages/flutter_chat_view/test/flutter_community_chat_test.dart
diff --git a/packages/flutter_community_chat/lib/flutter_community_chat.dart b/packages/flutter_community_chat/lib/flutter_community_chat.dart
deleted file mode 100644
index 98b5f46..0000000
--- a/packages/flutter_community_chat/lib/flutter_community_chat.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-library flutter_community_chat;
-
-export 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
-export 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
-export 'package:flutter_community_chat/src/routes.dart';
-export 'package:flutter_community_chat/src/models/community_chat_configuration.dart';
-export 'package:flutter_community_chat/src/flutter_community_chat_userstory.dart';
diff --git a/packages/flutter_community_chat_firebase/lib/flutter_community_chat_firebase.dart b/packages/flutter_community_chat_firebase/lib/flutter_community_chat_firebase.dart
deleted file mode 100644
index 4f314b8..0000000
--- a/packages/flutter_community_chat_firebase/lib/flutter_community_chat_firebase.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-library flutter_community_chat_firebase;
-
-export 'package:flutter_community_chat_firebase/service/service.dart';
diff --git a/packages/flutter_community_chat_firebase/lib/service/service.dart b/packages/flutter_community_chat_firebase/lib/service/service.dart
deleted file mode 100644
index 065193e..0000000
--- a/packages/flutter_community_chat_firebase/lib/service/service.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-export 'package:flutter_community_chat_firebase/service/firebase_user_service.dart';
-export 'package:flutter_community_chat_firebase/service/firebase_message_service.dart';
-export 'package:flutter_community_chat_firebase/service/firebase_chat_service.dart';
diff --git a/packages/flutter_community_chat_interface/lib/flutter_community_chat_interface.dart b/packages/flutter_community_chat_interface/lib/flutter_community_chat_interface.dart
deleted file mode 100644
index bb7b9d7..0000000
--- a/packages/flutter_community_chat_interface/lib/flutter_community_chat_interface.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-library flutter_community_chat_interface;
-
-export 'package:flutter_community_chat_interface/src/chat_data_provider.dart';
-export 'package:flutter_community_chat_interface/src/model/model.dart';
-export 'package:flutter_community_chat_interface/src/service/service.dart';
diff --git a/packages/flutter_community_chat_interface/lib/src/model/chat.dart b/packages/flutter_community_chat_interface/lib/src/model/chat.dart
deleted file mode 100644
index 7ea2761..0000000
--- a/packages/flutter_community_chat_interface/lib/src/model/chat.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-import 'package:flutter_community_chat_interface/src/model/chat_message.dart';
-
-abstract class ChatModel {
- ChatModel({
- this.id,
- this.messages = const [],
- this.unreadMessages,
- this.lastUsed,
- this.lastMessage,
- this.canBeDeleted = true,
- });
-
- String? id;
- List? messages;
- int? unreadMessages;
- DateTime? lastUsed;
- ChatMessageModel? lastMessage;
- bool canBeDeleted;
-}
diff --git a/packages/flutter_community_chat_interface/lib/src/model/chat_image_message.dart b/packages/flutter_community_chat_interface/lib/src/model/chat_image_message.dart
deleted file mode 100644
index 6f5b207..0000000
--- a/packages/flutter_community_chat_interface/lib/src/model/chat_image_message.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-import 'package:flutter_community_chat_interface/src/model/chat_message.dart';
-
-class ChatImageMessageModel extends ChatMessageModel {
- ChatImageMessageModel({
- required super.sender,
- required super.timestamp,
- required this.imageUrl,
- });
-
- final String imageUrl;
-}
diff --git a/packages/flutter_community_chat_interface/lib/src/model/chat_message.dart b/packages/flutter_community_chat_interface/lib/src/model/chat_message.dart
deleted file mode 100644
index 05fbba0..0000000
--- a/packages/flutter_community_chat_interface/lib/src/model/chat_message.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-import 'package:flutter_community_chat_interface/src/model/chat_user.dart';
-
-abstract class ChatMessageModel {
- const ChatMessageModel({
- required this.sender,
- required this.timestamp,
- });
-
- final ChatUserModel sender;
- final DateTime timestamp;
-}
diff --git a/packages/flutter_community_chat_interface/lib/src/model/chat_text_message.dart b/packages/flutter_community_chat_interface/lib/src/model/chat_text_message.dart
deleted file mode 100644
index 5eb2af3..0000000
--- a/packages/flutter_community_chat_interface/lib/src/model/chat_text_message.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-import 'package:flutter_community_chat_interface/src/model/chat_message.dart';
-
-class ChatTextMessageModel extends ChatMessageModel {
- ChatTextMessageModel({
- required super.sender,
- required super.timestamp,
- required this.text,
- });
-
- final String text;
-}
diff --git a/packages/flutter_community_chat_interface/lib/src/model/group_chat.dart b/packages/flutter_community_chat_interface/lib/src/model/group_chat.dart
deleted file mode 100644
index 3caeca5..0000000
--- a/packages/flutter_community_chat_interface/lib/src/model/group_chat.dart
+++ /dev/null
@@ -1,46 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
-
-class GroupChatModel extends ChatModel {
- GroupChatModel({
- required this.title,
- required this.imageUrl,
- required this.users,
- super.id,
- super.messages,
- super.lastUsed,
- super.lastMessage,
- super.unreadMessages,
- super.canBeDeleted,
- });
-
- final String title;
- final String imageUrl;
- final List users;
-
- GroupChatModel copyWith({
- String? id,
- List? messages,
- int? unreadMessages,
- DateTime? lastUsed,
- ChatMessageModel? lastMessage,
- String? title,
- String? imageUrl,
- List? users,
- bool? canBeDeleted,
- }) =>
- 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,
- canBeDeleted: canBeDeleted ?? this.canBeDeleted,
- );
-}
diff --git a/packages/flutter_community_chat_interface/lib/src/model/personal_chat.dart b/packages/flutter_community_chat_interface/lib/src/model/personal_chat.dart
deleted file mode 100644
index 28dd123..0000000
--- a/packages/flutter_community_chat_interface/lib/src/model/personal_chat.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-import 'package:flutter_community_chat_interface/flutter_community_chat_interface.dart';
-
-class PersonalChatModel extends ChatModel {
- PersonalChatModel({
- required this.user,
- super.id,
- super.messages,
- super.unreadMessages,
- super.lastUsed,
- super.lastMessage,
- super.canBeDeleted,
- });
-
- final ChatUserModel user;
-
- PersonalChatModel copyWith({
- String? id,
- List? messages,
- int? unreadMessages,
- DateTime? lastUsed,
- ChatMessageModel? lastMessage,
- ChatUserModel? user,
- bool? canBeDeleted,
- }) =>
- 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,
- canBeDeleted: canBeDeleted ?? this.canBeDeleted,
- );
-}
diff --git a/packages/flutter_community_chat_interface/lib/src/service/service.dart b/packages/flutter_community_chat_interface/lib/src/service/service.dart
deleted file mode 100644
index 8043b14..0000000
--- a/packages/flutter_community_chat_interface/lib/src/service/service.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-export 'chat_service.dart';
-export 'user_service.dart';
-export 'message_service.dart';
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
deleted file mode 100644
index 524c1b2..0000000
--- a/packages/flutter_community_chat_view/lib/src/screens/chat_screen.dart
+++ /dev/null
@@ -1,367 +0,0 @@
-// SPDX-FileCopyrightText: 2022 Iconica
-//
-// SPDX-License-Identifier: BSD-3-Clause
-
-// ignore_for_file: lines_longer_than_80_chars
-
-import 'dart:async';
-
-import 'package:flutter/material.dart';
-import 'package:flutter/rendering.dart';
-import 'package:flutter_community_chat_view/flutter_community_chat_view.dart';
-import 'package:flutter_community_chat_view/src/services/date_formatter.dart';
-
-class ChatScreen extends StatefulWidget {
- const ChatScreen({
- required this.options,
- required this.onPressStartChat,
- required this.onPressChat,
- required this.onDeleteChat,
- required this.service,
- required this.pageSize,
- this.onNoChats,
- this.deleteChatDialog,
- this.translations = const ChatTranslations(),
- this.disableDismissForPermanentChats = false,
- super.key,
- });
-
- final ChatOptions options;
- final ChatTranslations translations;
- final ChatService service;
- final Function()? onPressStartChat;
- final Function()? onNoChats;
- final void Function(ChatModel chat) onDeleteChat;
- final void Function(ChatModel chat) onPressChat;
- final int pageSize;
-
- /// Disable 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();
-}
-
-class _ChatScreenState extends State {
- final DateFormatter _dateFormatter = DateFormatter();
- bool _hasCalledOnNoChats = false;
- ScrollController controller = ScrollController();
- bool showIndicator = false;
- Stream>? chats;
- List deletedChats = [];
-
- @override
- void initState() {
- getChats();
- super.initState();
- }
-
- @override
- void dispose() {
- controller.dispose();
- super.dispose();
- }
-
- void getChats() {
- setState(() {
- chats = widget.service.getChatsStream(widget.pageSize);
- });
- }
-
- @override
- Widget build(BuildContext context) {
- var translations = widget.translations;
- return widget.options.scaffoldBuilder(
- AppBar(
- title: Text(translations.chatsTitle),
- centerTitle: true,
- actions: [
- StreamBuilder(
- stream: widget.service.getUnreadChatsCountStream(),
- builder: (BuildContext context, snapshot) => Align(
- alignment: Alignment.centerRight,
- child: Padding(
- padding: const EdgeInsets.only(right: 22.0),
- child: Text(
- '${snapshot.data ?? 0} ${translations.chatsUnread}',
- style: const TextStyle(
- color: Color(0xFFBBBBBB),
- fontSize: 14,
- ),
- ),
- ),
- ),
- ),
- ],
- ),
- Column(
- children: [
- Expanded(
- child: Listener(
- onPointerMove: (event) {
- var isTop = controller.position.pixels ==
- controller.position.maxScrollExtent;
-
- if (showIndicator == false &&
- !isTop &&
- controller.position.userScrollDirection ==
- ScrollDirection.reverse) {
- setState(() {
- showIndicator = true;
- });
- getChats();
- Future.delayed(const Duration(seconds: 2), () {
- if (mounted) {
- setState(() {
- showIndicator = false;
- });
- }
- });
- }
- },
- child: ListView(
- controller: controller,
- physics: const AlwaysScrollableScrollPhysics(),
- padding: const EdgeInsets.only(top: 15.0),
- children: [
- StreamBuilder>(
- stream: chats,
- builder: (BuildContext context, snapshot) {
- // if the stream is done, empty and noChats is set we should call that
- if (snapshot.connectionState == ConnectionState.done &&
- (snapshot.data?.isEmpty ?? true)) {
- if (widget.onNoChats != null && !_hasCalledOnNoChats) {
- _hasCalledOnNoChats = true; // Set the flag to true
- WidgetsBinding.instance
- .addPostFrameCallback((_) async {
- await widget.onNoChats!.call();
- getChats();
- });
- }
- } else {
- _hasCalledOnNoChats =
- false; // Reset the flag if there are chats
- }
- return Column(
- children: [
- for (ChatModel chat in (snapshot.data ?? []).where(
- (chat) => !deletedChats.contains(chat.id),
- )) ...[
- Builder(
- builder: (context) => !(widget
- .disableDismissForPermanentChats &&
- !chat.canBeDeleted)
- ? Dismissible(
- confirmDismiss: (_) async =>
- widget.deleteChatDialog
- ?.call(context, chat) ??
- showModalBottomSheet(
- context: context,
- builder: (BuildContext context) =>
- Container(
- padding:
- const EdgeInsets.all(16.0),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- children: [
- Text(
- chat.canBeDeleted
- ? translations
- .deleteChatModalTitle
- : translations
- .chatCantBeDeleted,
- style: const TextStyle(
- fontSize: 20,
- fontWeight:
- FontWeight.bold,
- ),
- ),
- const SizedBox(height: 16),
- if (chat.canBeDeleted)
- Text(
- translations
- .deleteChatModalDescription,
- style: const TextStyle(
- fontSize: 16,
- ),
- ),
- const SizedBox(height: 16),
- Row(
- mainAxisAlignment:
- MainAxisAlignment
- .center,
- children: [
- TextButton(
- child: Text(
- translations
- .deleteChatModalCancel,
- style:
- const TextStyle(
- fontSize: 16,
- ),
- ),
- onPressed: () =>
- Navigator.of(
- context,
- ).pop(false),
- ),
- if (chat.canBeDeleted)
- ElevatedButton(
- onPressed: () =>
- Navigator.of(
- context,
- ).pop(true),
- child: Text(
- translations
- .deleteChatModalConfirm,
- style:
- const TextStyle(
- fontSize: 16,
- ),
- ),
- ),
- ],
- ),
- ],
- ),
- ),
- ),
- onDismissed: (_) {
- setState(() {
- deletedChats.add(chat.id!);
- });
- widget.onDeleteChat(chat);
- },
- background: Container(
- color: Colors.red,
- child: Align(
- alignment: Alignment.centerRight,
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: Text(
- translations.deleteChatButton,
- ),
- ),
- ),
- ),
- key: ValueKey(
- chat.id.toString(),
- ),
- child: ChatListItem(
- widget: widget,
- chat: chat,
- translations: translations,
- dateFormatter: _dateFormatter,
- ),
- )
- : ChatListItem(
- widget: widget,
- chat: chat,
- translations: translations,
- dateFormatter: _dateFormatter,
- ),
- ),
- ],
- if (showIndicator &&
- snapshot.connectionState !=
- ConnectionState.done) ...[
- const SizedBox(
- height: 10,
- ),
- const CircularProgressIndicator(),
- const SizedBox(
- height: 10,
- ),
- ],
- ],
- );
- },
- ),
- ],
- ),
- ),
- ),
- if (widget.onPressStartChat != null)
- widget.options.newChatButtonBuilder(
- context,
- () async {
- await widget.onPressStartChat!.call();
- getChats();
- },
- translations,
- ),
- ],
- ),
- );
- }
-}
-
-class ChatListItem extends StatelessWidget {
- const ChatListItem({
- required this.widget,
- required this.chat,
- required this.translations,
- required DateFormatter dateFormatter,
- super.key,
- }) : _dateFormatter = dateFormatter;
-
- final ChatScreen widget;
- final ChatModel chat;
- final ChatTranslations translations;
- final DateFormatter _dateFormatter;
-
- @override
- Widget build(BuildContext context) {
- return GestureDetector(
- onTap: () => widget.onPressChat(chat),
- child: Container(
- color: Colors.transparent,
- child: widget.options.chatRowContainerBuilder(
- (chat is PersonalChatModel)
- ? ChatRow(
- unreadMessages: chat.unreadMessages ?? 0,
- avatar: widget.options.userAvatarBuilder(
- (chat as PersonalChatModel).user,
- 40.0,
- ),
- title: (chat as PersonalChatModel).user.fullName ??
- translations.anonymousUser,
- subTitle: chat.lastMessage != null
- ? chat.lastMessage is ChatTextMessageModel
- ? (chat.lastMessage! as ChatTextMessageModel).text
- : '📷 '
- '${translations.image}'
- : '',
- lastUsed: chat.lastUsed != null
- ? _dateFormatter.format(
- date: chat.lastUsed!,
- )
- : null,
- )
- : ChatRow(
- title: (chat as GroupChatModel).title,
- unreadMessages: chat.unreadMessages ?? 0,
- subTitle: chat.lastMessage != null
- ? chat.lastMessage is ChatTextMessageModel
- ? (chat.lastMessage! as ChatTextMessageModel).text
- : '📷 '
- '${translations.image}'
- : '',
- avatar: widget.options.groupAvatarBuilder(
- (chat as GroupChatModel).title,
- (chat as GroupChatModel).imageUrl,
- 40.0,
- ),
- lastUsed: chat.lastUsed != null
- ? _dateFormatter.format(
- date: chat.lastUsed!,
- )
- : null,
- ),
- ),
- ),
- );
- }
-}
diff --git a/pubspec.yaml b/pubspec.yaml
index fe778f0..ace4fbe 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
-name: flutter_community_chat_workspace
+name: flutter_chat_workspace
environment:
- sdk: '>=3.1.0 <4.0.0'
+ sdk: ">=3.1.0 <4.0.0"
dev_dependencies:
melos: ^3.0.1