From 2dfab0e76ffa6e5802197d0776b503ebfa75e8b0 Mon Sep 17 00:00:00 2001 From: otsmr Date: Sat, 1 Feb 2025 00:31:42 +0100 Subject: [PATCH] flame support --- lib/src/model/contacts_model.dart | 67 +++++++++++++++++++++- lib/src/model/messages_model.dart | 18 +++--- lib/src/providers/api/api.dart | 2 + lib/src/providers/api/server_messages.dart | 2 + lib/src/views/chat_list_view.dart | 12 ++-- 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/lib/src/model/contacts_model.dart b/lib/src/model/contacts_model.dart index 1e3be56..c9e7ce2 100644 --- a/lib/src/model/contacts_model.dart +++ b/lib/src/model/contacts_model.dart @@ -9,11 +9,15 @@ class Contact { {required this.userId, required this.displayName, required this.accepted, + required this.flameCounter, + required this.lastUpdateOfFlameCounter, required this.requested}); final Int64 userId; final String displayName; final bool accepted; final bool requested; + final int flameCounter; + final DateTime lastUpdateOfFlameCounter; } class DbContacts extends CvModelBase { @@ -34,6 +38,13 @@ class DbContacts extends CvModelBase { static const columnBlocked = "blocked"; final blocked = CvField(columnBlocked); + static const columnFlameCounter = "flame_counter"; + final flameCounter = CvField(columnFlameCounter); + + static const columnLastUpdateOfFlameCounter = "last_update_flame_counter"; + final lastUpdateOfFlameCounter = + CvField(columnLastUpdateOfFlameCounter); + static const columnCreatedAt = "created_at"; final createdAt = CvField(columnCreatedAt); @@ -45,6 +56,8 @@ class DbContacts extends CvModelBase { $columnAccepted INT NOT NULL DEFAULT 0, $columnRequested INT NOT NULL DEFAULT 0, $columnBlocked INT NOT NULL DEFAULT 0, + $columnFlameCounter INT NOT NULL DEFAULT 0, + $columnLastUpdateOfFlameCounter DATETIME DEFAULT CURRENT_TIMESTAMP, $columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ) """; @@ -58,6 +71,42 @@ class DbContacts extends CvModelBase { return (await getUsers()).where((u) => u.accepted).toList(); } + static Future checkAndUpdateFlames(int userId) async { + List> result = await dbProvider.db!.query( + tableName, + columns: [columnLastUpdateOfFlameCounter, columnFlameCounter], + where: '$columnUserId = ?', + whereArgs: [userId], + ); + + if (result.isNotEmpty) { + String lastUpdateString = result.first[columnLastUpdateOfFlameCounter]; + DateTime? lastUpdate = DateTime.tryParse(lastUpdateString); + + int currentCount = result.first.cast()[columnFlameCounter]; + if (lastUpdate != null && + lastUpdate.isAfter(DateTime.now().subtract(Duration(hours: 24)))) { + _updateFlameCounter(userId, currentCount); // just update the time + } else { + _updateFlameCounter(userId, (currentCount + 1)); + } + } + globalCallBackOnContactChange(); + } + + static Future _updateFlameCounter(int userId, int newCount) async { + Map valuesToUpdate = { + columnFlameCounter: newCount, + columnLastUpdateOfFlameCounter: DateTime.now().toIso8601String() + }; + await dbProvider.db!.update( + tableName, + valuesToUpdate, + where: "$columnUserId = ?", + whereArgs: [userId], + ); + } + static Future> getUsers() async { try { var users = await dbProvider.db!.query(tableName, @@ -66,6 +115,8 @@ class DbContacts extends CvModelBase { columnDisplayName, columnAccepted, columnRequested, + columnFlameCounter, + columnLastUpdateOfFlameCounter, columnCreatedAt ], where: "$columnBlocked = 0"); @@ -73,11 +124,25 @@ class DbContacts extends CvModelBase { List parsedUsers = []; for (int i = 0; i < users.length; i++) { + DateTime lastUpdate = + DateTime.tryParse(users.cast()[i][columnLastUpdateOfFlameCounter])!; + + int userId = users.cast()[i][columnUserId]; + + int flameCounter = users.cast()[i][columnFlameCounter]; + + if (lastUpdate.isBefore(DateTime.now().subtract(Duration(days: 2)))) { + _updateFlameCounter(userId, 0); + flameCounter = 0; + } + parsedUsers.add( Contact( - userId: Int64(users.cast()[i][columnUserId]), + userId: Int64(userId), displayName: users.cast()[i][columnDisplayName], accepted: users[i][columnAccepted] == 1, + flameCounter: flameCounter, + lastUpdateOfFlameCounter: lastUpdate, requested: users[i][columnRequested] == 1, ), ); diff --git a/lib/src/model/messages_model.dart b/lib/src/model/messages_model.dart index a66f10a..a56c10b 100644 --- a/lib/src/model/messages_model.dart +++ b/lib/src/model/messages_model.dart @@ -197,15 +197,6 @@ class DbMessages extends CvModelBase { return messages; } - static Future> getAllMessagesForRetransmitting() async { - var rows = await dbProvider.db!.query( - tableName, - where: "$columnMessageAcknowledgeByServer = 0", - ); - List messages = await convertToDbMessage(rows); - return messages; - } - static Future> getAllMessagesForUser(int otherUserId) async { var rows = await dbProvider.db!.query( tableName, @@ -219,6 +210,15 @@ class DbMessages extends CvModelBase { return messages; } + static Future> getAllMessagesForRetransmitting() async { + var rows = await dbProvider.db!.query( + tableName, + where: "$columnMessageAcknowledgeByServer = 0", + ); + List messages = await convertToDbMessage(rows); + return messages; + } + static Future getLastMessagesForPreviewForUser( int otherUserId) async { var rows = await dbProvider.db!.query( diff --git a/lib/src/providers/api/api.dart b/lib/src/providers/api/api.dart index 1b49e2b..23a3369 100644 --- a/lib/src/providers/api/api.dart +++ b/lib/src/providers/api/api.dart @@ -8,6 +8,7 @@ import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; import 'package:twonly/main.dart'; import 'package:twonly/src/app.dart'; +import 'package:twonly/src/model/contacts_model.dart'; import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/messages_model.dart'; import 'package:twonly/src/proto/api/error.pb.dart'; @@ -125,6 +126,7 @@ Future uploadMediaFile( box.delete("retransmit-$messageId-media"); box.delete("retransmit-$messageId-uploadtoken"); + await DbContacts.checkAndUpdateFlames(target.toInt()); // Ensures the retransmit of the message await encryptAndSendMessage( diff --git a/lib/src/providers/api/server_messages.dart b/lib/src/providers/api/server_messages.dart index 3dfdec0..c068e79 100644 --- a/lib/src/providers/api/server_messages.dart +++ b/lib/src/providers/api/server_messages.dart @@ -148,6 +148,8 @@ Future handleNewMessage( if (message.kind == MessageKind.video || message.kind == MessageKind.image) { + await DbContacts.checkAndUpdateFlames(fromUserId.toInt()); + dynamic content = message.content!; List downloadToken = content.downloadToken; diff --git a/lib/src/views/chat_list_view.dart b/lib/src/views/chat_list_view.dart index e072c1d..d0d5cb4 100644 --- a/lib/src/views/chat_list_view.dart +++ b/lib/src/views/chat_list_view.dart @@ -1,3 +1,4 @@ +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; import 'package:twonly/src/components/initialsavatar.dart'; import 'package:twonly/src/components/message_send_state_icon.dart'; @@ -174,20 +175,21 @@ class _UserListItem extends State { formatDuration(lastMessageInSeconds), style: TextStyle(fontSize: 12), ), - if (flames > 0) + if (widget.user.flameCounter > 0) Row( children: [ const SizedBox(width: 5), Text("•"), const SizedBox(width: 5), Text( - flames.toString(), + widget.user.flameCounter.toString(), style: TextStyle(fontSize: 12), ), - Icon( - Icons.local_fire_department_sharp, + const SizedBox(width: 1), + FaIcon( + FontAwesomeIcons.fireFlameCurved, color: const Color.fromARGB(255, 215, 73, 58), - size: 16, + size: 10, ), ], ),