mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 14:48:41 +00:00
retransmition of images
This commit is contained in:
parent
be2d01a1e7
commit
2117ca3fc1
6 changed files with 80 additions and 56 deletions
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue