|
@ -1,86 +1,122 @@ |
|
|
import 'dart:convert'; |
|
|
import 'dart:convert'; |
|
|
import 'dart:io'; |
|
|
import 'dart:io'; |
|
|
|
|
|
|
|
|
import 'package:Envelope/models/text_messages.dart'; |
|
|
|
|
|
|
|
|
import 'package:Envelope/models/messages.dart'; |
|
|
|
|
|
import 'package:Envelope/utils/storage/write_file.dart'; |
|
|
import 'package:http/http.dart' as http; |
|
|
import 'package:http/http.dart' as http; |
|
|
import 'package:sqflite/sqflite.dart'; |
|
|
import 'package:sqflite/sqflite.dart'; |
|
|
import 'package:uuid/uuid.dart'; |
|
|
import 'package:uuid/uuid.dart'; |
|
|
|
|
|
|
|
|
|
|
|
import '/models/image_message.dart'; |
|
|
|
|
|
import '/models/text_messages.dart'; |
|
|
import '/models/conversation_users.dart'; |
|
|
import '/models/conversation_users.dart'; |
|
|
import '/models/conversations.dart'; |
|
|
import '/models/conversations.dart'; |
|
|
import '/models/messages.dart'; |
|
|
|
|
|
import '/models/my_profile.dart'; |
|
|
import '/models/my_profile.dart'; |
|
|
import '/utils/storage/database.dart'; |
|
|
import '/utils/storage/database.dart'; |
|
|
import '/utils/storage/session_cookie.dart'; |
|
|
import '/utils/storage/session_cookie.dart'; |
|
|
|
|
|
|
|
|
Future<void> sendMessage(Conversation conversation, { String? data, List<File>? files }) async { |
|
|
|
|
|
|
|
|
Future<void> sendMessage(Conversation conversation, { |
|
|
|
|
|
String? data, |
|
|
|
|
|
List<File> files = const [] |
|
|
|
|
|
}) async { |
|
|
|
|
|
|
|
|
MyProfile profile = await MyProfile.getProfile(); |
|
|
MyProfile profile = await MyProfile.getProfile(); |
|
|
|
|
|
|
|
|
var uuid = const Uuid(); |
|
|
var uuid = const Uuid(); |
|
|
final String messageId = uuid.v4(); |
|
|
|
|
|
|
|
|
|
|
|
ConversationUser currentUser = await getConversationUser(conversation, profile.id); |
|
|
ConversationUser currentUser = await getConversationUser(conversation, profile.id); |
|
|
|
|
|
|
|
|
List<Map<String, dynamic>> messagesToAdd = []; |
|
|
|
|
|
|
|
|
List<Message> messages = []; |
|
|
|
|
|
List<Map<String, dynamic>> messagesToSend = []; |
|
|
|
|
|
|
|
|
|
|
|
final db = await getDatabaseConnection(); |
|
|
|
|
|
|
|
|
if (data != null) { |
|
|
if (data != null) { |
|
|
messagesToAdd.add({ 'text': data }); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
TextMessage message = TextMessage( |
|
|
|
|
|
id: uuid.v4(), |
|
|
|
|
|
symmetricKey: '', |
|
|
|
|
|
userSymmetricKey: '', |
|
|
|
|
|
senderId: currentUser.userId, |
|
|
|
|
|
senderUsername: profile.username, |
|
|
|
|
|
associationKey: currentUser.associationKey, |
|
|
|
|
|
createdAt: DateTime.now().toIso8601String(), |
|
|
|
|
|
failedToSend: false, |
|
|
|
|
|
text: data, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
messages.add(message); |
|
|
|
|
|
messagesToSend.add(await message.payloadJson( |
|
|
|
|
|
conversation, |
|
|
|
|
|
)); |
|
|
|
|
|
|
|
|
|
|
|
await db.insert( |
|
|
|
|
|
'messages', |
|
|
|
|
|
message.toMap(), |
|
|
|
|
|
conflictAlgorithm: ConflictAlgorithm.replace, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
if (files != null && files.isNotEmpty) { |
|
|
|
|
|
for (File file in files) { |
|
|
|
|
|
messagesToAdd.add({ 'file': file }); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var message = TextMessage( |
|
|
|
|
|
id: messageId, |
|
|
|
|
|
symmetricKey: '', |
|
|
|
|
|
userSymmetricKey: '', |
|
|
|
|
|
senderId: currentUser.userId, |
|
|
|
|
|
senderUsername: profile.username, |
|
|
|
|
|
text: data!, |
|
|
|
|
|
associationKey: currentUser.associationKey, |
|
|
|
|
|
createdAt: DateTime.now().toIso8601String(), |
|
|
|
|
|
failedToSend: false, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
for (File file in files) { |
|
|
|
|
|
|
|
|
final db = await getDatabaseConnection(); |
|
|
|
|
|
|
|
|
String messageId = uuid.v4(); |
|
|
|
|
|
|
|
|
await db.insert( |
|
|
|
|
|
'messages', |
|
|
|
|
|
message.toMap(), |
|
|
|
|
|
conflictAlgorithm: ConflictAlgorithm.replace, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
File writtenFile = await writeImage( |
|
|
|
|
|
messageId, |
|
|
|
|
|
file.readAsBytesSync(), |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
ImageMessage message = ImageMessage( |
|
|
|
|
|
id: messageId, |
|
|
|
|
|
symmetricKey: '', |
|
|
|
|
|
userSymmetricKey: '', |
|
|
|
|
|
senderId: currentUser.userId, |
|
|
|
|
|
senderUsername: profile.username, |
|
|
|
|
|
associationKey: currentUser.associationKey, |
|
|
|
|
|
createdAt: DateTime.now().toIso8601String(), |
|
|
|
|
|
failedToSend: false, |
|
|
|
|
|
file: writtenFile, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
messages.add(message); |
|
|
|
|
|
messagesToSend.add(await message.payloadJson( |
|
|
|
|
|
conversation, |
|
|
|
|
|
)); |
|
|
|
|
|
|
|
|
|
|
|
await db.insert( |
|
|
|
|
|
'messages', |
|
|
|
|
|
message.toMap(), |
|
|
|
|
|
conflictAlgorithm: ConflictAlgorithm.replace, |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
String sessionCookie = await getSessionCookie(); |
|
|
String sessionCookie = await getSessionCookie(); |
|
|
|
|
|
|
|
|
message.payloadJson(conversation, messageId) |
|
|
|
|
|
.then((messageJson) async { |
|
|
|
|
|
return http.post( |
|
|
|
|
|
await MyProfile.getServerUrl('api/v1/auth/message'), |
|
|
|
|
|
headers: <String, String>{ |
|
|
|
|
|
'Content-Type': 'application/json; charset=UTF-8', |
|
|
|
|
|
'cookie': sessionCookie, |
|
|
|
|
|
}, |
|
|
|
|
|
body: messageJson, |
|
|
|
|
|
); |
|
|
|
|
|
}) |
|
|
|
|
|
.then((resp) { |
|
|
|
|
|
if (resp.statusCode != 200) { |
|
|
|
|
|
throw Exception('Unable to send message'); |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
.catchError((exception) { |
|
|
|
|
|
message.failedToSend = true; |
|
|
|
|
|
db.update( |
|
|
|
|
|
'messages', |
|
|
|
|
|
message.toMap(), |
|
|
|
|
|
where: 'id = ?', |
|
|
|
|
|
whereArgs: [message.id], |
|
|
|
|
|
); |
|
|
|
|
|
throw exception; |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
return http.post( |
|
|
|
|
|
await MyProfile.getServerUrl('api/v1/auth/message'), |
|
|
|
|
|
headers: <String, String>{ |
|
|
|
|
|
'Content-Type': 'application/json; charset=UTF-8', |
|
|
|
|
|
'cookie': sessionCookie, |
|
|
|
|
|
}, |
|
|
|
|
|
body: jsonEncode(messagesToSend), |
|
|
|
|
|
) |
|
|
|
|
|
.then((resp) { |
|
|
|
|
|
if (resp.statusCode != 200) { |
|
|
|
|
|
throw Exception('Unable to send message'); |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
.catchError((exception) { |
|
|
|
|
|
for (Message message in messages) { |
|
|
|
|
|
message.failedToSend = true; |
|
|
|
|
|
db.update( |
|
|
|
|
|
'messages', |
|
|
|
|
|
message.toMap(), |
|
|
|
|
|
where: 'id = ?', |
|
|
|
|
|
whereArgs: [message.id], |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
throw exception; |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<void> updateMessageThread(Conversation conversation, {MyProfile? profile}) async { |
|
|
Future<void> updateMessageThread(Conversation conversation, {MyProfile? profile}) async { |
|
@ -103,10 +139,17 @@ Future<void> updateMessageThread(Conversation conversation, {MyProfile? profile} |
|
|
final db = await getDatabaseConnection(); |
|
|
final db = await getDatabaseConnection(); |
|
|
|
|
|
|
|
|
for (var i = 0; i < messageThreadJson.length; i++) { |
|
|
for (var i = 0; i < messageThreadJson.length; i++) { |
|
|
var message = TextMessage.fromJson( |
|
|
|
|
|
messageThreadJson[i] as Map<String, dynamic>, |
|
|
|
|
|
|
|
|
var messageJson = messageThreadJson[i] as Map<String, dynamic>; |
|
|
|
|
|
|
|
|
|
|
|
var message = messageJson['message_data']['attachment_id'] != null ? |
|
|
|
|
|
await ImageMessage.fromJson( |
|
|
|
|
|
messageJson, |
|
|
profile.privateKey!, |
|
|
profile.privateKey!, |
|
|
); |
|
|
|
|
|
|
|
|
) : |
|
|
|
|
|
TextMessage.fromJson( |
|
|
|
|
|
messageJson, |
|
|
|
|
|
profile.privateKey!, |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
ConversationUser messageUser = await getConversationUser(conversation, message.senderId); |
|
|
ConversationUser messageUser = await getConversationUser(conversation, message.senderId); |
|
|
message.senderUsername = messageUser.username; |
|
|
message.senderUsername = messageUser.username; |
|
|