This commit is contained in:
otsmr 2025-02-10 23:28:36 +01:00
parent ea7b29f594
commit a121aa6f23
3 changed files with 55 additions and 68 deletions

View file

@ -158,12 +158,12 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
} }
Future _stopService() async { Future _stopService() async {
FlutterForegroundTask.sendDataToTask("");
await FlutterForegroundTask.stopService();
if (context.mounted) { if (context.mounted) {
context.read<MessagesChangeProvider>().init(); context.read<MessagesChangeProvider>().init(afterPaused: true);
context.read<ContactChangeProvider>().update(); context.read<ContactChangeProvider>().update();
} }
FlutterForegroundTask.sendDataToTask("");
await FlutterForegroundTask.stopService();
if (!apiProvider.isAuthenticated) { if (!apiProvider.isAuthenticated) {
apiProvider.connect(); apiProvider.connect();
} }

View file

@ -7,10 +7,13 @@ import 'package:twonly/src/utils/misc.dart';
/// for every contact. /// for every contact.
class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin { class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin {
final Map<int, DbMessage> _lastMessage = <int, DbMessage>{}; final Map<int, DbMessage> _lastMessage = <int, DbMessage>{};
final Map<int, List<DbMessage>> _allMessagesFromUser =
<int, List<DbMessage>>{};
final Map<int, int> _changeCounter = <int, int>{}; final Map<int, int> _changeCounter = <int, int>{};
final Map<int, int> _flamesCounter = <int, int>{}; final Map<int, int> _flamesCounter = <int, int>{};
Map<int, DbMessage> get lastMessage => _lastMessage; Map<int, DbMessage> get lastMessage => _lastMessage;
Map<int, List<DbMessage>> get allMessagesFromUser => _allMessagesFromUser;
Map<int, int> get changeCounter => _changeCounter; Map<int, int> get changeCounter => _changeCounter;
Map<int, int> get flamesCounter => _flamesCounter; Map<int, int> get flamesCounter => _flamesCounter;
@ -20,15 +23,20 @@ class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin {
if (last != null) { if (last != null) {
_lastMessage[last.otherUserId] = last; _lastMessage[last.otherUserId] = last;
} }
if (!changeCounter.containsKey(targetUserId)) {
changeCounter[targetUserId] = 0;
}
changeCounter[targetUserId] = changeCounter[targetUserId]! + 1;
flamesCounter[targetUserId] = await getFlamesForOtherUser(targetUserId); flamesCounter[targetUserId] = await getFlamesForOtherUser(targetUserId);
notifyListeners(); notifyListeners();
loadMessagesForUser(targetUserId, force: true);
}
Future loadMessagesForUser(int targetUserId, {bool force = false}) async {
if (!force && _allMessagesFromUser[targetUserId] != null) return;
_allMessagesFromUser[targetUserId] =
await DbMessages.getAllMessagesForUser(targetUserId);
notifyListeners();
} }
void init() async { void init({bool afterPaused = false}) async {
// load everything from the database // load everything from the database
List<Contact> allContacts = await DbContacts.getUsers(); List<Contact> allContacts = await DbContacts.getUsers();
for (Contact contact in allContacts) { for (Contact contact in allContacts) {
@ -41,5 +49,10 @@ class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin {
await getFlamesForOtherUser(contact.userId.toInt()); await getFlamesForOtherUser(contact.userId.toInt());
} }
notifyListeners(); notifyListeners();
if (afterPaused) {
for (int targetUserId in _allMessagesFromUser.keys) {
loadMessagesForUser(targetUserId, force: true);
}
}
} }
} }

View file

@ -129,64 +129,25 @@ class ChatItemDetailsView extends StatefulWidget {
} }
class _ChatItemDetailsViewState extends State<ChatItemDetailsView> { class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
List<DbMessage> _messages = [];
int lastChangeCounter = 0; int lastChangeCounter = 0;
final TextEditingController newMessageController = TextEditingController(); final TextEditingController newMessageController = TextEditingController();
HashSet<int> alreadyReportedOpened = HashSet<int>(); HashSet<int> alreadyReportedOpened = HashSet<int>();
int sendTextMessages = 0;
late Contact user; late Contact user;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
user = widget.user; user = widget.user;
_loadAsync(updateOpenStatus: true); context
} .read<MessagesChangeProvider>()
.loadMessagesForUser(user.userId.toInt());
Future _loadAsync({bool updateOpenStatus = false}) async {
// if (_messages.isEmpty || updateOpenStatus) {
if (sendTextMessages <= 0) {
_messages = await DbMessages.getAllMessagesForUser(user.userId.toInt());
} else {
sendTextMessages--;
// will not update older message states like when they now downloaded...
int lastMessageId = _messages.first.messageId;
List<DbMessage> toAppend =
await DbMessages.getAllMessagesForUserWithHigherMessageId(
user.userId.toInt(), lastMessageId);
_messages.insertAll(0, toAppend);
}
if (updateOpenStatus) {
_messages.where((x) => x.messageOpenedAt == null).forEach((message) {
if (message.messageOtherId != null &&
message.messageContent is TextMessageContent) {
if (!alreadyReportedOpened.contains(message.messageOtherId!)) {
userOpenedOtherMessage(
message.otherUserId, message.messageOtherId!);
flutterLocalNotificationsPlugin.cancel(message.messageId);
alreadyReportedOpened.add(message.messageOtherId!);
}
}
});
}
try {
if (context.mounted) {
setState(() {});
}
} catch (e) {
// state should be disposed
return;
}
} }
Future _sendMessage() async { Future _sendMessage() async {
sendTextMessages++; if (newMessageController.text == "") return;
String text = newMessageController.text; setState(() {});
if (text == "") return;
await sendTextMessage(user.userId, newMessageController.text); await sendTextMessage(user.userId, newMessageController.text);
newMessageController.clear(); newMessageController.clear();
setState(() {});
} }
@override @override
@ -195,14 +156,27 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
.watch<ContactChangeProvider>() .watch<ContactChangeProvider>()
.allContacts .allContacts
.firstWhere((c) => c.userId == widget.user.userId); .firstWhere((c) => c.userId == widget.user.userId);
final changeCounter = context.watch<MessagesChangeProvider>().changeCounter;
if (changeCounter.containsKey(user.userId.toInt())) { List<DbMessage> messages = context
if (changeCounter[user.userId.toInt()] != lastChangeCounter) { .watch<MessagesChangeProvider>()
_loadAsync(updateOpenStatus: true); .allMessagesFromUser[user.userId.toInt()] ??
lastChangeCounter = changeCounter[user.userId.toInt()]!; [];
setState(() {});
messages.where((x) => x.messageOpenedAt == null).forEach((message) {
if (message.messageOtherId != null &&
message.messageContent is TextMessageContent) {
if (!alreadyReportedOpened.contains(message.messageOtherId!)) {
setState(() {
// so the _loadAsync will not be called again by this update
lastChangeCounter++;
});
userOpenedOtherMessage(message.otherUserId, message.messageOtherId!);
flutterLocalNotificationsPlugin.cancel(message.messageId);
alreadyReportedOpened.add(message.messageOtherId!);
}
} }
} });
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: GestureDetector( title: GestureDetector(
@ -223,7 +197,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
color: Colors.transparent, color: Colors.transparent,
child: Row( child: Row(
children: [ children: [
Text(user.displayName), Text(user.userId.toString()),
SizedBox(width: 10), SizedBox(width: 10),
VerifiedShield(user), VerifiedShield(user),
], ],
@ -238,27 +212,27 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
children: [ children: [
Expanded( Expanded(
child: ListView.builder( child: ListView.builder(
itemCount: _messages.length, // Number of items in the list itemCount: messages.length, // Number of items in the list
reverse: true, reverse: true,
itemBuilder: (context, i) { itemBuilder: (context, i) {
bool lastMessageFromSameUser = false; bool lastMessageFromSameUser = false;
if (i > 0) { if (i > 0) {
lastMessageFromSameUser = lastMessageFromSameUser =
(_messages[i - 1].messageOtherId == null && (messages[i - 1].messageOtherId == null &&
_messages[i].messageOtherId == null) || messages[i].messageOtherId == null) ||
(_messages[i - 1].messageOtherId != null && (messages[i - 1].messageOtherId != null &&
_messages[i].messageOtherId != null); messages[i].messageOtherId != null);
} }
if (_messages[i].messageOpenedAt != null) { if (messages[i].messageOpenedAt != null) {
if ((DateTime.now()) if ((DateTime.now())
.difference(_messages[i].messageOpenedAt!) .difference(messages[i].messageOpenedAt!)
.inHours >= .inHours >=
24) { 24) {
return Container(); return Container();
} }
} }
return ChatListEntry( return ChatListEntry(
_messages[i], messages[i],
user, user,
lastMessageFromSameUser, lastMessageFromSameUser,
); );