some performance improvements and fix #18

This commit is contained in:
otsmr 2025-02-11 11:08:08 +01:00
parent 504b528770
commit e21935eedf
8 changed files with 66 additions and 34 deletions

View file

@ -27,7 +27,7 @@ bool globalIsAppInBackground = true;
// these two callbacks are called on updated to the corresponding database
Function globalCallBackOnContactChange = () {};
Future Function(int) globalCallBackOnMessageChange = (a) async {};
Future Function(int, int?) globalCallBackOnMessageChange = (a, b) async {};
Function(List<int>, bool) globalCallBackOnDownloadChange = (a, b) {};
/// The Widget that configures your application.
@ -67,8 +67,10 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
context.read<DownloadChangeProvider>().update(token, add);
};
globalCallBackOnMessageChange = (userId) async {
await context.read<MessagesChangeProvider>().updateLastMessageFor(userId);
globalCallBackOnMessageChange = (userId, messageId) async {
await context
.read<MessagesChangeProvider>()
.updateLastMessageFor(userId, messageId);
};
WidgetsBinding.instance.addPostFrameCallback((_) {
@ -194,7 +196,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
globalCallbackConnectionState = (a) {};
globalCallBackOnDownloadChange = (a, b) {};
globalCallBackOnContactChange = () {};
globalCallBackOnMessageChange = (a) async {};
globalCallBackOnMessageChange = (a, b) async {};
super.dispose();
}

View file

@ -152,7 +152,7 @@ class DbMessages extends CvModelBase {
);
int? fromUserId = await getFromUserIdByMessageId(messageId);
if (fromUserId != null) {
globalCallBackOnMessageChange(fromUserId);
globalCallBackOnMessageChange(fromUserId, messageId);
}
return fromUserId;
}
@ -179,7 +179,7 @@ class DbMessages extends CvModelBase {
columnOtherUserId: userIdFrom,
columnSendAt: messageSendAt.toIso8601String()
});
globalCallBackOnMessageChange(userIdFrom);
globalCallBackOnMessageChange(userIdFrom, messageId);
return messageId;
} catch (e) {
Logger("messsage_model/insertMyMessage").shout("$e");
@ -200,7 +200,7 @@ class DbMessages extends CvModelBase {
columnOtherUserId: userIdFrom,
columnSendAt: messageSendAt.toIso8601String()
});
globalCallBackOnMessageChange(userIdFrom);
globalCallBackOnMessageChange(userIdFrom, messageId);
return messageId;
} catch (e) {
Logger("messsage_model/insertOtherMessage").shout("$e");
@ -235,6 +235,13 @@ class DbMessages extends CvModelBase {
return messages;
}
static Future<DbMessage?> getMessageById(int messageId) async {
var rows = await dbProvider.db!.query(tableName,
where: "$columnMessageId = ?", whereArgs: [messageId]);
List<DbMessage> messages = await convertToDbMessage(rows);
return messages.firstOrNull;
}
static Future<List<DbMessage>> getAllMessagesForRetransmitting() async {
var rows = await dbProvider.db!.query(
tableName,
@ -289,7 +296,7 @@ class DbMessages extends CvModelBase {
if (notifyFlutterState) {
int? fromUserId = await getFromUserIdByMessageId(messageId);
if (fromUserId != null) {
globalCallBackOnMessageChange(fromUserId);
globalCallBackOnMessageChange(fromUserId, messageId);
}
}
}
@ -302,7 +309,7 @@ class DbMessages extends CvModelBase {
where: "$columnMessageOtherId = ?",
whereArgs: [messageId],
);
globalCallBackOnMessageChange(fromUserId);
globalCallBackOnMessageChange(fromUserId, messageId);
}
// this ensures that the message id can be spoofed by another person
@ -314,7 +321,7 @@ class DbMessages extends CvModelBase {
where: "$columnMessageId = ? AND $columnOtherUserId = ?",
whereArgs: [messageId, fromUserId],
);
globalCallBackOnMessageChange(fromUserId);
globalCallBackOnMessageChange(fromUserId, messageId);
}
static Future userOpenedOtherMessage(
@ -351,7 +358,7 @@ class DbMessages extends CvModelBase {
where: "$messageId = ? AND $columnOtherUserId = ?",
whereArgs: [messageId, fromUserId],
);
globalCallBackOnMessageChange(fromUserId);
globalCallBackOnMessageChange(fromUserId, messageId);
}
@override
@ -374,6 +381,7 @@ class DbMessages extends CvModelBase {
List<dynamic> fromDb) async {
try {
List<DbMessage> parsedUsers = [];
final box = await getMediaStorage();
for (int i = 0; i < fromDb.length; i++) {
dynamic messageOpenedAt = fromDb[i][columnMessageOpenedAt];
@ -397,7 +405,8 @@ class DbMessages extends CvModelBase {
if (messageOtherId != null) {
if (content is MediaMessageContent) {
// when the media was send from the user itself the content is null
isDownloaded = await isMediaDownloaded(content.downloadToken);
isDownloaded =
box.containsKey("${content.downloadToken}_downloaded");
}
}
parsedUsers.add(

View file

@ -91,7 +91,11 @@ Future sendTextMessage(Int64 target, String message) async {
DateTime messageSendAt = DateTime.now();
int? messageId = await DbMessages.insertMyMessage(
target.toInt(), MessageKind.textMessage, content, messageSendAt);
target.toInt(),
MessageKind.textMessage,
content,
messageSendAt,
);
if (messageId == null) return;
Message msg = Message(
@ -264,13 +268,11 @@ Future sendImage(
}
// first step encrypt and store the encrypted image
for (SendImage task in tasks) {
await task.encryptAndStore();
}
await Future.wait(tasks.map((task) => task.encryptAndStore()));
// after the images are safely stored try do upload them one by one
for (SendImage task in tasks) {
await task.upload();
task.upload();
}
}
@ -332,11 +334,6 @@ Future<Uint8List?> getDownloadedMedia(
return media;
}
Future<bool> isMediaDownloaded(List<int> mediaToken) async {
final box = await getMediaStorage();
return box.containsKey("${mediaToken}_downloaded");
}
Future initMediaStorage() async {
final storage = getSecureStorage();
var containsEncryptionKey =

View file

@ -57,15 +57,15 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
final box = await getMediaStorage();
String boxId = data.uploadToken.toString();
int? messageId = box.get("${data.uploadToken}_messageId");
if (data.fin && data.data.isEmpty) {
// media file was deleted by the server. remove the media from device
int? messageId = box.get("${data.uploadToken}_messageId");
if (messageId != null) {
int? fromUserId = await DbMessages.deleteMessageById(messageId);
box.delete(boxId);
if (fromUserId != null) {
globalCallBackOnMessageChange(fromUserId);
globalCallBackOnMessageChange(fromUserId, messageId);
}
box.delete("${data.uploadToken}_fromUserId");
box.delete("${data.uploadToken}_downloaded");
@ -107,7 +107,7 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
}
box.delete(boxId);
await globalCallBackOnMessageChange(fromUserId);
await globalCallBackOnMessageChange(fromUserId, messageId);
globalCallBackOnDownloadChange(data.uploadToken, false);
}
} else {

View file

@ -17,16 +17,31 @@ class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin {
Map<int, int> get changeCounter => _changeCounter;
Map<int, int> get flamesCounter => _flamesCounter;
Future updateLastMessageFor(int targetUserId) async {
Future updateLastMessageFor(int targetUserId, int? messageId) async {
DbMessage? last =
await DbMessages.getLastMessagesForPreviewForUser(targetUserId);
if (last != null) {
_lastMessage[last.otherUserId] = last;
}
flamesCounter[targetUserId] = await getFlamesForOtherUser(targetUserId);
notifyListeners();
// notifyListeners();
if (messageId == null || _allMessagesFromUser[targetUserId] == null) {
loadMessagesForUser(targetUserId, force: true);
} else {
DbMessage? msg = await DbMessages.getMessageById(messageId);
if (msg != null) {
int index = _allMessagesFromUser[targetUserId]!
.indexWhere((x) => x.messageId == messageId);
if (index == -1) {
_allMessagesFromUser[targetUserId]!.insert(0, msg);
} else {
_allMessagesFromUser[targetUserId]![index] = msg;
}
}
_allMessagesFromUser[targetUserId] = allMessagesFromUser[targetUserId]!;
notifyListeners();
}
}
Future loadMessagesForUser(int targetUserId, {bool force = false}) async {

View file

@ -373,15 +373,16 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
icon: FaIcon(FontAwesomeIcons.solidPaperPlane),
onPressed: () async {
if (sendNextMediaToUserId != null) {
Navigator.popUntil(context, (route) => route.isFirst);
Uint8List? imageBytes = await getMergedImage();
globalUpdateOfHomeViewPageIndex(1);
sendImage(
[Int64(sendNextMediaToUserId)],
imageBytes!,
_isRealTwonly,
_maxShowTime,
);
Navigator.popUntil(context, (route) => route.isFirst);
globalUpdateOfHomeViewPageIndex(1);
// send hier...
return;
}

View file

@ -36,6 +36,7 @@ class _ShareImageView extends State<ShareImageView> {
List<Contact> _bestFriends = [];
int maxTotalMediaCounter = 0;
Uint8List? imageBytes;
bool sendingImage = false;
final HashSet<Int64> _selectedUserIds = HashSet<Int64>();
final TextEditingController searchUserName = TextEditingController();
bool showRealTwonlyWarning = false;
@ -188,7 +189,7 @@ class _ShareImageView extends State<ShareImageView> {
mainAxisAlignment: MainAxisAlignment.end,
children: [
FilledButton.icon(
icon: imageBytes == null
icon: imageBytes == null || sendingImage
? SizedBox(
height: 12,
width: 12,
@ -202,14 +203,19 @@ class _ShareImageView extends State<ShareImageView> {
if (imageBytes == null || _selectedUserIds.isEmpty) {
return;
}
sendImage(
setState(() {
sendingImage = true;
});
await sendImage(
_selectedUserIds.toList(),
imageBytes!,
widget.isRealTwonly,
widget.maxShowTime,
);
if (context.mounted) {
Navigator.popUntil(context, (route) => route.isFirst);
globalUpdateOfHomeViewPageIndex(1);
}
},
style: ButtonStyle(
padding: WidgetStateProperty.all<EdgeInsets>(

View file

@ -165,6 +165,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
.watch<MessagesChangeProvider>()
.allMessagesFromUser[user.userId.toInt()] ??
[];
print(messages.length);
messages.where((x) => x.messageOpenedAt == null).forEach((message) {
if (message.messageOtherId != null &&
@ -219,6 +220,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
itemCount: messages.length, // Number of items in the list
reverse: true,
itemBuilder: (context, i) {
print(i);
bool lastMessageFromSameUser = false;
if (i > 0) {
lastMessageFromSameUser =