feat: add unread chats system

This commit is contained in:
Freek van de Ven 2023-10-25 14:04:10 +02:00
parent 0d9e192134
commit 84934dec0c
13 changed files with 178 additions and 765 deletions

View file

@ -1,3 +1,7 @@
## 0.3.4 - October 25 2023
- Add interface methods for getting amount of unread messages
## 0.3.3 - October 10 2023
- Add icon color property for icon buttons

View file

@ -1,11 +1,15 @@
# SPDX-FileCopyrightText: 2022 Iconica
#
# SPDX-License-Identifier: GPL-3.0-or-later
name: flutter_community_chat
description: A new Flutter package project.
version: 0.3.3
version: 0.3.4
publish_to: none
environment:
sdk: '>=2.18.2 <3.0.0'
sdk: '>=3.1.0 <4.0.0'
flutter: ">=1.17.0"
dependencies:
@ -15,12 +19,12 @@ dependencies:
git:
url: https://github.com/Iconica-Development/flutter_community_chat
path: packages/flutter_community_chat_view
ref: 0.3.3
ref: 0.3.4
flutter_community_chat_interface:
git:
url: https://github.com/Iconica-Development/flutter_community_chat
path: packages/flutter_community_chat_interface
ref: 0.3.3
ref: 0.3.4
dev_dependencies:
flutter_lints: ^2.0.0

View file

