mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 11:18:41 +00:00
some performance improvements and fix #18
This commit is contained in:
parent
504b528770
commit
e21935eedf
8 changed files with 66 additions and 34 deletions
|
|
@ -27,7 +27,7 @@ bool globalIsAppInBackground = true;
|
||||||
|
|
||||||
// these two callbacks are called on updated to the corresponding database
|
// these two callbacks are called on updated to the corresponding database
|
||||||
Function globalCallBackOnContactChange = () {};
|
Function globalCallBackOnContactChange = () {};
|
||||||
Future Function(int) globalCallBackOnMessageChange = (a) async {};
|
Future Function(int, int?) globalCallBackOnMessageChange = (a, b) async {};
|
||||||
Function(List<int>, bool) globalCallBackOnDownloadChange = (a, b) {};
|
Function(List<int>, bool) globalCallBackOnDownloadChange = (a, b) {};
|
||||||
|
|
||||||
/// The Widget that configures your application.
|
/// The Widget that configures your application.
|
||||||
|
|
@ -67,8 +67,10 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||||
context.read<DownloadChangeProvider>().update(token, add);
|
context.read<DownloadChangeProvider>().update(token, add);
|
||||||
};
|
};
|
||||||
|
|
||||||
globalCallBackOnMessageChange = (userId) async {
|
globalCallBackOnMessageChange = (userId, messageId) async {
|
||||||
await context.read<MessagesChangeProvider>().updateLastMessageFor(userId);
|
await context
|
||||||
|
.read<MessagesChangeProvider>()
|
||||||
|
.updateLastMessageFor(userId, messageId);
|
||||||
};
|
};
|
||||||
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
|
@ -194,7 +196,7 @@ class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
|
||||||
globalCallbackConnectionState = (a) {};
|
globalCallbackConnectionState = (a) {};
|
||||||
globalCallBackOnDownloadChange = (a, b) {};
|
globalCallBackOnDownloadChange = (a, b) {};
|
||||||
globalCallBackOnContactChange = () {};
|
globalCallBackOnContactChange = () {};
|
||||||
globalCallBackOnMessageChange = (a) async {};
|
globalCallBackOnMessageChange = (a, b) async {};
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ class DbMessages extends CvModelBase {
|
||||||
);
|
);
|
||||||
int? fromUserId = await getFromUserIdByMessageId(messageId);
|
int? fromUserId = await getFromUserIdByMessageId(messageId);
|
||||||
if (fromUserId != null) {
|
if (fromUserId != null) {
|
||||||
globalCallBackOnMessageChange(fromUserId);
|
globalCallBackOnMessageChange(fromUserId, messageId);
|
||||||
}
|
}
|
||||||
return fromUserId;
|
return fromUserId;
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +179,7 @@ class DbMessages extends CvModelBase {
|
||||||
columnOtherUserId: userIdFrom,
|
columnOtherUserId: userIdFrom,
|
||||||
columnSendAt: messageSendAt.toIso8601String()
|
columnSendAt: messageSendAt.toIso8601String()
|
||||||
});
|
});
|
||||||
globalCallBackOnMessageChange(userIdFrom);
|
globalCallBackOnMessageChange(userIdFrom, messageId);
|
||||||
return messageId;
|
return messageId;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger("messsage_model/insertMyMessage").shout("$e");
|
Logger("messsage_model/insertMyMessage").shout("$e");
|
||||||
|
|
@ -200,7 +200,7 @@ class DbMessages extends CvModelBase {
|
||||||
columnOtherUserId: userIdFrom,
|
columnOtherUserId: userIdFrom,
|
||||||
columnSendAt: messageSendAt.toIso8601String()
|
columnSendAt: messageSendAt.toIso8601String()
|
||||||
});
|
});
|
||||||
globalCallBackOnMessageChange(userIdFrom);
|
globalCallBackOnMessageChange(userIdFrom, messageId);
|
||||||
return messageId;
|
return messageId;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger("messsage_model/insertOtherMessage").shout("$e");
|
Logger("messsage_model/insertOtherMessage").shout("$e");
|
||||||
|
|
@ -235,6 +235,13 @@ class DbMessages extends CvModelBase {
|
||||||
return messages;
|
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 {
|
static Future<List<DbMessage>> getAllMessagesForRetransmitting() async {
|
||||||
var rows = await dbProvider.db!.query(
|
var rows = await dbProvider.db!.query(
|
||||||
tableName,
|
tableName,
|
||||||
|
|
@ -289,7 +296,7 @@ class DbMessages extends CvModelBase {
|
||||||
if (notifyFlutterState) {
|
if (notifyFlutterState) {
|
||||||
int? fromUserId = await getFromUserIdByMessageId(messageId);
|
int? fromUserId = await getFromUserIdByMessageId(messageId);
|
||||||
if (fromUserId != null) {
|
if (fromUserId != null) {
|
||||||
globalCallBackOnMessageChange(fromUserId);
|
globalCallBackOnMessageChange(fromUserId, messageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -302,7 +309,7 @@ class DbMessages extends CvModelBase {
|
||||||
where: "$columnMessageOtherId = ?",
|
where: "$columnMessageOtherId = ?",
|
||||||
whereArgs: [messageId],
|
whereArgs: [messageId],
|
||||||
);
|
);
|
||||||
globalCallBackOnMessageChange(fromUserId);
|
globalCallBackOnMessageChange(fromUserId, messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this ensures that the message id can be spoofed by another person
|
// this ensures that the message id can be spoofed by another person
|
||||||
|
|
@ -314,7 +321,7 @@ class DbMessages extends CvModelBase {
|
||||||
where: "$columnMessageId = ? AND $columnOtherUserId = ?",
|
where: "$columnMessageId = ? AND $columnOtherUserId = ?",
|
||||||
whereArgs: [messageId, fromUserId],
|
whereArgs: [messageId, fromUserId],
|
||||||
);
|
);
|
||||||
globalCallBackOnMessageChange(fromUserId);
|
globalCallBackOnMessageChange(fromUserId, messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future userOpenedOtherMessage(
|
static Future userOpenedOtherMessage(
|
||||||
|
|
@ -351,7 +358,7 @@ class DbMessages extends CvModelBase {
|
||||||
where: "$messageId = ? AND $columnOtherUserId = ?",
|
where: "$messageId = ? AND $columnOtherUserId = ?",
|
||||||
whereArgs: [messageId, fromUserId],
|
whereArgs: [messageId, fromUserId],
|
||||||
);
|
);
|
||||||
globalCallBackOnMessageChange(fromUserId);
|
globalCallBackOnMessageChange(fromUserId, messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -374,6 +381,7 @@ class DbMessages extends CvModelBase {
|
||||||
List<dynamic> fromDb) async {
|
List<dynamic> fromDb) async {
|
||||||
try {
|
try {
|
||||||
List<DbMessage> parsedUsers = [];
|
List<DbMessage> parsedUsers = [];
|
||||||
|
final box = await getMediaStorage();
|
||||||
for (int i = 0; i < fromDb.length; i++) {
|
for (int i = 0; i < fromDb.length; i++) {
|
||||||
dynamic messageOpenedAt = fromDb[i][columnMessageOpenedAt];
|
dynamic messageOpenedAt = fromDb[i][columnMessageOpenedAt];
|
||||||
|
|
||||||
|
|
@ -397,7 +405,8 @@ class DbMessages extends CvModelBase {
|
||||||
if (messageOtherId != null) {
|
if (messageOtherId != null) {
|
||||||
if (content is MediaMessageContent) {
|
if (content is MediaMessageContent) {
|
||||||
// when the media was send from the user itself the content is null
|
// 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(
|
parsedUsers.add(
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,11 @@ Future sendTextMessage(Int64 target, String message) async {
|
||||||
DateTime messageSendAt = DateTime.now();
|
DateTime messageSendAt = DateTime.now();
|
||||||
|
|
||||||
int? messageId = await DbMessages.insertMyMessage(
|
int? messageId = await DbMessages.insertMyMessage(
|
||||||
target.toInt(), MessageKind.textMessage, content, messageSendAt);
|
target.toInt(),
|
||||||
|
MessageKind.textMessage,
|
||||||
|
content,
|
||||||
|
messageSendAt,
|
||||||
|
);
|
||||||
if (messageId == null) return;
|
if (messageId == null) return;
|
||||||
|
|
||||||
Message msg = Message(
|
Message msg = Message(
|
||||||
|
|
@ -264,13 +268,11 @@ Future sendImage(
|
||||||
}
|
}
|
||||||
|
|
||||||
// first step encrypt and store the encrypted image
|
// first step encrypt and store the encrypted image
|
||||||
for (SendImage task in tasks) {
|
await Future.wait(tasks.map((task) => task.encryptAndStore()));
|
||||||
await task.encryptAndStore();
|
|
||||||
}
|
|
||||||
|
|
||||||
// after the images are safely stored try do upload them one by one
|
// after the images are safely stored try do upload them one by one
|
||||||
for (SendImage task in tasks) {
|
for (SendImage task in tasks) {
|
||||||
await task.upload();
|
task.upload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,11 +334,6 @@ Future<Uint8List?> getDownloadedMedia(
|
||||||
return media;
|
return media;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> isMediaDownloaded(List<int> mediaToken) async {
|
|
||||||
final box = await getMediaStorage();
|
|
||||||
return box.containsKey("${mediaToken}_downloaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
Future initMediaStorage() async {
|
Future initMediaStorage() async {
|
||||||
final storage = getSecureStorage();
|
final storage = getSecureStorage();
|
||||||
var containsEncryptionKey =
|
var containsEncryptionKey =
|
||||||
|
|
|
||||||
|
|
@ -57,15 +57,15 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
|
||||||
final box = await getMediaStorage();
|
final box = await getMediaStorage();
|
||||||
|
|
||||||
String boxId = data.uploadToken.toString();
|
String boxId = data.uploadToken.toString();
|
||||||
|
int? messageId = box.get("${data.uploadToken}_messageId");
|
||||||
if (data.fin && data.data.isEmpty) {
|
if (data.fin && data.data.isEmpty) {
|
||||||
// media file was deleted by the server. remove the media from device
|
// media file was deleted by the server. remove the media from device
|
||||||
|
|
||||||
int? messageId = box.get("${data.uploadToken}_messageId");
|
|
||||||
if (messageId != null) {
|
if (messageId != null) {
|
||||||
int? fromUserId = await DbMessages.deleteMessageById(messageId);
|
int? fromUserId = await DbMessages.deleteMessageById(messageId);
|
||||||
box.delete(boxId);
|
box.delete(boxId);
|
||||||
if (fromUserId != null) {
|
if (fromUserId != null) {
|
||||||
globalCallBackOnMessageChange(fromUserId);
|
globalCallBackOnMessageChange(fromUserId, messageId);
|
||||||
}
|
}
|
||||||
box.delete("${data.uploadToken}_fromUserId");
|
box.delete("${data.uploadToken}_fromUserId");
|
||||||
box.delete("${data.uploadToken}_downloaded");
|
box.delete("${data.uploadToken}_downloaded");
|
||||||
|
|
@ -107,7 +107,7 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
box.delete(boxId);
|
box.delete(boxId);
|
||||||
await globalCallBackOnMessageChange(fromUserId);
|
await globalCallBackOnMessageChange(fromUserId, messageId);
|
||||||
globalCallBackOnDownloadChange(data.uploadToken, false);
|
globalCallBackOnDownloadChange(data.uploadToken, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,31 @@ class MessagesChangeProvider with ChangeNotifier, DiagnosticableTreeMixin {
|
||||||
Map<int, int> get changeCounter => _changeCounter;
|
Map<int, int> get changeCounter => _changeCounter;
|
||||||
Map<int, int> get flamesCounter => _flamesCounter;
|
Map<int, int> get flamesCounter => _flamesCounter;
|
||||||
|
|
||||||
Future updateLastMessageFor(int targetUserId) async {
|
Future updateLastMessageFor(int targetUserId, int? messageId) async {
|
||||||
DbMessage? last =
|
DbMessage? last =
|
||||||
await DbMessages.getLastMessagesForPreviewForUser(targetUserId);
|
await DbMessages.getLastMessagesForPreviewForUser(targetUserId);
|
||||||
if (last != null) {
|
if (last != null) {
|
||||||
_lastMessage[last.otherUserId] = last;
|
_lastMessage[last.otherUserId] = last;
|
||||||
}
|
}
|
||||||
flamesCounter[targetUserId] = await getFlamesForOtherUser(targetUserId);
|
flamesCounter[targetUserId] = await getFlamesForOtherUser(targetUserId);
|
||||||
notifyListeners();
|
// notifyListeners();
|
||||||
|
|
||||||
loadMessagesForUser(targetUserId, force: true);
|
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 {
|
Future loadMessagesForUser(int targetUserId, {bool force = false}) async {
|
||||||
|
|
|
||||||
|
|
@ -373,15 +373,16 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
||||||
icon: FaIcon(FontAwesomeIcons.solidPaperPlane),
|
icon: FaIcon(FontAwesomeIcons.solidPaperPlane),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (sendNextMediaToUserId != null) {
|
if (sendNextMediaToUserId != null) {
|
||||||
Navigator.popUntil(context, (route) => route.isFirst);
|
|
||||||
Uint8List? imageBytes = await getMergedImage();
|
Uint8List? imageBytes = await getMergedImage();
|
||||||
globalUpdateOfHomeViewPageIndex(1);
|
|
||||||
sendImage(
|
sendImage(
|
||||||
[Int64(sendNextMediaToUserId)],
|
[Int64(sendNextMediaToUserId)],
|
||||||
imageBytes!,
|
imageBytes!,
|
||||||
_isRealTwonly,
|
_isRealTwonly,
|
||||||
_maxShowTime,
|
_maxShowTime,
|
||||||
);
|
);
|
||||||
|
Navigator.popUntil(context, (route) => route.isFirst);
|
||||||
|
globalUpdateOfHomeViewPageIndex(1);
|
||||||
|
|
||||||
// send hier...
|
// send hier...
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ class _ShareImageView extends State<ShareImageView> {
|
||||||
List<Contact> _bestFriends = [];
|
List<Contact> _bestFriends = [];
|
||||||
int maxTotalMediaCounter = 0;
|
int maxTotalMediaCounter = 0;
|
||||||
Uint8List? imageBytes;
|
Uint8List? imageBytes;
|
||||||
|
bool sendingImage = false;
|
||||||
final HashSet<Int64> _selectedUserIds = HashSet<Int64>();
|
final HashSet<Int64> _selectedUserIds = HashSet<Int64>();
|
||||||
final TextEditingController searchUserName = TextEditingController();
|
final TextEditingController searchUserName = TextEditingController();
|
||||||
bool showRealTwonlyWarning = false;
|
bool showRealTwonlyWarning = false;
|
||||||
|
|
@ -188,7 +189,7 @@ class _ShareImageView extends State<ShareImageView> {
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
FilledButton.icon(
|
FilledButton.icon(
|
||||||
icon: imageBytes == null
|
icon: imageBytes == null || sendingImage
|
||||||
? SizedBox(
|
? SizedBox(
|
||||||
height: 12,
|
height: 12,
|
||||||
width: 12,
|
width: 12,
|
||||||
|
|
@ -202,14 +203,19 @@ class _ShareImageView extends State<ShareImageView> {
|
||||||
if (imageBytes == null || _selectedUserIds.isEmpty) {
|
if (imageBytes == null || _selectedUserIds.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sendImage(
|
setState(() {
|
||||||
|
sendingImage = true;
|
||||||
|
});
|
||||||
|
await sendImage(
|
||||||
_selectedUserIds.toList(),
|
_selectedUserIds.toList(),
|
||||||
imageBytes!,
|
imageBytes!,
|
||||||
widget.isRealTwonly,
|
widget.isRealTwonly,
|
||||||
widget.maxShowTime,
|
widget.maxShowTime,
|
||||||
);
|
);
|
||||||
Navigator.popUntil(context, (route) => route.isFirst);
|
if (context.mounted) {
|
||||||
globalUpdateOfHomeViewPageIndex(1);
|
Navigator.popUntil(context, (route) => route.isFirst);
|
||||||
|
globalUpdateOfHomeViewPageIndex(1);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
padding: WidgetStateProperty.all<EdgeInsets>(
|
padding: WidgetStateProperty.all<EdgeInsets>(
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
||||||
.watch<MessagesChangeProvider>()
|
.watch<MessagesChangeProvider>()
|
||||||
.allMessagesFromUser[user.userId.toInt()] ??
|
.allMessagesFromUser[user.userId.toInt()] ??
|
||||||
[];
|
[];
|
||||||
|
print(messages.length);
|
||||||
|
|
||||||
messages.where((x) => x.messageOpenedAt == null).forEach((message) {
|
messages.where((x) => x.messageOpenedAt == null).forEach((message) {
|
||||||
if (message.messageOtherId != null &&
|
if (message.messageOtherId != null &&
|
||||||
|
|
@ -219,6 +220,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
||||||
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) {
|
||||||
|
print(i);
|
||||||
bool lastMessageFromSameUser = false;
|
bool lastMessageFromSameUser = false;
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
lastMessageFromSameUser =
|
lastMessageFromSameUser =
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue