retransmition of images

This commit is contained in:
otsmr 2025-01-31 23:42:32 +01:00
parent be2d01a1e7
commit 2117ca3fc1
6 changed files with 80 additions and 56 deletions

View file

@ -154,7 +154,6 @@ class DbMessages extends CvModelBase {
columnOtherUserId: userIdFrom, columnOtherUserId: userIdFrom,
columnSendOrReceivedAt: DateTime.now().toIso8601String() columnSendOrReceivedAt: DateTime.now().toIso8601String()
}); });
print("insertl");
globalCallBackOnMessageChange(userIdFrom); globalCallBackOnMessageChange(userIdFrom);
return messageId; return messageId;
} catch (e) { } catch (e) {

View file

@ -16,8 +16,6 @@ import 'package:twonly/src/utils/misc.dart';
// ignore: library_prefixes // ignore: library_prefixes
import 'package:twonly/src/utils/signal.dart' as SignalHelper; import 'package:twonly/src/utils/signal.dart' as SignalHelper;
// this functions ensures that the message is received by the server and in case of errors will try again later
Future tryTransmitMessages() async { Future tryTransmitMessages() async {
List<DbMessage> retransmit = List<DbMessage> retransmit =
await DbMessages.getAllMessagesForRetransmitting(); await DbMessages.getAllMessagesForRetransmitting();
@ -28,22 +26,28 @@ Future tryTransmitMessages() async {
for (int i = 0; i < retransmit.length; i++) { for (int i = 0; i < retransmit.length; i++) {
int msgId = retransmit[i].messageId; int msgId = retransmit[i].messageId;
debugPrint("msgId=$msgId"); debugPrint("msgId=$msgId");
Uint8List? bytes = box.get("retransmit-$msgId");
debugPrint("bytes == null =${bytes == null}"); Uint8List? bytes = box.get("retransmit-$msgId-textmessage");
if (bytes != null) { if (bytes != null) {
Result resp = await apiProvider.sendTextMessage( Result resp = await apiProvider.sendTextMessage(
Int64(retransmit[i].otherUserId), bytes); Int64(retransmit[i].otherUserId), bytes);
if (resp.isSuccess) { if (resp.isSuccess) {
DbMessages.acknowledgeMessageByServer(msgId); DbMessages.acknowledgeMessageByServer(msgId);
box.delete("retransmit-$msgId"); box.delete("retransmit-$msgId-textmessage");
} else { } else {
// in case of error do nothing. As the message is not removed the app will try again when relaunched // in case of error do nothing. As the message is not removed the app will try again when relaunched
} }
} }
Uint8List? encryptedMedia = await box.get("retransmit-$msgId-media");
if (encryptedMedia != null) {
uploadMediaFile(msgId, Int64(retransmit[i].otherUserId), encryptedMedia);
}
} }
} }
// this functions ensures that the message is received by the server and in case of errors will try again later
Future<Result> encryptAndSendMessage(Int64 userId, Message msg) async { Future<Result> encryptAndSendMessage(Int64 userId, Message msg) async {
Uint8List? bytes = await SignalHelper.encryptMessage(msg, userId); Uint8List? bytes = await SignalHelper.encryptMessage(msg, userId);
@ -55,7 +59,7 @@ Future<Result> encryptAndSendMessage(Int64 userId, Message msg) async {
Box box = await getMediaStorage(); Box box = await getMediaStorage();
if (msg.messageId != null) { if (msg.messageId != null) {
debugPrint("putting=${msg.messageId}"); debugPrint("putting=${msg.messageId}");
box.put("retransmit-${msg.messageId}", bytes); box.put("retransmit-${msg.messageId}-textmessage", bytes);
} }
Result resp = await apiProvider.sendTextMessage(userId, bytes); Result resp = await apiProvider.sendTextMessage(userId, bytes);
@ -63,7 +67,7 @@ Future<Result> encryptAndSendMessage(Int64 userId, Message msg) async {
if (resp.isSuccess) { if (resp.isSuccess) {
if (msg.messageId != null) { if (msg.messageId != null) {
DbMessages.acknowledgeMessageByServer(msg.messageId!); DbMessages.acknowledgeMessageByServer(msg.messageId!);
box.delete("retransmit-${msg.messageId}"); box.delete("retransmit-${msg.messageId}-textmessage");
} }
} }
@ -88,7 +92,53 @@ Future sendTextMessage(Int64 target, String message) async {
encryptAndSendMessage(target, msg); encryptAndSendMessage(target, msg);
} }
Future sendImageToSingleTarget(Int64 target, Uint8List imageBytes) async { // this will send the media file and ensures retransmission when errors occur
Future uploadMediaFile(
int messageId, Int64 target, Uint8List encryptedMedia) async {
Box box = await getMediaStorage();
if ((await box.get("retransmit-$messageId-media") == null)) {
await box.put("retransmit-$messageId-media", encryptedMedia);
}
List<int>? uploadToken = await box.get("retransmit-$messageId-uploadtoken");
if (uploadToken == null) {
Result res = await apiProvider.getUploadToken();
if (res.isError || !res.value.hasUploadtoken()) {
Logger("api.dart").shout("Error getting upload token!");
return; // will be retried on next app start
}
uploadToken = res.value.uploadtoken;
await box.put("retransmit-$messageId-uploadtoken", uploadToken);
}
if (uploadToken == null) return;
// TODO: fragmented upload...
if (!await apiProvider.uploadData(uploadToken, encryptedMedia, 0)) {
Logger("api.dart").shout("error while uploading media");
return;
}
box.delete("retransmit-$messageId-media");
box.delete("retransmit-$messageId-uploadtoken");
// Ensures the retransmit of the message
await encryptAndSendMessage(
target,
Message(
kind: MessageKind.image,
messageId: messageId,
content: MessageContent(text: null, downloadToken: uploadToken),
timestamp: DateTime.now(),
),
);
}
Future encryptAndUploadMediaFile(Int64 target, Uint8List imageBytes) async {
int? messageId = int? messageId =
await DbMessages.insertMyMessage(target.toInt(), MessageKind.image); await DbMessages.insertMyMessage(target.toInt(), MessageKind.image);
if (messageId == null) return; if (messageId == null) return;
@ -96,38 +146,11 @@ Future sendImageToSingleTarget(Int64 target, Uint8List imageBytes) async {
Uint8List? encryptBytes = await SignalHelper.encryptBytes(imageBytes, target); Uint8List? encryptBytes = await SignalHelper.encryptBytes(imageBytes, target);
if (encryptBytes == null) { if (encryptBytes == null) {
await DbMessages.deleteMessageById(messageId); await DbMessages.deleteMessageById(messageId);
Logger("api.dart").shout("Error encrypting image! Deleting image."); Logger("api.dart").shout("Error encrypting media! Deleting media.");
return; return;
} }
Result res = await apiProvider.getUploadToken(); await uploadMediaFile(messageId, target, encryptBytes);
if (res.isError || !res.value.hasUploadtoken()) {
print("store encryptBytes in box to retransmit without an upload token");
Logger("api.dart").shout("Error getting upload token!");
return null;
}
List<int> uploadToken = res.value.uploadtoken;
MessageContent content =
MessageContent(text: null, downloadToken: uploadToken);
print("fragmentate the data");
if (!await apiProvider.uploadData(uploadToken, encryptBytes, 0)) {
Logger("api.dart").shout("error while uploading image");
return;
}
Message msg = Message(
kind: MessageKind.image,
messageId: messageId,
content: content,
timestamp: DateTime.now(),
);
await encryptAndSendMessage(target, msg);
} }
Future sendImage(List<Int64> userIds, String imagePath) async { Future sendImage(List<Int64> userIds, String imagePath) async {
@ -142,7 +165,7 @@ Future sendImage(List<Int64> userIds, String imagePath) async {
} }
for (int i = 0; i < userIds.length; i++) { for (int i = 0; i < userIds.length; i++) {
sendImageToSingleTarget(userIds[i], imageBytes); encryptAndUploadMediaFile(userIds[i], imageBytes);
} }
} }
@ -163,7 +186,7 @@ Future tryDownloadMedia(List<int> mediaToken, {bool force = false}) async {
if (media != null && media.isNotEmpty) { if (media != null && media.isNotEmpty) {
offset = media.length; offset = media.length;
} }
//globalCallBackOnDownloadChange(mediaToken, true); globalCallBackOnDownloadChange(mediaToken, true);
apiProvider.triggerDownload(mediaToken, offset); apiProvider.triggerDownload(mediaToken, offset);
} }

View file

@ -73,7 +73,6 @@ Future<client.Response> handleDownloadData(DownloadData data) async {
SignalHelper.getSignalStore(); SignalHelper.getSignalStore();
int? fromUserId = box.get("${data.uploadToken}_fromUserId"); int? fromUserId = box.get("${data.uploadToken}_fromUserId");
if (fromUserId != null) { if (fromUserId != null) {
print(fromUserId);
Uint8List? rawBytes = Uint8List? rawBytes =
await SignalHelper.decryptBytes(downloadedBytes, Int64(fromUserId)); await SignalHelper.decryptBytes(downloadedBytes, Int64(fromUserId));

View file

@ -15,7 +15,6 @@ class ConnectSignedPreKeyStore extends SignedPreKeyStore {
return store; return store;
} }
final storeHashMap = json.decode(storeSerialized); final storeHashMap = json.decode(storeSerialized);
print(storeHashMap);
for (final item in storeHashMap) { for (final item in storeHashMap) {
store[item[0]] = base64Decode(item[1]); store[item[0]] = base64Decode(item[1]);
} }

View file

@ -7,6 +7,7 @@ import 'package:twonly/src/model/contacts_model.dart';
import 'package:twonly/src/model/json/message.dart'; import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/model/messages_model.dart'; import 'package:twonly/src/model/messages_model.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/api.dart';
import 'package:twonly/src/providers/download_change_provider.dart';
import 'package:twonly/src/providers/messages_change_provider.dart'; import 'package:twonly/src/providers/messages_change_provider.dart';
import 'package:twonly/src/views/media_viewer_view.dart'; import 'package:twonly/src/views/media_viewer_view.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -24,13 +25,13 @@ class ChatListEntry extends StatelessWidget {
MessageSendState state = message.getSendState(); MessageSendState state = message.getSendState();
bool isDownloading = false; bool isDownloading = false;
// if (message.messageContent != null && if (message.messageContent != null &&
// message.messageContent!.downloadToken != null) { message.messageContent!.downloadToken != null) {
// isDownloading = context isDownloading = context
// .watch<DownloadChangeProvider>() .watch<DownloadChangeProvider>()
// .currentlyDownloading .currentlyDownloading
// .contains(message.messageContent!.downloadToken!); .contains(message.messageContent!.downloadToken!.toString());
// } }
Widget child = Container(); Widget child = Container();

View file

@ -7,6 +7,7 @@ import 'package:twonly/src/model/contacts_model.dart';
import 'package:twonly/src/model/messages_model.dart'; import 'package:twonly/src/model/messages_model.dart';
import 'package:twonly/src/providers/api/api.dart'; import 'package:twonly/src/providers/api/api.dart';
import 'package:twonly/src/providers/contacts_change_provider.dart'; import 'package:twonly/src/providers/contacts_change_provider.dart';
import 'package:twonly/src/providers/download_change_provider.dart';
import 'package:twonly/src/providers/messages_change_provider.dart'; import 'package:twonly/src/providers/messages_change_provider.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/chat_item_details_view.dart'; import 'package:twonly/src/views/chat_item_details_view.dart';
@ -150,13 +151,15 @@ class _UserListItem extends State<UserListItem> {
MessageSendState state = widget.lastMessage.getSendState(); MessageSendState state = widget.lastMessage.getSendState();
bool isDownloading = false; bool isDownloading = false;
// if (widget.lastMessage.messageContent != null &&
// widget.lastMessage.messageContent!.downloadToken != null) { if (widget.lastMessage.messageContent != null &&
// isDownloading = context widget.lastMessage.messageContent!.downloadToken != null) {
// .watch<DownloadChangeProvider>() isDownloading = context
// .currentlyDownloading .watch<DownloadChangeProvider>()
// .contains(widget.lastMessage.messageContent!.downloadToken!); .currentlyDownloading
// } .contains(
widget.lastMessage.messageContent!.downloadToken!.toString());
}
return UserContextMenu( return UserContextMenu(
user: widget.user, user: widget.user,