@ -6,7 +6,6 @@ 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/material.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';
@ -197,7 +196,6 @@ class FirebaseChatService implements ChatService {
StreamSubscription? chatsSubscription;
controller = StreamController(
onListen: () async {
debugPrint('Start listening to chats');
var currentUser = await _userService.getCurrentUser();
var userSnapshot = await _db
.collection(_options.usersCollectionName)
@ -223,7 +221,6 @@ class FirebaseChatService implements ChatService {
},
onCancel: () {
chatsSubscription?.cancel();
debugPrint('Stop listening to chats');
},
);
return controller.stream;
@ -416,4 +413,51 @@ class FirebaseChatService implements ChatService {
return chat;
}
@override
Stream<int> getUnreadChatsCountStream() {
// open a stream to the user's chats collection and listen to changes in this collection we will also add the amount of read chats
StreamSubscription? unreadChatSubscription;
late StreamController<int> controller;
controller = StreamController(
onListen: () async {
var currentUser = await _userService.getCurrentUser();
var userSnapshot = _db
.collection(_options.usersCollectionName)
.doc(currentUser?.id)
.collection('chats')
.snapshots();
unreadChatSubscription = userSnapshot.listen((event) {
// every chat has a field called amount_unread_messages, combine all of these fields to get the total amount of unread messages
var unreadChats = event.docs
.map((chat) => chat.data()['amount_unread_messages'] ?? 0)
.toList();
var totalUnreadChats = unreadChats.fold<int>(
0, (previousValue, element) => previousValue + (element as int));
controller.add(totalUnreadChats);
});
},
onCancel: () {
unreadChatSubscription?.cancel();
},
);
return controller.stream;
}
@override
Future<void> readChat(ChatModel chat) async {
// set the amount of read chats to the amount of messages in the chat
var currentUser = await _userService.getCurrentUser();
if (currentUser?.id == null || chat.id == null) {
return;
}
// set the amount of unread messages to 0
await _db
.collection(_options.usersCollectionName)
.doc(currentUser!.id!)
.collection('chats')
.doc(chat.id)
.update({'amount_unread_messages': 0});
}
}

View file

@ -68,6 +68,28 @@ class FirebaseMessageService implements MessageService {
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
var fetchedChat = await chatReference.get();
var chatUsers = fetchedChat.data()?['users'] as List<dynamic>;
// for all users except the message sender update the unread counter
for (var userId in chatUsers) {
if (userId != currentUser.id) {
var userReference = _db
.collection(
_options.usersCollectionName,
)
.doc(userId)
.collection('chats')
.doc(chat.id);
await userReference.update({
'amount_unread_messages': FieldValue.increment(1),
});
}
}
}
@override

View file

@ -1,10 +1,14 @@
# SPDX-FileCopyrightText: 2022 Iconica
#
# SPDX-License-Identifier: GPL-3.0-or-later
name: flutter_community_chat_firebase
description: A new Flutter package project.
version: 0.3.3
version: 0.3.4
publish_to: none
environment:
sdk: '>=2.18.2 <3.0.0'
sdk: '>=3.1.0 <4.0.0'
flutter: ">=1.17.0"
dependencies:
@ -19,7 +23,7 @@ dependencies:
git:
url: https://github.com/Iconica-Development/flutter_community_chat
path: packages/flutter_community_chat_interface
ref: 0.3.3
ref: 0.3.4
dev_dependencies:
flutter_lints: ^2.0.0

View file

@ -6,5 +6,7 @@ abstract class ChatService {
Future<ChatModel> getOrCreateChatByUser(ChatUserModel user);
Future<ChatModel> getChatById(String id);
Future<void> deleteChat(ChatModel chat);
Future<void> readChat(ChatModel chat);
Future<ChatModel> storeChatIfNot(ChatModel chat);
Stream<int> getUnreadChatsCountStream();
}

View file

@ -1,10 +1,14 @@
# SPDX-FileCopyrightText: 2022 Iconica
#
# SPDX-License-Identifier: GPL-3.0-or-later
name: flutter_community_chat_interface
description: A new Flutter package project.
version: 0.3.3
version: 0.3.4
publish_to: none
environment:
sdk: '>=2.18.2 <3.0.0'
sdk: ">=3.1.0 <4.0.0"
flutter: ">=1.17.0"
dependencies:
@ -12,7 +16,7 @@ dependencies:
sdk: flutter
flutter_data_interface:
git:
url: https://github.com/Iconica-Development/flutter_data_interface
url: https://github.com/Iconica-Development/flutter_data_interface.git
ref: 1.0.0
dev_dependencies:

View file

@ -19,6 +19,7 @@ class MyStatefulWidget extends StatefulWidget {
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
static final pietUser = ChatUserModel(
id: 'piet',
firstName: 'Piet',
lastName: 'Jansen',
imageUrl: 'https://xsgames.co/randomusers/avatar.php?g=female',
@ -37,11 +38,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
timestamp: DateTime.now(),
),
ChatTextMessageModel(
sender: ChatUserModel(
firstName: 'Jan',
lastName: 'Jansen',
imageUrl: 'https://xsgames.co/randomusers/avatar.php?g=male',
),
sender: janUser,
text: 'Met mij gaat het goed, dankje!',
timestamp: DateTime.now().subtract(const Duration(days: 2)),
)
@ -109,6 +106,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
onPressChat: (chat) => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ChatDetailScreen(
userId: 'piet',
chat: chat,
chatMessages: messageStream,
options: options,
@ -120,6 +118,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
() => debugPrint('onMessageSubmit'),
);
},
onReadChat: (chat) async {},
onUploadImage: (image) async {},
),
),

View file

