feat: updated readme, ui colors and null values

This commit is contained in:
mike doornenbal 2023-12-29 12:02:54 +01:00
parent ac163a28f8
commit cb423c582c
6 changed files with 154 additions and 75 deletions

102
README.md
View file

@ -1,4 +1,5 @@
# Flutter Community Chat # Flutter Community 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 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 Community Chat GIF](example.gif) ![Flutter Community Chat GIF](example.gif)
@ -7,11 +8,12 @@ Figma Design that defines this component (only accessible for Iconica developers
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 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 ## Setup
To use this package, add flutter_community_chat as a dependency in your pubspec.yaml file: To use this package, add flutter_community_chat as a dependency in your pubspec.yaml file:
``` ```
flutter_community_chat: flutter_community_chat:
git: git:
url: https://github.com/Iconica-Development/flutter_community_chat.git url: https://github.com/Iconica-Development/flutter_community_chat.git
path: packages/flutter_community_chat path: packages/flutter_community_chat
``` ```
@ -20,43 +22,102 @@ If you are going to use Firebase as the back-end of the Community Chat, you shou
``` ```
flutter_community_chat_firebase: flutter_community_chat_firebase:
git: git:
url: https://github.com/Iconica-Development/flutter_community_chat.git url: https://github.com/Iconica-Development/flutter_community_chat.git
path: packages/flutter_community_chat_firebase path: packages/flutter_community_chat_firebase
``` ```
Create a Firebase project for your application and add firebase firestore and storage.
## How to use ## How to use
To use the module within your Flutter-application you should add the following code to the build-method of a chosen widget.
To use the module within your Flutter-application with predefined `Go_router` routes you should add the following:
Add go_router as dependency to your project.
Add the following configuration to your flutter_application:
``` ```
CommunityChat( List<GoRoute> getCommunityChatRoutes() => getCommunityChatStoryRoutes(
dataProvider: FirebaseCommunityChatDataProvider(), CommunityChatUserStoryConfiguration(
) service: FirebaseChatService(userService: FirebaseUserService()),
userService: FirebaseUserService(),
messageService:
FirebaseMessageService(userService: FirebaseUserService()),
chatOptionsBuilder: (ctx) => const ChatOptions(),
),
);
``` ```
In this example we provide a `FirebaseCommunityChatDataProvider` as a data provider. You can also specify your own implementation here of the `CommunityChatInterface` interface. Add the `getCommunityChatRoutes()` to your go_router routes like so:
You can also include your custom configuration for both the Community Chat itself as the Image Picker which is included in this package. You can specify those configurations as a parameter:
``` ```
CommunityChat( final GoRouter _router = GoRouter(
dataProvider: FirebaseCommunityChatDataProvider(), routes: <RouteBase>[
imagePickerTheme: ImagePickerTheme(), GoRoute(
chatOptions: ChatOptions(), path: '/',
) builder: (BuildContext context, GoRouterState state) {
return const MyHomePage(
title: "home",
);
},
),
...getCommunityChatRoutes()
],
);
```
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:
To add the `ChatScreen` add the following code:
````
ChatScreen(
options: options,
onPressStartChat: onPressStartChat,
onPressChat: onPressChat,
onDeleteChat: onDeleteChat,
service: service,
pageSize: pageSize,
);
```
To add the `ChatDetailScreen` add the following code:
```
ChatDetailScreen(
options: options,
onMessageSubmit: onMessageSubmit,
onUploadImage: onUploadImage,
onReadChat: onReadChat,
service: service,
chatUserService: chatUserService,
messageService: messageService,
pageSize: pageSize,
);
```
To add the `NewChatScreen` add the following code:
```
NewChatScreen(
options: options,
onPressCreateChat: onPressCreateChat,
service: service,
userService: userService,
);
``` ```
The `ChatOptions` has its own parameters, as specified below: The `ChatOptions` has its own parameters, as specified below:
| Parameter | Explanation | | Parameter | Explanation |
|-----------|-------------| |-----------|-------------|
| newChatButtonBuilder | Builds the 'New Chat' button, to initiate a new chat session. This button is displayed on the chat overview. | | newChatButtonBuilder | Builds the 'New Chat' button, to initiate a new chat session. This button is displayed on the chat overview. |
| messageInputBuilder | Builds the text input which is displayed within the chat view, responsible for sending text messages. | | messageInputBuilder | Builds the text input which is displayed within the chat view, responsible for sending text messages. |
| chatRowContainerBuilder | Builds a chat row. A row with the users' avatar, name and eventually the last massage sended in the chat. This builder is used both in the *chat overview screen* as in the *new chat screen*. | | chatRowContainerBuilder | Builds a chat row. A row with the users' avatar, name and eventually the last massage sended in the chat. This builder is used both in the _chat overview screen_ as in the _new chat screen_. |
| imagePickerContainerBuilder | Builds the container around the ImagePicker. | | imagePickerContainerBuilder | Builds the container around the ImagePicker. |
| closeImagePickerButtonBuilder | Builds the close button for the Image Picker pop-up window. | | closeImagePickerButtonBuilder | Builds the close button for the Image Picker pop-up window. |
| scaffoldBuilder | Builds the default Scaffold-widget around the Community Chat. The chat title is displayed within the Scaffolds' title for example. | | scaffoldBuilder | Builds the default Scaffold-widget around the Community Chat. The chat title is displayed within the Scaffolds' title for example. |
The `ImagePickerTheme` also has its own parameters, how to use these parameters can be found in [the documentation of the flutter_image_picker package](https://github.com/Iconica-Development/flutter_image_picker). The `ImagePickerTheme` also has its own parameters, how to use these parameters can be found in [the documentation of the flutter_image_picker package](https://github.com/Iconica-Development/flutter_image_picker).
## Issues ## Issues
@ -69,3 +130,4 @@ If you would like to contribute to the plugin (e.g. by improving the documentati
## Author ## Author
This `flutter_community_chat` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl> This `flutter_community_chat` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl>
````

View file

@ -267,13 +267,16 @@ class FirebaseChatService implements ChatService {
var startIndex = (pageNumber - 1) * pageSize; var startIndex = (pageNumber - 1) * pageSize;
var endIndex = startIndex + pageSize; var endIndex = startIndex + pageSize;
if (startIndex >= groupChatIds.length) { if (groupChatIds != null) {
return []; if (startIndex >= groupChatIds.length) {
return [];
}
var groupIds = groupChatIds.sublist(
startIndex, endIndex.clamp(0, groupChatIds.length));
lastGroupId = groupIds.last;
return groupIds;
} }
var groupIds = groupChatIds.sublist( return [];
startIndex, endIndex.clamp(0, groupChatIds.length));
lastGroupId = groupIds.last;
return groupIds;
}); });
if (userSnapshot.docs.isNotEmpty) { if (userSnapshot.docs.isNotEmpty) {

View file

@ -37,7 +37,6 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
widget.message.timestamp.day != widget.previousMessage?.timestamp.day; widget.message.timestamp.day != widget.previousMessage?.timestamp.day;
var isSameSender = widget.previousMessage == null || var isSameSender = widget.previousMessage == null ||
widget.previousMessage?.sender.id != widget.message.sender.id; widget.previousMessage?.sender.id != widget.message.sender.id;
print(isNewDate);
return Padding( return Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
@ -79,9 +78,13 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
Text( Text(
widget.message.sender.fullName?.toUpperCase() ?? widget.message.sender.fullName?.toUpperCase() ??
widget.translations.anonymousUser, widget.translations.anonymousUser,
style: const TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Theme.of(context)
.textTheme
.labelMedium
?.color,
), ),
), ),
Padding( Padding(
@ -106,7 +109,13 @@ class _ChatDetailRowState extends State<ChatDetailRow> {
text: TextSpan( text: TextSpan(
text: (widget.message as ChatTextMessageModel) text: (widget.message as ChatTextMessageModel)
.text, .text,
style: const TextStyle(fontSize: 16), style: TextStyle(
fontSize: 16,
color: Theme.of(context)
.textTheme
.labelMedium
?.color,
),
children: <TextSpan>[ children: <TextSpan>[
if (widget.showTime) if (widget.showTime)
TextSpan( TextSpan(

View file

@ -24,9 +24,11 @@ class ChatImage extends StatelessWidget {
), ),
width: size, width: size,
height: size, height: size,
child: CachedNetworkImage( child: image != ''
imageUrl: image, ? CachedNetworkImage(
fit: BoxFit.cover, imageUrl: image,
), fit: BoxFit.cover,
)
: null,
); );
} }

View file

@ -75,7 +75,7 @@ Widget _createImagePickerContainer(
) => ) =>
Container( Container(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
color: Colors.black, color: Colors.white,
child: ImagePicker( child: ImagePicker(
customButton: ElevatedButton( customButton: ElevatedButton(
onPressed: onClose, onPressed: onClose,

View file

@ -316,48 +316,51 @@ class ChatListItem extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
onTap: () => widget.onPressChat(chat), onTap: () => widget.onPressChat(chat),
child: widget.options.chatRowContainerBuilder( child: Container(
(chat is PersonalChatModel) color: Colors.transparent,
? ChatRow( child: widget.options.chatRowContainerBuilder(
unreadMessages: chat.unreadMessages ?? 0, (chat is PersonalChatModel)
avatar: widget.options.userAvatarBuilder( ? ChatRow(
(chat as PersonalChatModel).user, unreadMessages: chat.unreadMessages ?? 0,
40.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,
), ),
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,
),
), ),
); );
} }