From 8cdcc746833a41402415f5927a18603a2a0e2561 Mon Sep 17 00:00:00 2001 From: otsmr Date: Fri, 7 Feb 2025 19:06:17 +0100 Subject: [PATCH] fix flame problem --- README.md | 1 - lib/src/components/best_friends_selector.dart | 11 +++- lib/src/components/flame.dart | 4 +- lib/src/model/contacts_model.dart | 65 ++----------------- lib/src/model/messages_model.dart | 53 +++++++++------ lib/src/providers/api/api.dart | 47 +++++++------- lib/src/providers/api/server_messages.dart | 6 +- .../providers/messages_change_provider.dart | 6 ++ lib/src/utils/misc.dart | 46 +++++++++++++ .../camera_to_share/share_image_view.dart | 22 +++++-- lib/src/views/chats/chat_list_view.dart | 19 ++++-- lib/src/views/chats/media_viewer_view.dart | 5 +- lib/src/views/home_view.dart | 6 +- 13 files changed, 168 insertions(+), 123 deletions(-) diff --git a/README.md b/README.md index 5e6dc5f..f924e22 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ Don't be lonely, get twonly! Send pictures to a friend in real time and be sure ## TODOS bevor first beta -- Flammen Problem fixen - Add no_screenshot plugin: https://pub.dev/packages/no_screenshot - Bei mehreren neu Empfangen Nachrichten fixen - Settings diff --git a/lib/src/components/best_friends_selector.dart b/lib/src/components/best_friends_selector.dart index 8ca5fe7..84a5edd 100644 --- a/lib/src/components/best_friends_selector.dart +++ b/lib/src/components/best_friends_selector.dart @@ -1,6 +1,8 @@ import 'dart:collection'; import 'package:fixnum/fixnum.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:twonly/src/providers/messages_change_provider.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/components/flame.dart'; import 'package:twonly/src/components/headline.dart'; @@ -87,6 +89,11 @@ class UserCheckbox extends StatelessWidget { @override Widget build(BuildContext context) { + int? flameCounter = context + .watch() + .flamesCounter[user.userId.toInt()]; + flameCounter ??= 0; + return Container( padding: EdgeInsets.symmetric(horizontal: 3), // Padding inside the container @@ -116,8 +123,8 @@ class UserCheckbox extends StatelessWidget { : user.displayName, overflow: TextOverflow.ellipsis, ), - if (user.flameCounter > 0) - FlameCounterWidget(user, maxTotalMediaCounter), + if (flameCounter > 0) + FlameCounterWidget(user, flameCounter, maxTotalMediaCounter), Expanded(child: Container()), Checkbox( value: isChecked, diff --git a/lib/src/components/flame.dart b/lib/src/components/flame.dart index 0fb470b..cc1f723 100644 --- a/lib/src/components/flame.dart +++ b/lib/src/components/flame.dart @@ -4,9 +4,11 @@ import 'package:twonly/src/model/contacts_model.dart'; class FlameCounterWidget extends StatelessWidget { final Contact user; final int maxTotalMediaCounter; + final int flameCounter; const FlameCounterWidget( this.user, + this.flameCounter, this.maxTotalMediaCounter, { super.key, }); @@ -19,7 +21,7 @@ class FlameCounterWidget extends StatelessWidget { Text("•"), const SizedBox(width: 5), Text( - user.flameCounter.toString(), + flameCounter.toString(), style: const TextStyle(fontSize: 13), ), Text( diff --git a/lib/src/model/contacts_model.dart b/lib/src/model/contacts_model.dart index 8767932..3399c19 100644 --- a/lib/src/model/contacts_model.dart +++ b/lib/src/model/contacts_model.dart @@ -10,17 +10,13 @@ class Contact { {required this.userId, required this.displayName, required this.accepted, - required this.flameCounter, required this.totalMediaCounter, - required this.lastUpdateOfFlameCounter, required this.requested}); final Int64 userId; final String displayName; final bool accepted; final bool requested; - final int flameCounter; final int totalMediaCounter; - final DateTime lastUpdateOfFlameCounter; } class DbContacts extends CvModelBase { @@ -41,16 +37,9 @@ class DbContacts extends CvModelBase { static const columnBlocked = "blocked"; final blocked = CvField(columnBlocked); - static const columnFlameCounter = "flame_counter"; - final flameCounter = CvField(columnFlameCounter); - static const columnTotalMediaCounter = "total_media_counter"; final totalMediaCounter = CvField(columnTotalMediaCounter); - static const columnLastUpdateOfFlameCounter = "last_update_flame_counter"; - final lastUpdateOfFlameCounter = - CvField(columnLastUpdateOfFlameCounter); - static const columnCreatedAt = "created_at"; final createdAt = CvField(columnCreatedAt); @@ -65,8 +54,6 @@ class DbContacts extends CvModelBase { $columnRequested INT NOT NULL DEFAULT 0, $columnBlocked INT NOT NULL DEFAULT 0, $columnTotalMediaCounter INT NOT NULL DEFAULT 0, - $columnFlameCounter INT NOT NULL DEFAULT 0, - $columnLastUpdateOfFlameCounter DATETIME DEFAULT CURRENT_TIMESTAMP, $columnCreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ) """; @@ -85,46 +72,22 @@ class DbContacts extends CvModelBase { List> result = await dbProvider.db!.query( tableName, - columns: [ - columnLastUpdateOfFlameCounter, - columnFlameCounter, - columnTotalMediaCounter - ], + columns: [columnTotalMediaCounter], where: '$columnUserId = ?', whereArgs: [userId], ); if (result.isNotEmpty) { - String lastUpdateString = result.first[columnLastUpdateOfFlameCounter]; - DateTime lastUpdate = DateTime.tryParse(lastUpdateString)!; - - if (timestamp.isAfter(lastUpdate)) { - int currentCount = result.first.cast()[columnFlameCounter]; - int totalMediaCounter = result.first.cast()[columnTotalMediaCounter]; - if (lastUpdate.isAfter(DateTime.now() - .subtract(Duration(seconds: nextFlameCounterInSeconds)))) { - _updateFlameCounter(userId, currentCount, - totalMediaCounter: totalMediaCounter + 1, - timestamp: timestamp); // just update the time - } else { - _updateFlameCounter(userId, (currentCount + 1), - totalMediaCounter: totalMediaCounter + 1, timestamp: timestamp); - } - } + int totalMediaCounter = result.first.cast()[columnTotalMediaCounter]; + _updateFlameCounter(userId, totalMediaCounter + 1); + globalCallBackOnContactChange(); } - globalCallBackOnContactChange(); } - static Future _updateFlameCounter(int userId, int newCount, - {DateTime? timestamp, int? totalMediaCounter}) async { - timestamp ??= DateTime.now(); + static Future _updateFlameCounter(int userId, int totalMediaCounter) async { Map valuesToUpdate = { - columnFlameCounter: newCount, - columnLastUpdateOfFlameCounter: timestamp.toIso8601String() + columnTotalMediaCounter: totalMediaCounter }; - if (totalMediaCounter != null) { - valuesToUpdate[columnTotalMediaCounter] = totalMediaCounter; - } await dbProvider.db!.update( tableName, valuesToUpdate, @@ -141,9 +104,7 @@ class DbContacts extends CvModelBase { columnDisplayName, columnAccepted, columnRequested, - columnFlameCounter, columnTotalMediaCounter, - columnLastUpdateOfFlameCounter, columnCreatedAt ], where: "$columnBlocked = 0"); @@ -151,27 +112,13 @@ 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(seconds: nextFlameCounterInSeconds * 2)))) { - // _updateFlameCounter(userId, 0); - // flameCounter = 0; - // } - parsedUsers.add( Contact( userId: Int64(userId), totalMediaCounter: users.cast()[i][columnTotalMediaCounter], 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 93e42de..79339da 100644 --- a/lib/src/model/messages_model.dart +++ b/lib/src/model/messages_model.dart @@ -19,7 +19,7 @@ class DbMessage { required this.messageAcknowledgeByUser, required this.isDownloaded, required this.messageAcknowledgeByServer, - required this.sendOrReceivedAt, + required this.sendAt, }); int messageId; @@ -32,7 +32,7 @@ class DbMessage { bool messageAcknowledgeByUser; bool isDownloaded; bool messageAcknowledgeByServer; - DateTime sendOrReceivedAt; + DateTime sendAt; bool containsOtherMedia() { if (messageOtherId == null) return false; @@ -99,8 +99,8 @@ class DbMessages extends CvModelBase { final messageAcknowledgeByServer = CvField(columnMessageAcknowledgeByServer); - static const columnSendOrReceivedAt = "message_send_or_received_at"; - final sendOrReceivedAt = CvField(columnSendOrReceivedAt); + static const columnSendAt = "message_send_or_received_at"; + final sendAt = CvField(columnSendAt); static const columnUpdatedAt = "updated_at"; final updatedAt = CvField(columnUpdatedAt); @@ -116,12 +116,33 @@ class DbMessages extends CvModelBase { $columnMessageAcknowledgeByServer INTEGER NOT NULL DEFAULT 0, $columnMessageContentJson TEXT NOT NULL, $columnMessageOpenedAt DATETIME DEFAULT NULL, - $columnSendOrReceivedAt DATETIME DEFAULT CURRENT_TIMESTAMP, + $columnSendAt DATETIME DEFAULT CURRENT_TIMESTAMP, $columnUpdatedAt DATETIME DEFAULT CURRENT_TIMESTAMP ) """; } + static Future> getMessageDates(int otherUserId) async { + final List> maps = await dbProvider.db!.rawQuery(''' + SELECT $columnSendAt, $columnMessageOtherId + FROM $tableName + WHERE $columnOtherUserId = ? + ORDER BY $columnSendAt DESC; + ''', [otherUserId]); + + try { + return List.generate(maps.length, (i) { + return ( + DateTime.tryParse(maps[i][columnSendAt])!, + maps[i][columnMessageOtherId] + ); + }); + } catch (e) { + Logger("error parsing datetime: $e"); + return []; + } + } + static Future deleteMessageById(int messageId) async { await dbProvider.db!.delete( tableName, @@ -147,14 +168,14 @@ class DbMessages extends CvModelBase { return null; } - static Future insertMyMessage( - int userIdFrom, MessageKind kind, MessageContent content) async { + static Future insertMyMessage(int userIdFrom, MessageKind kind, + MessageContent content, DateTime messageSendAt) async { try { int messageId = await dbProvider.db!.insert(tableName, { columnMessageKind: kind.index, columnMessageContentJson: jsonEncode(content.toJson()), columnOtherUserId: userIdFrom, - columnSendOrReceivedAt: DateTime.now().toIso8601String() + columnSendAt: messageSendAt.toIso8601String() }); globalCallBackOnMessageChange(userIdFrom); return messageId; @@ -165,7 +186,7 @@ class DbMessages extends CvModelBase { } static Future insertOtherMessage(int userIdFrom, MessageKind kind, - int messageOtherId, String jsonContent) async { + int messageOtherId, String jsonContent, DateTime messageSendAt) async { try { int messageId = await dbProvider.db!.insert(tableName, { columnMessageOtherId: messageOtherId, @@ -175,7 +196,7 @@ class DbMessages extends CvModelBase { columnMessageAcknowledgeByUser: 0, // ack in case of sending corresponds to the opened flag columnOtherUserId: userIdFrom, - columnSendOrReceivedAt: DateTime.now().toIso8601String() + columnSendAt: messageSendAt.toIso8601String() }); globalCallBackOnMessageChange(userIdFrom); return messageId; @@ -330,13 +351,8 @@ class DbMessages extends CvModelBase { } @override - List get fields => [ - messageId, - messageKind, - messageContentJson, - messageOpenedAt, - sendOrReceivedAt - ]; + List get fields => + [messageId, messageKind, messageContentJson, messageOpenedAt, sendAt]; static Future> convertToDbMessage( List fromDb) async { @@ -366,8 +382,7 @@ class DbMessages extends CvModelBase { } parsedUsers.add( DbMessage( - sendOrReceivedAt: - DateTime.tryParse(fromDb[i][columnSendOrReceivedAt])!, + sendAt: DateTime.tryParse(fromDb[i][columnSendAt])!, messageId: fromDb[i][columnMessageId], messageOtherId: messageOtherId, otherUserId: fromDb[i][columnOtherUserId], diff --git a/lib/src/providers/api/api.dart b/lib/src/providers/api/api.dart index cdb91c5..7ec809f 100644 --- a/lib/src/providers/api/api.dart +++ b/lib/src/providers/api/api.dart @@ -46,13 +46,8 @@ Future tryTransmitMessages() async { if (encryptedMedia != null) { final content = retransmit[i].messageContent; if (content is MediaMessageContent) { - uploadMediaFile( - msgId, - Int64(retransmit[i].otherUserId), - encryptedMedia, - content.isRealTwonly, - content.maxShowTime, - ); + uploadMediaFile(msgId, Int64(retransmit[i].otherUserId), encryptedMedia, + content.isRealTwonly, content.maxShowTime, retransmit[i].sendAt); } } } @@ -88,18 +83,18 @@ Future encryptAndSendMessage(Int64 userId, Message msg) async { Future sendTextMessage(Int64 target, String message) async { MessageContent content = TextMessageContent(text: message); + DateTime messageSendAt = + DateTime.now().subtract(Duration(days: 1, minutes: 120)); + int? messageId = await DbMessages.insertMyMessage( - target.toInt(), - MessageKind.textMessage, - content, - ); + target.toInt(), MessageKind.textMessage, content, messageSendAt); if (messageId == null) return; Message msg = Message( kind: MessageKind.textMessage, messageId: messageId, content: content, - timestamp: DateTime.now(), + timestamp: messageSendAt, ); encryptAndSendMessage(target, msg); @@ -112,6 +107,7 @@ Future uploadMediaFile( Uint8List encryptedMedia, bool isRealTwonly, int maxShowTime, + DateTime messageSendAt, ) async { Box box = await getMediaStorage(); @@ -156,7 +152,7 @@ Future uploadMediaFile( maxShowTime: maxShowTime, isRealTwonly: isRealTwonly, isVideo: false), - timestamp: DateTime.now(), + timestamp: messageSendAt, ), ); } @@ -167,14 +163,17 @@ Future encryptAndUploadMediaFile( bool isRealTwonly, int maxShowTime, ) async { + DateTime messageSendAt = DateTime.now(); int? messageId = await DbMessages.insertMyMessage( target.toInt(), MessageKind.image, MediaMessageContent( - downloadToken: [], - maxShowTime: maxShowTime, - isRealTwonly: isRealTwonly, - isVideo: false)); + downloadToken: [], + maxShowTime: maxShowTime, + isRealTwonly: isRealTwonly, + isVideo: false, + ), + messageSendAt); // isRealTwonly, if (messageId == null) return; @@ -185,8 +184,8 @@ Future encryptAndUploadMediaFile( return; } - await uploadMediaFile( - messageId, target, encryptBytes, isRealTwonly, maxShowTime); + await uploadMediaFile(messageId, target, encryptBytes, isRealTwonly, + maxShowTime, messageSendAt); } Future sendImage( @@ -253,11 +252,11 @@ Future getDownloadedMedia( final box = await getMediaStorage(); Uint8List? media = box.get("${mediaToken}_downloaded"); - // int fromUserId = box.get("${mediaToken}_fromUserId"); - // await userOpenedOtherMessage(fromUserId, messageOtherId); - // box.delete(mediaToken.toString()); - // box.put("${mediaToken}_downloaded", "deleted"); - // box.delete("${mediaToken}_fromUserId"); + int fromUserId = box.get("${mediaToken}_fromUserId"); + await userOpenedOtherMessage(fromUserId, messageOtherId); + box.delete(mediaToken.toString()); + box.put("${mediaToken}_downloaded", "deleted"); + box.delete("${mediaToken}_fromUserId"); return media; } diff --git a/lib/src/providers/api/server_messages.dart b/lib/src/providers/api/server_messages.dart index 4bc45e8..40c8258 100644 --- a/lib/src/providers/api/server_messages.dart +++ b/lib/src/providers/api/server_messages.dart @@ -131,7 +131,11 @@ Future handleNewMessage( } else { String content = jsonEncode(message.content.toJson()); int? messageId = await DbMessages.insertOtherMessage( - fromUserId.toInt(), message.kind, message.messageId!, content); + fromUserId.toInt(), + message.kind, + message.messageId!, + content, + message.timestamp); if (messageId == null) { return client.Response()..error = ErrorCode.InternalError; diff --git a/lib/src/providers/messages_change_provider.dart b/lib/src/providers/messages_change_provider.dart index ee06d7e..db02a89 100644 --- a/lib/src/providers/messages_change_provider.dart +++ b/lib/src/providers/messages_change_provider.dart @@ -1,15 +1,18 @@ import 'package:flutter/foundation.dart'; import 'package:twonly/src/model/contacts_model.dart'; import 'package:twonly/src/model/messages_model.dart'; +import 'package:twonly/src/utils/misc.dart'; /// This provider does always contains the latest messages send or received /// for every contact. class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin { final Map _lastMessage = {}; final Map _changeCounter = {}; + final Map _flamesCounter = {}; Map get lastMessage => _lastMessage; Map get changeCounter => _changeCounter; + Map get flamesCounter => _flamesCounter; void updateLastMessageFor(int targetUserId) async { DbMessage? last = @@ -21,6 +24,7 @@ class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin { changeCounter[targetUserId] = 0; } changeCounter[targetUserId] = changeCounter[targetUserId]! + 1; + flamesCounter[targetUserId] = await getFlamesForOtherUser(targetUserId); notifyListeners(); } @@ -33,6 +37,8 @@ class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin { if (last != null) { _lastMessage[last.otherUserId] = last; } + flamesCounter[contact.userId.toInt()] = + await getFlamesForOtherUser(contact.userId.toInt()); } notifyListeners(); } diff --git a/lib/src/utils/misc.dart b/lib/src/utils/misc.dart index 2e7a7f7..e81f4f8 100644 --- a/lib/src/utils/misc.dart +++ b/lib/src/utils/misc.dart @@ -7,6 +7,7 @@ import 'package:gal/gal.dart'; import 'package:logging/logging.dart'; import 'package:path_provider/path_provider.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:twonly/src/model/messages_model.dart'; import 'package:twonly/src/proto/api/error.pb.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -131,3 +132,48 @@ Future getCompressedImage(Uint8List imageBytes) async { ); return result; } + +int getFlameCounter(List dates) { + if (dates.isEmpty) return 0; + + int flamesCount = 0; + DateTime lastFlameCount = DateTime.now(); + + if (dates[0].difference(lastFlameCount).inDays == 0) { + flamesCount = 1; + lastFlameCount = dates[0]; + } + + // print(dates[0]); + for (int i = 1; i < dates.length; i++) { + // print( + // "${dates[i]} ${dates[i].difference(dates[i - 1]).inDays} ${dates[i].difference(lastFlameCount).inDays}"); + if (dates[i].difference(dates[i - 1]).inDays == 0) { + if (lastFlameCount.difference(dates[i]).inDays == 1) { + flamesCount++; + lastFlameCount = dates[i]; + } + } else { + break; // Stop counting if there's a break in the sequence + } + } + return flamesCount; +} + +Future getFlamesForOtherUser(int otherUserId) async { + List<(DateTime, int?)> dates = await DbMessages.getMessageDates(otherUserId); + // print("Dates ${dates.length}"); + if (dates.isEmpty) return 0; + + List received = + dates.where((x) => x.$2 != null).map((x) => x.$1).toList(); + List send = + dates.where((x) => x.$2 == null).map((x) => x.$1).toList(); + + // print("Received ${received.length} and send ${send.length}"); + + int a = getFlameCounter(received); + int b = getFlameCounter(send); + // print("Received $a and send $b"); + return min(a, b); +} diff --git a/lib/src/views/camera_to_share/share_image_view.dart b/lib/src/views/camera_to_share/share_image_view.dart index 89ab15d..3fe4ffc 100644 --- a/lib/src/views/camera_to_share/share_image_view.dart +++ b/lib/src/views/camera_to_share/share_image_view.dart @@ -3,12 +3,14 @@ import 'dart:typed_data'; import 'package:fixnum/fixnum.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; import 'package:twonly/src/components/best_friends_selector.dart'; import 'package:twonly/src/components/flame.dart'; import 'package:twonly/src/components/headline.dart'; import 'package:twonly/src/components/initialsavatar.dart'; import 'package:twonly/src/model/contacts_model.dart'; import 'package:twonly/src/providers/api/api.dart'; +import 'package:twonly/src/providers/messages_change_provider.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/views/home_view.dart'; @@ -51,10 +53,14 @@ class _ShareImageView extends State { } Future _updateUsers(List users) async { + Map flameCounters = + context.read().flamesCounter; + // Sort contacts by flameCounter and then by totalMediaCounter users.sort((a, b) { // First, compare by flameCounter - int flameComparison = b.flameCounter.compareTo(a.flameCounter); + int flameComparison = flameCounters[b.userId.toInt()]! + .compareTo(flameCounters[a.userId.toInt()]!); if (flameComparison != 0) { return flameComparison; // Sort by flameCounter in descending order } @@ -74,7 +80,8 @@ class _ShareImageView extends State { List otherUsers = []; for (var contact in users) { - if (contact.flameCounter > 0 && bestFriends.length < 6) { + if (flameCounters[contact.userId.toInt()]! > 0 && + bestFriends.length < 6) { bestFriends.add(contact); } else { otherUsers.add(contact); @@ -179,7 +186,7 @@ class _ShareImageView extends State { // TODO: pop back to the HomeView page popUntil did not work. check later how to improve in case of pushing more then 2 Navigator.pop(context); Navigator.pop(context); - globalUpdateOfHomeViewPageIndex(0); + globalUpdateOfHomeViewPageIndex(1); }, style: ButtonStyle( padding: WidgetStateProperty.all( @@ -216,16 +223,21 @@ class UserList extends StatelessWidget { // Step 1: Sort the users alphabetically users.sort((a, b) => a.displayName.compareTo(b.displayName)); + Map flameCounters = + context.watch().flamesCounter; + return ListView.builder( restorationId: 'new_message_users_list', itemCount: users.length, itemBuilder: (BuildContext context, int i) { Contact user = users[i]; + int? flameCounter = flameCounters[user.userId.toInt()]; + flameCounter ??= 0; return ListTile( title: Row(children: [ Text(user.displayName), - if (user.flameCounter > 0) - FlameCounterWidget(user, maxTotalMediaCounter), + if (flameCounter > 0) + FlameCounterWidget(user, flameCounter, maxTotalMediaCounter), ]), leading: InitialsAvatar( displayName: user.displayName, diff --git a/lib/src/views/chats/chat_list_view.dart b/lib/src/views/chats/chat_list_view.dart index 043b539..e09937d 100644 --- a/lib/src/views/chats/chat_list_view.dart +++ b/lib/src/views/chats/chat_list_view.dart @@ -45,8 +45,8 @@ class _ChatListViewState extends State { .toList(); activeUsers.sort((b, a) { return lastMessages[a.userId.toInt()]! - .sendOrReceivedAt - .compareTo(lastMessages[b.userId.toInt()]!.sendOrReceivedAt); + .sendAt + .compareTo(lastMessages[b.userId.toInt()]!.sendAt); }); int maxTotalMediaCounter = 0; @@ -165,9 +165,8 @@ class _UserListItem extends State { @override Widget build(BuildContext context) { - int lastMessageInSeconds = DateTime.now() - .difference(widget.lastMessage.sendOrReceivedAt) - .inSeconds; + int lastMessageInSeconds = + DateTime.now().difference(widget.lastMessage.sendAt).inSeconds; MessageSendState state = widget.lastMessage.getSendState(); bool isDownloading = false; @@ -183,6 +182,11 @@ class _UserListItem extends State { .contains(token.toString()); } + int? flameCounter = context + .watch() + .flamesCounter[widget.user.userId.toInt()]; + flameCounter ??= 0; + return UserContextMenu( user: widget.user, child: ListTile( @@ -196,8 +200,9 @@ class _UserListItem extends State { formatDuration(lastMessageInSeconds), style: TextStyle(fontSize: 12), ), - if (widget.user.flameCounter > 0) - FlameCounterWidget(widget.user, widget.maxTotalMediaCounter), + if (flameCounter > 0) + FlameCounterWidget( + widget.user, flameCounter, widget.maxTotalMediaCounter), ], ), leading: InitialsAvatar(displayName: widget.user.displayName), diff --git a/lib/src/views/chats/media_viewer_view.dart b/lib/src/views/chats/media_viewer_view.dart index 580b673..bf6d44b 100644 --- a/lib/src/views/chats/media_viewer_view.dart +++ b/lib/src/views/chats/media_viewer_view.dart @@ -24,6 +24,7 @@ class _MediaViewerViewState extends State { DateTime? canBeSeenUntil; int maxShowTime = 999999; bool isRealTwonly = false; + Timer? _timer; // DateTime opened; @override @@ -72,7 +73,7 @@ class _MediaViewerViewState extends State { } startTimer() { - Future.delayed(canBeSeenUntil!.difference(DateTime.now()), () { + _timer = Timer(canBeSeenUntil!.difference(DateTime.now()), () { if (context.mounted) { Navigator.pop(context); } @@ -96,6 +97,8 @@ class _MediaViewerViewState extends State { @override void dispose() { super.dispose(); + + _timer?.cancel(); } @override diff --git a/lib/src/views/home_view.dart b/lib/src/views/home_view.dart index 8905c8f..9ef6963 100644 --- a/lib/src/views/home_view.dart +++ b/lib/src/views/home_view.dart @@ -66,8 +66,8 @@ class HomeViewState extends State { activePageIdx = index; }, children: [ - ChatListView(), CameraPreviewViewPermission(), + ChatListView(), ], ), bottomNavigationBar: BottomNavigationBar( @@ -76,12 +76,12 @@ class HomeViewState extends State { selectedIconTheme: IconThemeData(color: const Color.fromARGB(255, 255, 255, 255)), items: [ - BottomNavigationBarItem( - icon: FaIcon(FontAwesomeIcons.solidComments), label: ""), BottomNavigationBarItem( icon: FaIcon(FontAwesomeIcons.camera), label: "", ), + BottomNavigationBarItem( + icon: FaIcon(FontAwesomeIcons.solidComments), label: ""), // BottomNavigationBarItem( // icon: FaIcon(FontAwesomeIcons.userShield), label: ""), ],