@ -1,716 +0,0 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
url: "https://pub.dev"
source: hosted
version: "61.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
url: "https://pub.dev"
source: hosted
version: "5.13.0"
args:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev"
source: hosted
version: "2.4.2"
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.dev"
source: hosted
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
build:
dependency: transitive
description:
name: build
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
built_collection:
dependency: transitive
description:
name: built_collection
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
url: "https://pub.dev"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74
url: "https://pub.dev"
source: hosted
version: "8.6.3"
cached_network_image:
dependency: transitive
description:
name: cached_network_image
sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f
url: "https://pub.dev"
source: hosted
version: "3.3.0"
cached_network_image_platform_interface:
dependency: transitive
description:
name: cached_network_image_platform_interface
sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
cached_network_image_web:
dependency: transitive
description:
name: cached_network_image_web
sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
characters:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.dev"
source: hosted
version: "1.1.1"
code_builder:
dependency: transitive
description:
name: code_builder
sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677"
url: "https://pub.dev"
source: hosted
version: "4.7.0"
collection:
dependency: transitive
description:
name: collection
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
url: "https://pub.dev"
source: hosted
version: "1.17.2"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
cross_file:
dependency: transitive
description:
name: cross_file
sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb
url: "https://pub.dev"
source: hosted
version: "0.3.3+5"
crypto:
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
source: hosted
version: "3.0.3"
dart_style:
dependency: transitive
description:
name: dart_style
sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
ffi:
dependency: transitive
description:
name: ffi
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
file:
dependency: transitive
description:
name: file
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
file_selector_linux:
dependency: transitive
description:
name: file_selector_linux
sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492"
url: "https://pub.dev"
source: hosted
version: "0.9.2+1"
file_selector_macos:
dependency: transitive
description:
name: file_selector_macos
sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6
url: "https://pub.dev"
source: hosted
version: "0.9.3+3"
file_selector_platform_interface:
dependency: transitive
description:
name: file_selector_platform_interface
sha256: "0aa47a725c346825a2bd396343ce63ac00bda6eff2fbc43eabe99737dede8262"
url: "https://pub.dev"
source: hosted
version: "2.6.1"
file_selector_windows:
dependency: transitive
description:
name: file_selector_windows
sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0
url: "https://pub.dev"
source: hosted
version: "0.9.3+1"
fixnum:
dependency: transitive
description:
name: fixnum
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_cache_manager:
dependency: transitive
description:
name: flutter_cache_manager
sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba"
url: "https://pub.dev"
source: hosted
version: "3.3.1"
flutter_community_chat_interface:
dependency: transitive
description:
path: "packages/flutter_community_chat_interface"
ref: "0.3.3"
resolved-ref: "2e79910e7767a89b1ae9232aec2c5f3bc99f8027"
url: "https://github.com/Iconica-Development/flutter_community_chat"
source: git
version: "0.3.3"
flutter_community_chat_view:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "0.3.3"
flutter_data_interface:
dependency: transitive
description:
path: "."
ref: "1.0.0"
resolved-ref: "500ed1d08095b33387ae3aa4ed1a2ad4d2fb2ac3"
url: "https://github.com/Iconica-Development/flutter_data_interface.git"
source: git
version: "1.0.0"
flutter_image_picker:
dependency: transitive
description:
path: "."
ref: "1.0.4"
resolved-ref: "829574e5f650cabcbd157f22b95001c9052fce0d"
url: "https://github.com/Iconica-Development/flutter_image_picker"
source: git
version: "1.0.4"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
url: "https://pub.dev"
source: hosted
version: "2.0.3"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c
url: "https://pub.dev"
source: hosted
version: "2.0.16"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
glob:
dependency: transitive
description:
name: glob
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
http:
dependency: transitive
description:
name: http
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev"
source: hosted
version: "4.0.2"
image_picker:
dependency: transitive
description:
name: image_picker
sha256: b6951e25b795d053a6ba03af5f710069c99349de9341af95155d52665cb4607c
url: "https://pub.dev"
source: hosted
version: "0.8.9"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: "0c7b83bbe2980c8a8e36e974f055e11e51675784e13a4762889feed0f3937ff2"
url: "https://pub.dev"
source: hosted
version: "0.8.8+1"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: c5538cacefacac733c724be7484377923b476216ad1ead35a0d2eadcdc0fc497
url: "https://pub.dev"
source: hosted
version: "0.8.8+2"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa"
url: "https://pub.dev"
source: hosted
version: "0.2.1+1"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62"
url: "https://pub.dev"
source: hosted
version: "0.2.1+1"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: ed9b00e63977c93b0d2d2b343685bed9c324534ba5abafbb3dfbd6a780b1b514
url: "https://pub.dev"
source: hosted
version: "2.9.1"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
url: "https://pub.dev"
source: hosted
version: "0.2.1+1"
intl:
dependency: transitive
description:
name: intl
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev"
source: hosted
version: "0.18.1"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
lints:
dependency: transitive
description:
name: lints
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
logging:
dependency: transitive
description:
name: logging
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
matcher:
dependency: transitive
description:
name: matcher
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
version: "0.12.16"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
meta:
dependency: transitive
description:
name: meta
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
mime:
dependency: transitive
description:
name: mime
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
url: "https://pub.dev"
source: hosted
version: "1.0.4"
mockito:
dependency: transitive
description:
name: mockito
sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616"
url: "https://pub.dev"
source: hosted
version: "5.4.2"
octo_image:
dependency: transitive
description:
name: octo_image
sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
path:
dependency: transitive
description:
name: path
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
url: "https://pub.dev"
source: hosted
version: "1.8.3"
path_provider:
dependency: transitive
description:
name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
platform:
dependency: transitive
description:
name: platform
sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
url: "https://pub.dev"
source: hosted
version: "3.1.3"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
url: "https://pub.dev"
source: hosted
version: "2.1.6"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
rxdart:
dependency: transitive
description:
name: rxdart
sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb"
url: "https://pub.dev"
source: hosted
version: "0.27.7"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16
url: "https://pub.dev"
source: hosted
version: "1.4.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
sprintf:
dependency: transitive
description:
name: sprintf
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
sqflite:
dependency: transitive
description:
name: sqflite
sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a"
url: "https://pub.dev"
source: hosted
version: "2.3.0"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a"
url: "https://pub.dev"
source: hosted
version: "2.5.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
url: "https://pub.dev"
source: hosted
version: "1.11.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.dev"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
url: "https://pub.dev"
source: hosted
version: "0.6.0"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
url: "https://pub.dev"
source: hosted
version: "1.3.2"
uuid:
dependency: transitive
description:
name: uuid
sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7
url: "https://pub.dev"
source: hosted
version: "4.1.0"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
watcher:
dependency: transitive
description:
name: watcher
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
win32:
dependency: transitive
description:
name: win32
sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
url: "https://pub.dev"
source: hosted
version: "5.0.9"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
url: "https://pub.dev"
source: hosted
version: "1.0.3"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.1.0-185.0.dev <4.0.0"
flutter: ">=3.10.0"

