mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 14:48:41 +00:00
maybe fix for #180
This commit is contained in:
parent
95ad761898
commit
a57a8051ef
9 changed files with 109 additions and 63 deletions
|
|
@ -9,7 +9,6 @@ import 'package:twonly/src/database/twonly_database.dart';
|
|||
import 'package:twonly/src/database/tables/messages_table.dart';
|
||||
import 'package:twonly/src/model/json/message.dart';
|
||||
import 'package:twonly/src/model/json/userdata.dart';
|
||||
import 'package:twonly/src/model/protobuf/api/error.pb.dart';
|
||||
import 'package:twonly/src/providers/api/api_utils.dart';
|
||||
import 'package:twonly/src/providers/hive.dart';
|
||||
import 'package:twonly/src/services/notification_service.dart';
|
||||
|
|
@ -29,9 +28,12 @@ Future tryTransmitMessages() async {
|
|||
|
||||
Map<String, dynamic> failed = {};
|
||||
|
||||
for (String key in retransmit.keys) {
|
||||
// List<MapEntry<String, dynamic>> sortedList = retransmit.entries.toList()
|
||||
// ..sort((a, b) => int.parse(a.key).compareTo(int.parse(b.key)));
|
||||
|
||||
for (final element in retransmit.entries) {
|
||||
RetransmitMessage msg =
|
||||
RetransmitMessage.fromJson(jsonDecode(retransmit[key]));
|
||||
RetransmitMessage.fromJson(jsonDecode(element.value));
|
||||
|
||||
Result resp = await apiProvider.sendTextMessage(
|
||||
msg.userId,
|
||||
|
|
@ -49,7 +51,7 @@ Future tryTransmitMessages() async {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
failed[key] = retransmit[key];
|
||||
failed[element.key] = element.value;
|
||||
}
|
||||
}
|
||||
Box box = await getMediaStorage();
|
||||
|
|
@ -98,21 +100,49 @@ Future<Map<String, dynamic>> getAllMessagesForRetransmitting() async {
|
|||
Map<String, dynamic> retransmit = {};
|
||||
|
||||
if (retransmitJson != null) {
|
||||
retransmit = jsonDecode(retransmitJson);
|
||||
try {
|
||||
retransmit = jsonDecode(retransmitJson);
|
||||
} catch (e) {
|
||||
Logger("api.dart").shout("Could not decode the retransmit messages: $e");
|
||||
await box.delete("messages-to-retransmit");
|
||||
}
|
||||
}
|
||||
return retransmit;
|
||||
}
|
||||
|
||||
Future<Result> sendRetransmitMessage(
|
||||
String stateId, RetransmitMessage msg) async {
|
||||
Result resp =
|
||||
await apiProvider.sendTextMessage(msg.userId, msg.bytes, msg.pushData);
|
||||
|
||||
if (resp.isSuccess) {
|
||||
{
|
||||
var retransmit = await getAllMessagesForRetransmitting();
|
||||
retransmit.remove(stateId);
|
||||
Box box = await getMediaStorage();
|
||||
box.put("messages-to-retransmit", jsonEncode(retransmit));
|
||||
}
|
||||
if (msg.messageId != null) {
|
||||
await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
||||
msg.messageId!,
|
||||
MessagesCompanion(acknowledgeByServer: Value(true)),
|
||||
);
|
||||
}
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
// this functions ensures that the message is received by the server and in case of errors will try again later
|
||||
Future<Result> encryptAndSendMessage(
|
||||
Future<(String, RetransmitMessage)?> encryptMessage(
|
||||
int? messageId, int userId, MessageJson msg,
|
||||
{PushKind? pushKind}) async {
|
||||
return await lockSendingMessages.protect<Result>(() async {
|
||||
return await lockSendingMessages
|
||||
.protect<(String, RetransmitMessage)?>(() async {
|
||||
Uint8List? bytes = await SignalHelper.encryptMessage(msg, userId);
|
||||
|
||||
if (bytes == null) {
|
||||
Logger("api.dart").shout("Error encryption message!");
|
||||
return Result.error(ErrorCode.InternalError);
|
||||
return null;
|
||||
}
|
||||
|
||||
String stateId =
|
||||
|
|
@ -124,39 +154,36 @@ Future<Result> encryptAndSendMessage(
|
|||
pushData = await getPushData(userId, pushKind);
|
||||
}
|
||||
|
||||
RetransmitMessage encryptedMessage = RetransmitMessage(
|
||||
messageId: messageId,
|
||||
userId: userId,
|
||||
bytes: bytes,
|
||||
pushData: pushData,
|
||||
);
|
||||
|
||||
{
|
||||
var retransmit = await getAllMessagesForRetransmitting();
|
||||
|
||||
retransmit[stateId] = jsonEncode(RetransmitMessage(
|
||||
messageId: messageId,
|
||||
userId: userId,
|
||||
bytes: bytes,
|
||||
pushData: pushData,
|
||||
).toJson());
|
||||
retransmit[stateId] = jsonEncode(encryptedMessage.toJson());
|
||||
|
||||
box.put("messages-to-retransmit", jsonEncode(retransmit));
|
||||
}
|
||||
|
||||
Result resp = await apiProvider.sendTextMessage(userId, bytes, pushData);
|
||||
|
||||
if (resp.isSuccess) {
|
||||
{
|
||||
var retransmit = await getAllMessagesForRetransmitting();
|
||||
retransmit.remove(stateId);
|
||||
box.put("messages-to-retransmit", jsonEncode(retransmit));
|
||||
}
|
||||
if (messageId != null) {
|
||||
await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
||||
messageId,
|
||||
MessagesCompanion(acknowledgeByServer: Value(true)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return resp;
|
||||
return (stateId, encryptedMessage);
|
||||
});
|
||||
}
|
||||
|
||||
// encrypts and stores the message and then sends it in the background
|
||||
Future encryptAndSendMessageAsync(int? messageId, int userId, MessageJson msg,
|
||||
{PushKind? pushKind}) async {
|
||||
(String, RetransmitMessage)? stateData =
|
||||
await encryptMessage(messageId, userId, msg);
|
||||
if (stateData != null) {
|
||||
final (stateId, message) = stateData;
|
||||
sendRetransmitMessage(stateId, message);
|
||||
}
|
||||
}
|
||||
|
||||
Future sendTextMessage(
|
||||
int target, TextMessageContent content, PushKind? pushKind) async {
|
||||
DateTime messageSendAt = DateTime.now();
|
||||
|
|
@ -184,13 +211,13 @@ Future sendTextMessage(
|
|||
timestamp: messageSendAt,
|
||||
);
|
||||
|
||||
encryptAndSendMessage(messageId, target, msg, pushKind: pushKind);
|
||||
await encryptAndSendMessageAsync(messageId, target, msg, pushKind: pushKind);
|
||||
}
|
||||
|
||||
Future notifyContactAboutOpeningMessage(
|
||||
int fromUserId, List<int> messageOtherIds) async {
|
||||
for (final messageOtherId in messageOtherIds) {
|
||||
await encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
fromUserId,
|
||||
MessageJson(
|
||||
|
|
@ -216,7 +243,7 @@ Future notifyContactsAboutProfileChange() async {
|
|||
if (contact.myAvatarCounter < user.avatarCounter!) {
|
||||
twonlyDatabase.contactsDao.updateContact(contact.userId,
|
||||
ContactsCompanion(myAvatarCounter: Value(user.avatarCounter!)));
|
||||
encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
contact.userId,
|
||||
MessageJson(
|
||||
|
|
|
|||
|
|
@ -451,7 +451,7 @@ Future<bool> handleNotifyReceiver(MediaUpload media) async {
|
|||
);
|
||||
|
||||
// Ensures the retransmit of the message
|
||||
await encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
messageId,
|
||||
message.contactId,
|
||||
MessageJson(
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ Future<client.Response> handleNewMessage(int fromUserId, Uint8List body) async {
|
|||
}
|
||||
}
|
||||
|
||||
encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
message.messageId!,
|
||||
fromUserId,
|
||||
MessageJson(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Future syncFlameCounters() async {
|
|||
// only sync when flame counter is higher than three days
|
||||
if (flameCounter < 1 && bestFriend.userId != contact.userId) continue;
|
||||
|
||||
encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
contact.userId,
|
||||
my.MessageJson(
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ Future setupNotificationWithUsers({bool force = false}) async {
|
|||
}
|
||||
|
||||
Future sendNewPushKey(int userId, PushKeyMeta pushKey) async {
|
||||
await encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
userId,
|
||||
my.MessageJson(
|
||||
|
|
|
|||
|
|
@ -89,6 +89,17 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
|||
Map<int, List<Message>> tmpEmojiReactionsToMessageId = {};
|
||||
|
||||
List<int> openedMessageOtherIds = [];
|
||||
|
||||
Map<int, int> messageOtherMessageIdToMyMessageId = {};
|
||||
|
||||
/// there is probably a better way...
|
||||
for (Message msg in msgs) {
|
||||
if (msg.messageOtherId != null) {
|
||||
messageOtherMessageIdToMyMessageId[msg.messageOtherId!] =
|
||||
msg.messageId;
|
||||
}
|
||||
}
|
||||
|
||||
for (Message msg in msgs) {
|
||||
if (msg.kind == MessageKind.textMessage &&
|
||||
msg.messageOtherId != null &&
|
||||
|
|
@ -96,8 +107,9 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
|||
openedMessageOtherIds.add(msg.messageOtherId!);
|
||||
}
|
||||
|
||||
int? responseId =
|
||||
msg.responseToMessageId ?? msg.responseToOtherMessageId;
|
||||
int? responseId = msg.responseToMessageId ??
|
||||
messageOtherMessageIdToMyMessageId[msg.responseToOtherMessageId];
|
||||
|
||||
if (responseId != null) {
|
||||
bool added = false;
|
||||
MessageContent? content =
|
||||
|
|
@ -243,9 +255,11 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
|||
children: [
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: messages.length,
|
||||
itemCount: messages.length + 1,
|
||||
reverse: true,
|
||||
itemExtentBuilder: (index, dimensions) {
|
||||
if (index == 0) return 10; // empty padding
|
||||
index -= 1;
|
||||
double size = 44;
|
||||
if (messages[index].kind == MessageKind.textMessage) {
|
||||
MessageContent? content = MessageContent.fromJson(
|
||||
|
|
@ -277,6 +291,10 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
|
|||
return size;
|
||||
},
|
||||
itemBuilder: (context, i) {
|
||||
if (i == 0) {
|
||||
return Container(); // just a padding
|
||||
}
|
||||
i -= 1;
|
||||
return ChatListEntry(
|
||||
key: Key(messages[i].messageId.toString()),
|
||||
messages[i],
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ class ChatListEntry extends StatelessWidget {
|
|||
return;
|
||||
}
|
||||
if (await received.existsMediaFile(message.messageId, "png")) {
|
||||
encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
contact.userId,
|
||||
MessageJson(
|
||||
|
|
@ -291,22 +291,22 @@ class ChatListEntry extends StatelessWidget {
|
|||
crossAxisAlignment:
|
||||
right ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||
children: [
|
||||
SlidingResponse(
|
||||
child: child,
|
||||
onResponseTriggered: () {
|
||||
onResponseTriggered(message);
|
||||
},
|
||||
),
|
||||
Positioned(
|
||||
bottom: 5,
|
||||
left: 5,
|
||||
right: 5,
|
||||
child: getReactionRow(),
|
||||
),
|
||||
],
|
||||
SlidingResponse(
|
||||
child: Stack(
|
||||
alignment: right ? Alignment.centerRight : Alignment.centerLeft,
|
||||
children: [
|
||||
child,
|
||||
Positioned(
|
||||
bottom: 5,
|
||||
left: 5,
|
||||
right: 5,
|
||||
child: getReactionRow(),
|
||||
),
|
||||
],
|
||||
),
|
||||
onResponseTriggered: () {
|
||||
onResponseTriggered(message);
|
||||
},
|
||||
),
|
||||
getTextResponseColumns(context, !right)
|
||||
],
|
||||
|
|
|
|||
|
|
@ -132,8 +132,8 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
|
||||
Future loadCurrentMediaFile({bool showTwonly = false}) async {
|
||||
if (!isMounted) return;
|
||||
await _noScreenshot.screenshotOff();
|
||||
if (!context.mounted || allMediaFiles.isEmpty) return nextMediaOrExit();
|
||||
await _noScreenshot.screenshotOff();
|
||||
|
||||
setState(() {
|
||||
videoController = null;
|
||||
|
|
@ -230,6 +230,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
imageBytes = await getImageBytes(current.messageId);
|
||||
|
||||
if ((imageBytes == null && !content.isVideo) ||
|
||||
|
|
@ -300,7 +301,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
allMediaFiles.first.messageId,
|
||||
MessagesCompanion(mediaStored: Value(true)),
|
||||
);
|
||||
encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
widget.contact.userId,
|
||||
MessageJson(
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
|
|||
if (await SignalHelper.addNewContact(res.value.userdata)) {
|
||||
// before notifying the other party, add
|
||||
await setupNotificationWithUsers();
|
||||
encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
res.value.userdata.userId.toInt(),
|
||||
MessageJson(
|
||||
|
|
@ -267,7 +267,7 @@ class _ContactsListViewState extends State<ContactsListView> {
|
|||
onPressed: () async {
|
||||
await twonlyDatabase.contactsDao
|
||||
.deleteContactByUserId(contact.userId);
|
||||
encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
contact.userId,
|
||||
MessageJson(
|
||||
|
|
@ -285,7 +285,7 @@ class _ContactsListViewState extends State<ContactsListView> {
|
|||
final update = ContactsCompanion(accepted: Value(true));
|
||||
await twonlyDatabase.contactsDao
|
||||
.updateContact(contact.userId, update);
|
||||
await encryptAndSendMessage(
|
||||
await encryptAndSendMessageAsync(
|
||||
null,
|
||||
contact.userId,
|
||||
MessageJson(
|
||||
|
|
|
|||
Loading…
Reference in a new issue