View file

@ -10,7 +10,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: '>=2.18.2 <3.0.0'
sdk: '>=3.1.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
@ -18,7 +18,7 @@ dependencies:
git:
url: https://github.com/Iconica-Development/flutter_community_chat
path: packages/flutter_community_chat_view
ref: 0.3.3
ref: 0.3.4
dev_dependencies:
flutter_test:

View file

@ -2,6 +2,7 @@
//
// SPDX-License-Identifier: BSD-3-Clause
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
@ -10,11 +11,13 @@ 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';
class ChatDetailScreen extends StatelessWidget {
class ChatDetailScreen extends StatefulWidget {
const ChatDetailScreen({
required this.userId,
required this.options,
required this.onMessageSubmit,
required this.onUploadImage,
required this.onReadChat,
this.translations = const ChatTranslations(),
this.chat,
this.chatMessages,
@ -24,34 +27,76 @@ class ChatDetailScreen extends StatelessWidget {
});
final ChatModel? chat;
/// The id of the current user that is viewing the chat.
final String userId;
final ChatOptions options;
final ChatTranslations translations;
final Stream<List<ChatMessageModel>>? chatMessages;
final Future<void> Function(Uint8List image) onUploadImage;
final Future<void> Function(String text) onMessageSubmit;
// called at the start of the screen to set the chat to read
// or when a new message is received
final Future<void> Function(ChatModel chat) onReadChat;
final VoidCallback? onPressChatTitle;
/// The color of the icon buttons in the chat bottom.
final Color? iconColor;
@override
State<ChatDetailScreen> createState() => _ChatDetailScreenState();
}
class _ChatDetailScreenState extends State<ChatDetailScreen> {
// stream listener that needs to be disposed later
late StreamSubscription<List<ChatMessageModel>>? _chatMessagesSubscription;
late Stream<List<ChatMessageModel>>? _chatMessages;
@override
void initState() {
super.initState();
// create a broadcast stream from the chat messages
_chatMessages = widget.chatMessages?.asBroadcastStream();
_chatMessagesSubscription = _chatMessages?.listen((event) {
// check if the last message is from the current user
// if so, set the chat to read
if (event.isNotEmpty &&
event.last.sender.id != widget.userId &&
widget.chat != null) {
widget.onReadChat(widget.chat!);
}
});
// set the chat to read when opening the screen
if (widget.chat != null) {
widget.onReadChat(widget.chat!);
}
}
@override
void dispose() {
_chatMessagesSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
Future<void> onPressSelectImage() => showModalBottomSheet<Uint8List?>(
context: context,
builder: (BuildContext context) =>
options.imagePickerContainerBuilder(
widget.options.imagePickerContainerBuilder(
() => Navigator.of(context).pop(),
translations,
widget.translations,
),
).then(
(image) async {
var messenger = ScaffoldMessenger.of(context)
..showSnackBar(
getImageLoadingSnackbar(translations),
getImageLoadingSnackbar(widget.translations),
);
if (image != null) {
await onUploadImage(image);
await widget.onUploadImage(image);
}
messenger.hideCurrentSnackBar();
@ -62,20 +107,20 @@ class ChatDetailScreen extends StatelessWidget {
appBar: AppBar(
centerTitle: true,
title: GestureDetector(
onTap: onPressChatTitle,
onTap: widget.onPressChatTitle,
child: Row(
mainAxisSize: MainAxisSize.min,
children: chat == null
children: widget.chat == null
? []
: [
if (chat is GroupChatModel) ...[
options.groupAvatarBuilder(
(chat! as GroupChatModel).imageUrl,
if (widget.chat is GroupChatModel) ...[
widget.options.groupAvatarBuilder(
(widget.chat! as GroupChatModel).imageUrl,
36.0,
),
] else if (chat is PersonalChatModel) ...[
options.userAvatarBuilder(
(chat! as PersonalChatModel).user,
] else if (widget.chat is PersonalChatModel) ...[
widget.options.userAvatarBuilder(
(widget.chat! as PersonalChatModel).user,
36.0,
),
] else
@ -84,10 +129,10 @@ class ChatDetailScreen extends StatelessWidget {
child: Padding(
padding: const EdgeInsets.only(left: 15.5),
child: Text(
(chat is GroupChatModel)
? (chat! as GroupChatModel).title
: (chat is PersonalChatModel)
? (chat! as PersonalChatModel)
(widget.chat is GroupChatModel)
? (widget.chat! as GroupChatModel).title
: (widget.chat is PersonalChatModel)
? (widget.chat! as PersonalChatModel)
.user
.fullName ??
''
@ -104,13 +149,14 @@ class ChatDetailScreen extends StatelessWidget {
children: [
Expanded(
child: StreamBuilder<List<ChatMessageModel>>(
stream: chatMessages,
stream: _chatMessages,
builder: (BuildContext context, snapshot) => ListView(
reverse: true,
padding: const EdgeInsets.only(top: 24.0),
children: [
for (var message
in (snapshot.data ?? chat?.messages ?? []).reversed)
in (snapshot.data ?? widget.chat?.messages ?? [])
.reversed)
ChatDetailRow(
message: message,
),
@ -118,14 +164,14 @@ class ChatDetailScreen extends StatelessWidget {
),
),
),
if (chat != null)
if (widget.chat != null)
ChatBottom(
chat: chat!,
messageInputBuilder: options.messageInputBuilder,
chat: widget.chat!,
messageInputBuilder: widget.options.messageInputBuilder,
onPressSelectImage: onPressSelectImage,
onMessageSubmit: onMessageSubmit,
translations: translations,
iconColor: iconColor,
onMessageSubmit: widget.onMessageSubmit,
translations: widget.translations,
iconColor: widget.iconColor,
),
],
),

View file

@ -4,12 +4,12 @@
name: flutter_community_chat_view
description: A standard flutter package.
version: 0.3.3
version: 0.3.4
publish_to: none
environment:
sdk: '>=2.18.2 <3.0.0'
sdk: '>=3.1.0 <4.0.0'
flutter: ">=1.17.0"
dependencies:
@ -20,7 +20,7 @@ dependencies:
git:
url: https://github.com/Iconica-Development/flutter_community_chat
path: packages/flutter_community_chat_interface
ref: 0.3.3
ref: 0.3.4
cached_network_image: ^3.2.2
flutter_image_picker:
git:

View file

@ -1,6 +1,6 @@
name: flutter_community_chat_workspace
environment:
sdk: '>=2.18.0 <3.0.0'
sdk: '>=3.1.0 <4.0.0'
dev_dependencies:
melos: ^3.0.1