diff --git a/lib/cwtch/cwtch.dart b/lib/cwtch/cwtch.dart index c7efdbf3..cf42d0e0 100644 --- a/lib/cwtch/cwtch.dart +++ b/lib/cwtch/cwtch.dart @@ -29,36 +29,35 @@ abstract class Cwtch { void SendAppEvent(String jsonEvent); // ignore: non_constant_identifier_names - void AcceptContact(String profileOnion, String contactHandle); + void AcceptContact(String profileOnion, int contactHandle); // ignore: non_constant_identifier_names - void BlockContact(String profileOnion, String contactHandle); + void BlockContact(String profileOnion, int contactHandle); // ignore: non_constant_identifier_names - Future GetMessage(String profile, String handle, int index); + Future GetMessage(String profile, int handle, int index); // ignore: non_constant_identifier_names - Future GetMessageByContentHash(String profile, String handle, String contentHash); - // ignore: non_constant_identifier_names - void UpdateMessageFlags(String profile, String handle, int index, int flags); - // ignore: non_constant_identifier_names - void SendMessage(String profile, String handle, String message); - // ignore: non_constant_identifier_names - void SendInvitation(String profile, String handle, String target); + Future GetMessageByContentHash(String profile, int handle, String contentHash); // ignore: non_constant_identifier_names - void ShareFile(String profile, String handle, String filepath); + void SendMessage(String profile, int handle, String message); // ignore: non_constant_identifier_names - void DownloadFile(String profile, String handle, String filepath, String manifestpath, String filekey); + void SendInvitation(String profile, int handle, int target); + // ignore: non_constant_identifier_names - void CreateDownloadableFile(String profile, String handle, String filenameSuggestion, String filekey); + void ShareFile(String profile, int handle, String filepath); + // ignore: non_constant_identifier_names + void DownloadFile(String profile, int handle, String filepath, String manifestpath, String filekey); + // ignore: non_constant_identifier_names + void CreateDownloadableFile(String profile, int handle, String filenameSuggestion, String filekey); // ignore: non_constant_identifier_names void CheckDownloadStatus(String profile, String fileKey); // ignore: non_constant_identifier_names - void VerifyOrResumeDownload(String profile, String handle, String filekey); + void VerifyOrResumeDownload(String profile, int handle, String filekey); // ignore: non_constant_identifier_names - void ArchiveConversation(String profile, String handle); + void ArchiveConversation(String profile, int handle); // ignore: non_constant_identifier_names - void DeleteContact(String profile, String handle); + void DeleteContact(String profile, int handle); // ignore: non_constant_identifier_names void CreateGroup(String profile, String server, String groupName); @@ -66,13 +65,11 @@ abstract class Cwtch { // ignore: non_constant_identifier_names void ImportBundle(String profile, String bundle); // ignore: non_constant_identifier_names - void SetGroupAttribute(String profile, String groupHandle, String key, String value); - // ignore: non_constant_identifier_names - void RejectInvite(String profileOnion, String groupHandle); + void RejectInvite(String profileOnion, int groupHandle); // ignore: non_constant_identifier_names void SetProfileAttribute(String profile, String key, String val); // ignore: non_constant_identifier_names - void SetContactAttribute(String profile, String contact, String key, String val); + void SetConversationAttribute(String profile, int contact, String key, String val); // ignore: non_constant_identifier_names void LoadServers(String password); diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index 7f16ab49..5a3f9b6a 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -34,6 +34,7 @@ class CwtchNotifier { } void handleMessage(String type, dynamic data) { + EnvironmentConfig.debugLog("NewEvent $type $data"); switch (type) { case "CwtchStarted": appState.SetCwtchInit(); @@ -42,12 +43,15 @@ class CwtchNotifier { appState.SetAppError(data["Error"]); break; case "NewPeer": + EnvironmentConfig.debugLog("NewPeer $data"); // if tag != v1-defaultPassword then it is either encrypted OR it is an unencrypted account created during pre-beta... profileCN.add(data["Identity"], data["name"], data["picture"], data["ContactsJson"], data["ServerList"], data["Online"] == "true", data["tag"] != "v1-defaultPassword"); break; - case "PeerCreated": + case "ContactCreated": + EnvironmentConfig.debugLog("NewServer $data"); profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState( data["ProfileOnion"], + data["ConversationID"], data["RemotePeer"], nickname: data["nick"], status: data["status"], @@ -88,7 +92,7 @@ class CwtchNotifier { status = serverInfoState.status; } if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"]) == null) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(data["ProfileOnion"], data["GroupID"], + profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(data["ProfileOnion"], data["ConversationID"], data["GroupID"], authorization: ContactAuthorization.approved, imagePath: data["PicturePath"], nickname: data["GroupName"], @@ -111,13 +115,13 @@ class CwtchNotifier { } break; case "DeleteContact": - profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["RemotePeer"]); + profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["ConversationID"]); break; case "DeleteGroup": - profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["GroupID"]); + profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["ConversationID"]); break; case "PeerStateChange": - ContactInfoState? contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"]); + ContactInfoState? contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]); if (contact != null) { if (data["ConnectionState"] != null) { contact.status = data["ConnectionState"]; @@ -131,19 +135,20 @@ class CwtchNotifier { break; case "NewMessageFromPeer": notificationManager.notify("New Message From Peer!"); - if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != data["RemotePeer"]) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.unreadMessages++; + var identifier = int.parse(data["ConversationID"]); + if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != identifier) { + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.unreadMessages++; } else { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.newMarker++; + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.newMarker++; } - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.totalMessages++; - profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["RemotePeer"], DateTime.now()); + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages++; + profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(identifier, DateTime.now()); // We only ever see messages from authenticated peers. // If the contact is marked as offline then override this - can happen when the contact is removed from the front // end during syncing. - if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.isOnline() == false) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.status = "Authenticated"; + if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.isOnline() == false) { + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.status = "Authenticated"; } break; @@ -151,10 +156,13 @@ class CwtchNotifier { // We don't use these anymore, IndexedAcknowledgement is more suited to the UI front end... break; case "IndexedAcknowledgement": - var idx = data["Index"]; + var messageID = data["Index"]; + var identifier = int.parse(data["ConversationID"]); + var idx = identifier.toString() + messageID; + // We return -1 for protocol message acks if there is no message if (idx == "-1") break; - var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.getMessageKey(idx); + var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.getMessageKey(idx); if (key == null) break; try { var message = Provider.of(key.currentContext!, listen: false); @@ -162,8 +170,8 @@ class CwtchNotifier { // We only ever see acks from authenticated peers. // If the contact is marked as offline then override this - can happen when the contact is removed from the front // end during syncing. - if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.isOnline() == false) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.status = "Authenticated"; + if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.isOnline() == false) { + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.status = "Authenticated"; } message.ackd = true; } catch (e) { @@ -172,19 +180,20 @@ class CwtchNotifier { } break; case "NewMessageFromGroup": + var identifier = int.parse(data["ConversationID"]); if (data["ProfileOnion"] != data["RemotePeer"]) { var idx = int.parse(data["Index"]); - var currentTotal = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.totalMessages; + var currentTotal = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages; // Only bother to do anything if we know about the group and the provided index is greater than our current total... if (currentTotal != null && idx >= currentTotal) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.totalMessages = idx + 1; + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages = idx + 1; //if not currently open - if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != data["GroupID"]) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.unreadMessages++; + if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != identifier) { + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.unreadMessages++; } else { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.newMarker++; + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.newMarker++; } var timestampSent = DateTime.tryParse(data['TimestampSent'])!; @@ -204,7 +213,7 @@ class CwtchNotifier { } else { // from me (already displayed - do not update counter) var idx = data["Signature"]; - var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])?.getMessageKey(idx); + var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)?.getMessageKey(idx); if (key == null) break; try { var message = Provider.of(key.currentContext!, listen: false); @@ -219,8 +228,8 @@ class CwtchNotifier { var contactHandle = data["RemotePeer"]; if (contactHandle == null || contactHandle == "") contactHandle = data["GroupID"]; var total = int.parse(data["Data"]); - if (total != profileCN.getProfile(data["Identity"])?.contactList.getContact(contactHandle)!.totalMessages) { - profileCN.getProfile(data["Identity"])?.contactList.getContact(contactHandle)!.totalMessages = total; + if (total != profileCN.getProfile(data["Identity"])?.contactList.findContact(contactHandle)!.totalMessages) { + profileCN.getProfile(data["Identity"])?.contactList.findContact(contactHandle)!.totalMessages = total; } break; case "SendMessageToPeerError": @@ -228,7 +237,7 @@ class CwtchNotifier { break; case "IndexedFailure": var idx = data["Index"]; - var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])?.getMessageKey(idx); + var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"])?.getMessageKey(idx); try { var message = Provider.of(key!.currentContext!, listen: false); message.error = true; @@ -240,7 +249,7 @@ class CwtchNotifier { // from me (already displayed - do not update counter) EnvironmentConfig.debugLog("SendMessageToGroupError"); var idx = data["Signature"]; - var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.getMessageKey(idx); + var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["GroupID"])!.getMessageKey(idx); if (key == null) break; try { var message = Provider.of(key.currentContext!, listen: false); @@ -298,8 +307,8 @@ class CwtchNotifier { status = serverInfoState.status; } - if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(groupInvite["GroupID"]) == null) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(data["ProfileOnion"], groupInvite["GroupID"], + if (profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(groupInvite["GroupID"]) == null) { + profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(data["ProfileOnion"], data["ConversationID"], groupInvite["GroupID"], authorization: ContactAuthorization.approved, imagePath: data["PicturePath"], nickname: groupInvite["GroupName"], diff --git a/lib/cwtch/ffi.dart b/lib/cwtch/ffi.dart index 87eb66d1..14cdffe9 100644 --- a/lib/cwtch/ffi.dart +++ b/lib/cwtch/ffi.dart @@ -36,8 +36,9 @@ typedef VoidFromStringStringStringFn = void Function(Pointer, int, Pointer typedef void_from_string_string_string_string_function = Void Function(Pointer, Int32, Pointer, Int32, Pointer, Int32, Pointer, Int32); typedef VoidFromStringStringStringStringFn = void Function(Pointer, int, Pointer, int, Pointer, int, Pointer, int); -typedef void_from_string_string_string_string_string_function = Void Function(Pointer, Int32, Pointer, Int32, Pointer, Int32, Pointer, Int32, Pointer, Int32); -typedef VoidFromStringStringStringStringStringFn = void Function(Pointer, int, Pointer, int, Pointer, int, Pointer, int, Pointer, int); +// DownloadFile +typedef void_from_string_int_string_string_string_function = Void Function(Pointer, Int32, Int32, Pointer, Int32, Pointer, Int32, Pointer, Int32); +typedef VoidFromStringIntStringStringStringFn = void Function(Pointer, int, int, Pointer, int, Pointer, int, Pointer, int); typedef void_from_string_string_int_int_function = Void Function(Pointer, Int32, Pointer, Int32, Int64, Int64); typedef VoidFromStringStringIntIntFn = void Function(Pointer, int, Pointer, int, int, int); @@ -51,6 +52,9 @@ typedef StringFn = void Function(Pointer dir, int); typedef string_string_to_void_function = Void Function(Pointer str, Int32 length, Pointer str2, Int32 length2); typedef StringStringFn = void Function(Pointer, int, Pointer, int); +typedef string_int_to_void_function = Void Function(Pointer str, Int32 length, Int32 handle); +typedef VoidFromStringIntFn = void Function(Pointer, int, int); + typedef get_json_blob_string_function = Pointer Function(Pointer str, Int32 length); typedef GetJsonBlobStringFn = Pointer Function(Pointer str, int len); @@ -58,10 +62,26 @@ typedef GetJsonBlobStringFn = Pointer Function(Pointer str, int len) typedef get_json_blob_from_str_str_int_function = Pointer Function(Pointer, Int32, Pointer, Int32, Int32); typedef GetJsonBlobFromStrStrIntFn = Pointer Function(Pointer, int, Pointer, int, int); +typedef get_json_blob_from_str_int_int_function = Pointer Function(Pointer, Int32, Int32, Int32); +typedef GetJsonBlobFromStrIntIntFn = Pointer Function(Pointer, int, int, int); + +typedef get_json_blob_from_str_int_string_function = Pointer Function(Pointer, Int32, Int32, Pointer, Int32); +typedef GetJsonBlobFromStrIntStringFn = Pointer Function(Pointer, int, int, Pointer, int,); + // func c_GetMessagesByContentHash(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, contenthash_ptr *C.char, contenthash_len C.int) *C.char typedef get_json_blob_from_str_str_str_function = Pointer Function(Pointer, Int32, Pointer, Int32, Pointer, Int32); typedef GetJsonBlobFromStrStrStrFn = Pointer Function(Pointer, int, Pointer, int, Pointer, int); +typedef void_from_string_int_string_function = Void Function(Pointer, Int32, Int32, Pointer, Int32); +typedef VoidFromStringIntStringFn = void Function(Pointer, int, int, Pointer, int); + +typedef void_from_string_int_string_string_function = Void Function(Pointer, Int32, Int32, Pointer, Int32, Pointer, Int32); +typedef VoidFromStringIntStringStringFn = void Function(Pointer, int, int, Pointer, int, Pointer, int); + +typedef void_from_string_int_int_function =Void Function(Pointer, Int32, Int32, Int32); +typedef VoidFromStringIntIntFn = void Function(Pointer, int, int, int); + + typedef appbus_events_function = Pointer Function(); typedef AppbusEventsFn = Pointer Function(); @@ -266,17 +286,15 @@ class CwtchFfi implements Cwtch { } // ignore: non_constant_identifier_names - Future GetMessage(String profile, String handle, int index) async { - var getMessageC = library.lookup>("c_GetMessage"); + Future GetMessage(String profile, int handle, int index) async { + var getMessageC = library.lookup>("c_GetMessage"); // ignore: non_constant_identifier_names - final GetMessage = getMessageC.asFunction(); + final GetMessage = getMessageC.asFunction(); final utf8profile = profile.toNativeUtf8(); - final utf8handle = handle.toNativeUtf8(); - Pointer jsonMessageBytes = GetMessage(utf8profile, utf8profile.length, utf8handle, utf8handle.length, index); + Pointer jsonMessageBytes = GetMessage(utf8profile, utf8profile.length, handle, index); String jsonMessage = jsonMessageBytes.toDartString(); _UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes); malloc.free(utf8profile); - malloc.free(utf8handle); return jsonMessage; } @@ -306,89 +324,75 @@ class CwtchFfi implements Cwtch { @override // ignore: non_constant_identifier_names - void AcceptContact(String profileOnion, String contactHandle) { - var acceptContact = library.lookup>("c_AcceptContact"); + void AcceptContact(String profileOnion, int contactHandle) { + var acceptContact = library.lookup>("c_AcceptContact"); // ignore: non_constant_identifier_names - final AcceptContact = acceptContact.asFunction(); + final AcceptContact = acceptContact.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = contactHandle.toNativeUtf8(); - AcceptContact(u1, u1.length, u2, u2.length); + AcceptContact(u1, u1.length, contactHandle); malloc.free(u1); - malloc.free(u2); } @override // ignore: non_constant_identifier_names - void BlockContact(String profileOnion, String contactHandle) { - var blockContact = library.lookup>("c_BlockContact"); + void BlockContact(String profileOnion, int contactHandle) { + var blockContact = library.lookup>("c_BlockContact"); // ignore: non_constant_identifier_names - final BlockContact = blockContact.asFunction(); + final BlockContact = blockContact.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = contactHandle.toNativeUtf8(); - BlockContact(u1, u1.length, u2, u2.length); + BlockContact(u1, u1.length, contactHandle); malloc.free(u1); - malloc.free(u2); } @override // ignore: non_constant_identifier_names - void SendMessage(String profileOnion, String contactHandle, String message) { - var sendMessage = library.lookup>("c_SendMessage"); + void SendMessage(String profileOnion, int contactHandle, String message) { + var sendMessage = library.lookup>("c_SendMessage"); // ignore: non_constant_identifier_names - final SendMessage = sendMessage.asFunction(); + final SendMessage = sendMessage.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = contactHandle.toNativeUtf8(); final u3 = message.toNativeUtf8(); - SendMessage(u1, u1.length, u2, u2.length, u3, u3.length); + SendMessage(u1, u1.length, contactHandle, u3, u3.length); malloc.free(u1); - malloc.free(u2); malloc.free(u3); } @override // ignore: non_constant_identifier_names - void SendInvitation(String profileOnion, String contactHandle, String target) { - var sendInvitation = library.lookup>("c_SendInvitation"); + void SendInvitation(String profileOnion, int contactHandle, int target) { + var sendInvitation = library.lookup>("c_SendInvitation"); // ignore: non_constant_identifier_names - final SendInvitation = sendInvitation.asFunction(); + final SendInvitation = sendInvitation.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = contactHandle.toNativeUtf8(); - final u3 = target.toNativeUtf8(); - SendInvitation(u1, u1.length, u2, u2.length, u3, u3.length); + SendInvitation(u1, u1.length, contactHandle, target); malloc.free(u1); - malloc.free(u2); - malloc.free(u3); } @override // ignore: non_constant_identifier_names - void ShareFile(String profileOnion, String contactHandle, String filepath) { - var shareFile = library.lookup>("c_ShareFile"); + void ShareFile(String profileOnion, int contactHandle, String filepath) { + var shareFile = library.lookup>("c_ShareFile"); // ignore: non_constant_identifier_names - final ShareFile = shareFile.asFunction(); + final ShareFile = shareFile.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = contactHandle.toNativeUtf8(); final u3 = filepath.toNativeUtf8(); - ShareFile(u1, u1.length, u2, u2.length, u3, u3.length); + ShareFile(u1, u1.length, contactHandle, u3, u3.length); malloc.free(u1); - malloc.free(u2); malloc.free(u3); } @override // ignore: non_constant_identifier_names - void DownloadFile(String profileOnion, String contactHandle, String filepath, String manifestpath, String filekey) { - var dlFile = library.lookup>("c_DownloadFile"); + void DownloadFile(String profileOnion, int contactHandle, String filepath, String manifestpath, String filekey) { + var dlFile = library.lookup>("c_DownloadFile"); // ignore: non_constant_identifier_names - final DownloadFile = dlFile.asFunction(); + final DownloadFile = dlFile.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = contactHandle.toNativeUtf8(); final u3 = filepath.toNativeUtf8(); final u4 = manifestpath.toNativeUtf8(); final u5 = filekey.toNativeUtf8(); - DownloadFile(u1, u1.length, u2, u2.length, u3, u3.length, u4, u4.length, u5, u5.length); + DownloadFile(u1, u1.length, contactHandle, u3, u3.length, u4, u4.length, u5, u5.length); malloc.free(u1); - malloc.free(u2); malloc.free(u3); malloc.free(u4); malloc.free(u5); @@ -396,7 +400,7 @@ class CwtchFfi implements Cwtch { @override // ignore: non_constant_identifier_names - void CreateDownloadableFile(String profileOnion, String contactHandle, String filenameSuggestion, String filekey) { + void CreateDownloadableFile(String profileOnion, int contactHandle, String filenameSuggestion, String filekey) { // android only - do nothing } @@ -415,16 +419,14 @@ class CwtchFfi implements Cwtch { @override // ignore: non_constant_identifier_names - void VerifyOrResumeDownload(String profileOnion, String contactHandle, String filekey) { - var fn = library.lookup>("c_VerifyOrResumeDownload"); + void VerifyOrResumeDownload(String profileOnion, int contactHandle, String filekey) { + var fn = library.lookup>("c_VerifyOrResumeDownload"); // ignore: non_constant_identifier_names - final VerifyOrResumeDownload = fn.asFunction(); + final VerifyOrResumeDownload = fn.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = contactHandle.toNativeUtf8(); final u3 = filekey.toNativeUtf8(); - VerifyOrResumeDownload(u1, u1.length, u2, u2.length, u3, u3.length); + VerifyOrResumeDownload(u1, u1.length, contactHandle, u3, u3.length); malloc.free(u1); - malloc.free(u2); malloc.free(u3); } @@ -451,34 +453,16 @@ class CwtchFfi implements Cwtch { malloc.free(u2); } - @override - // ignore: non_constant_identifier_names - void SetGroupAttribute(String profileOnion, String groupHandle, String key, String value) { - var setGroupAttribute = library.lookup>("c_SetGroupAttribute"); - // ignore: non_constant_identifier_names - final SetGroupAttribute = setGroupAttribute.asFunction(); - final u1 = profileOnion.toNativeUtf8(); - final u2 = groupHandle.toNativeUtf8(); - final u3 = key.toNativeUtf8(); - final u4 = value.toNativeUtf8(); - SetGroupAttribute(u1, u1.length, u2, u2.length, u3, u3.length, u4, u4.length); - malloc.free(u1); - malloc.free(u2); - malloc.free(u3); - malloc.free(u4); - } @override // ignore: non_constant_identifier_names - void RejectInvite(String profileOnion, String groupHandle) { - var rejectInvite = library.lookup>("c_RejectInvite"); + void RejectInvite(String profileOnion, int groupHandle) { + var rejectInvite = library.lookup>("c_RejectInvite"); // ignore: non_constant_identifier_names - final RejectInvite = rejectInvite.asFunction(); + final RejectInvite = rejectInvite.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = groupHandle.toNativeUtf8(); - RejectInvite(u1, u1.length, u2, u2.length); + RejectInvite(u1, u1.length, groupHandle); malloc.free(u1); - malloc.free(u2); } @override @@ -499,42 +483,27 @@ class CwtchFfi implements Cwtch { @override // ignore: non_constant_identifier_names - void ArchiveConversation(String profileOnion, String handle) { - var archiveConversation = library.lookup>("c_ArchiveConversation"); + void ArchiveConversation(String profileOnion, int handle) { + var archiveConversation = library.lookup>("c_ArchiveConversation"); // ignore: non_constant_identifier_names - final ArchiveConversation = archiveConversation.asFunction(); + final ArchiveConversation = archiveConversation.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = handle.toNativeUtf8(); - ArchiveConversation(u1, u1.length, u2, u2.length); + ArchiveConversation(u1, u1.length, handle); malloc.free(u1); - malloc.free(u2); + } @override // ignore: non_constant_identifier_names - void DeleteContact(String profileOnion, String handle) { - var deleteContact = library.lookup>("c_DeleteContact"); + void DeleteContact(String profileOnion, int handle) { + var deleteContact = library.lookup>("c_DeleteContact"); // ignore: non_constant_identifier_names - final DeleteContact = deleteContact.asFunction(); + final DeleteContact = deleteContact.asFunction(); final u1 = profileOnion.toNativeUtf8(); - final u2 = handle.toNativeUtf8(); - DeleteContact(u1, u1.length, u2, u2.length); + DeleteContact(u1, u1.length, handle); malloc.free(u1); - malloc.free(u2); } - @override - // ignore: non_constant_identifier_names - void UpdateMessageFlags(String profile, String handle, int index, int flags) { - var updateMessageFlagsC = library.lookup>("c_UpdateMessageFlags"); - // ignore: non_constant_identifier_names - final updateMessageFlags = updateMessageFlagsC.asFunction(); - final utf8profile = profile.toNativeUtf8(); - final utf8handle = handle.toNativeUtf8(); - updateMessageFlags(utf8profile, utf8profile.length, utf8handle, utf8handle.length, index, flags); - malloc.free(utf8profile); - malloc.free(utf8handle); - } @override // ignore: non_constant_identifier_names @@ -566,17 +535,15 @@ class CwtchFfi implements Cwtch { @override // ignore: non_constant_identifier_names - void SetContactAttribute(String profile, String contact, String key, String val) { - var setContactAttribute = library.lookup>("c_SetContactAttribute"); + void SetConversationAttribute(String profile, int contact, String key, String val) { + var setContactAttribute = library.lookup>("c_SetContactAttribute"); // ignore: non_constant_identifier_names - final SetContactAttribute = setContactAttribute.asFunction(); + final SetContactAttribute = setContactAttribute.asFunction(); final u1 = profile.toNativeUtf8(); - final u2 = contact.toNativeUtf8(); final u3 = key.toNativeUtf8(); final u4 = key.toNativeUtf8(); - SetContactAttribute(u1, u1.length, u2, u2.length, u3, u3.length, u4, u4.length); + SetContactAttribute(u1, u1.length, contact, u3, u3.length, u4, u4.length); malloc.free(u1); - malloc.free(u2); malloc.free(u3); malloc.free(u4); } @@ -703,19 +670,17 @@ class CwtchFfi implements Cwtch { @override // ignore: non_constant_identifier_names - Future GetMessageByContentHash(String profile, String handle, String contentHash) async { - var getMessagesByContentHashC = library.lookup>("c_GetMessagesByContentHash"); + Future GetMessageByContentHash(String profile, int handle, String contentHash) async { + var getMessagesByContentHashC = library.lookup>("c_GetMessagesByContentHash"); // ignore: non_constant_identifier_names - final GetMessagesByContentHash = getMessagesByContentHashC.asFunction(); + final GetMessagesByContentHash = getMessagesByContentHashC.asFunction(); final utf8profile = profile.toNativeUtf8(); - final utf8handle = handle.toNativeUtf8(); final utf8contentHash = contentHash.toNativeUtf8(); - Pointer jsonMessageBytes = GetMessagesByContentHash(utf8profile, utf8profile.length, utf8handle, utf8handle.length, utf8contentHash, utf8contentHash.length); + Pointer jsonMessageBytes = GetMessagesByContentHash(utf8profile, utf8profile.length, handle, utf8contentHash, utf8contentHash.length); String jsonMessage = jsonMessageBytes.toDartString(); _UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes); malloc.free(utf8profile); - malloc.free(utf8handle); malloc.free(utf8contentHash); return jsonMessage; } diff --git a/lib/cwtch/gomobile.dart b/lib/cwtch/gomobile.dart index ae30a80c..06c91f74 100644 --- a/lib/cwtch/gomobile.dart +++ b/lib/cwtch/gomobile.dart @@ -87,7 +87,7 @@ class CwtchGomobile implements Cwtch { } // ignore: non_constant_identifier_names - Future GetMessage(String profile, String handle, int index) { + Future GetMessage(String profile, int handle, int index) { print("gomobile.dart GetMessage " + index.toString()); return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "index": index}); } @@ -109,42 +109,42 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void AcceptContact(String profileOnion, String contactHandle) { + void AcceptContact(String profileOnion, int contactHandle) { cwtchPlatform.invokeMethod("AcceptContact", {"ProfileOnion": profileOnion, "handle": contactHandle}); } @override // ignore: non_constant_identifier_names - void BlockContact(String profileOnion, String contactHandle) { + void BlockContact(String profileOnion, int contactHandle) { cwtchPlatform.invokeMethod("BlockContact", {"ProfileOnion": profileOnion, "handle": contactHandle}); } @override // ignore: non_constant_identifier_names - void SendMessage(String profileOnion, String contactHandle, String message) { + void SendMessage(String profileOnion, int contactHandle, String message) { cwtchPlatform.invokeMethod("SendMessage", {"ProfileOnion": profileOnion, "handle": contactHandle, "message": message}); } @override // ignore: non_constant_identifier_names - void SendInvitation(String profileOnion, String contactHandle, String target) { + void SendInvitation(String profileOnion, int contactHandle, int target) { cwtchPlatform.invokeMethod("SendInvitation", {"ProfileOnion": profileOnion, "handle": contactHandle, "target": target}); } @override // ignore: non_constant_identifier_names - void ShareFile(String profileOnion, String contactHandle, String filepath) { + void ShareFile(String profileOnion, int contactHandle, String filepath) { cwtchPlatform.invokeMethod("ShareFile", {"ProfileOnion": profileOnion, "handle": contactHandle, "filepath": filepath}); } @override // ignore: non_constant_identifier_names - void DownloadFile(String profileOnion, String contactHandle, String filepath, String manifestpath, String filekey) { + void DownloadFile(String profileOnion, int contactHandle, String filepath, String manifestpath, String filekey) { cwtchPlatform.invokeMethod("DownloadFile", {"ProfileOnion": profileOnion, "handle": contactHandle, "filepath": filepath, "manifestpath": manifestpath, "filekey": filekey}); } // ignore: non_constant_identifier_names - void CreateDownloadableFile(String profileOnion, String contactHandle, String filenameSuggestion, String filekey) { + void CreateDownloadableFile(String profileOnion, int contactHandle, String filenameSuggestion, String filekey) { cwtchPlatform.invokeMethod("CreateDownloadableFile", {"ProfileOnion": profileOnion, "handle": contactHandle, "filename": filenameSuggestion, "filekey": filekey}); } @@ -156,7 +156,7 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void VerifyOrResumeDownload(String profileOnion, String contactHandle, String filekey) { + void VerifyOrResumeDownload(String profileOnion, int contactHandle, String filekey) { cwtchPlatform.invokeMethod("VerifyOrResumeDownload", {"ProfileOnion": profileOnion, "handle": contactHandle, "filekey": filekey}); } @@ -180,7 +180,7 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void RejectInvite(String profileOnion, String groupHandle) { + void RejectInvite(String profileOnion, int groupHandle) { cwtchPlatform.invokeMethod("RejectInvite", {"ProfileOnion": profileOnion, "groupHandle": groupHandle}); } @@ -191,21 +191,16 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void DeleteContact(String profileOnion, String handle) { + void DeleteContact(String profileOnion, int handle) { cwtchPlatform.invokeMethod("DeleteContact", {"ProfileOnion": profileOnion, "handle": handle}); } @override // ignore: non_constant_identifier_names - void ArchiveConversation(String profileOnion, String contactHandle) { + void ArchiveConversation(String profileOnion, int contactHandle) { cwtchPlatform.invokeMethod("ArchiveConversation", {"ProfileOnion": profileOnion, "handle": contactHandle}); } - @override - void UpdateMessageFlags(String profile, String handle, int index, int flags) { - print("gomobile.dart UpdateMessageFlags " + index.toString()); - cwtchPlatform.invokeMethod("UpdateMessageFlags", {"profile": profile, "contact": handle, "midx": index, "flags": flags}); - } @override // ignore: non_constant_identifier_names @@ -215,7 +210,7 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void SetContactAttribute(String profile, String contact, String key, String val) { + void SetConversationAttribute(String profile, int contact, String key, String val) { cwtchPlatform.invokeMethod("SetContactAttribute", {"ProfileOnion": profile, "Contact": contact, "Key": key, "Val": val}); } @@ -280,7 +275,7 @@ class CwtchGomobile implements Cwtch { } @override - Future GetMessageByContentHash(String profile, String handle, String contentHash) { + Future GetMessageByContentHash(String profile, int handle, String contentHash) { return cwtchPlatform.invokeMethod("GetMessageByContentHash", {"profile": profile, "contact": handle, "contentHash": contentHash}); } } diff --git a/lib/model.dart b/lib/model.dart index 23780557..a0882561 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -29,7 +29,7 @@ class AppState extends ChangeNotifier { bool cwtchIsClosing = false; String appError = ""; String? _selectedProfile; - String? _selectedConversation; + int? _selectedConversation; int _initialScrollIndex = 0; int _hoveredIndex = -1; int? _selectedIndex; @@ -51,8 +51,8 @@ class AppState extends ChangeNotifier { notifyListeners(); } - String? get selectedConversation => _selectedConversation; - set selectedConversation(String? newVal) { + int? get selectedConversation => _selectedConversation; + set selectedConversation(int? newVal) { this._selectedConversation = newVal; notifyListeners(); } @@ -172,8 +172,8 @@ class ContactListState extends ChangeNotifier { //} } - void updateLastMessageTime(String forOnion, DateTime newMessageTime) { - var contact = getContact(forOnion); + void updateLastMessageTime(int forIdentifier, DateTime newMessageTime) { + var contact = getContact(forIdentifier); if (contact == null) return; // Assert that the new time is after the current last message time AND that @@ -191,18 +191,24 @@ class ContactListState extends ChangeNotifier { List get contacts => _contacts.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier - ContactInfoState? getContact(String onion) { - int idx = _contacts.indexWhere((element) => element.onion == onion); + ContactInfoState? getContact(int identifier) { + int idx = _contacts.indexWhere((element) => element.identifier == identifier); return idx >= 0 ? _contacts[idx] : null; } - void removeContact(String onion) { - int idx = _contacts.indexWhere((element) => element.onion == onion); + void removeContact(int identifier) { + int idx = _contacts.indexWhere((element) => element.identifier == identifier); if (idx >= 0) { _contacts.removeAt(idx); notifyListeners(); } } + + ContactInfoState? findContact(String byHandle) { + int idx = _contacts.indexWhere((element) => element.onion == byHandle); + return idx >= 0 ? _contacts[idx] : null; + } + } class ProfileInfoState extends ChangeNotifier { @@ -238,7 +244,7 @@ class ProfileInfoState extends ChangeNotifier { if (contactsJson != null && contactsJson != "" && contactsJson != "null") { List contacts = jsonDecode(contactsJson); this._contacts.addAll(contacts.map((contact) { - return ContactInfoState(this.onion, contact["onion"], + return ContactInfoState(this.onion, contact["identifier"], contact["onion"], nickname: contact["name"], status: contact["status"], imagePath: contact["picture"], @@ -254,7 +260,7 @@ class ProfileInfoState extends ChangeNotifier { // dummy set to invoke sort-on-load if (this._contacts.num > 0) { - this._contacts.updateLastMessageTime(this._contacts._contacts.first.onion, this._contacts._contacts.first.lastMessageTime); + this._contacts.updateLastMessageTime(this._contacts._contacts.first.identifier, this._contacts._contacts.first.lastMessageTime); } } @@ -341,6 +347,7 @@ class ProfileInfoState extends ChangeNotifier { } else { this._contacts.add(ContactInfoState( this.onion, + contact["identifier"], contact["onion"], nickname: contact["name"], status: contact["status"], @@ -496,6 +503,7 @@ ContactAuthorization stringToContactAuthorization(String authStr) { class ContactInfoState extends ChangeNotifier { final String profileOnion; + final int identifier; final String onion; late String _nickname; @@ -515,7 +523,7 @@ class ContactInfoState extends ChangeNotifier { String? _server; late bool _archived; - ContactInfoState(this.profileOnion, this.onion, + ContactInfoState(this.profileOnion, this.identifier, this.onion, {nickname = "", isGroup = false, authorization = ContactAuthorization.unknown, diff --git a/lib/models/message.dart b/lib/models/message.dart index 2156b8d6..062c60a8 100644 --- a/lib/models/message.dart +++ b/lib/models/message.dart @@ -31,11 +31,11 @@ abstract class Message { Widget getPreviewWidget(BuildContext context); } -Future messageHandler(BuildContext context, String profileOnion, String contactHandle, int index) { +Future messageHandler(BuildContext context, String profileOnion, int conversationIdentifier, int index) { try { - var rawMessageEnvelopeFuture = Provider.of(context, listen: false).cwtch.GetMessage(profileOnion, contactHandle, index); + var rawMessageEnvelopeFuture = Provider.of(context, listen: false).cwtch.GetMessage(profileOnion, conversationIdentifier, index); return rawMessageEnvelopeFuture.then((dynamic rawMessageEnvelope) { - var metadata = MessageMetadata(profileOnion, contactHandle, index, DateTime.now(), "", "", null, 0, false, true); + var metadata = MessageMetadata(profileOnion, conversationIdentifier, index, -1, DateTime.now(), "", "", null, 0, false, true); try { dynamic messageWrapper = jsonDecode(rawMessageEnvelope); // There are 2 conditions in which this error condition can be met: @@ -50,23 +50,20 @@ Future messageHandler(BuildContext context, String profileOnion, String if (messageWrapper['Message'] == null || messageWrapper['Message'] == '' || messageWrapper['Message'] == '{}') { return Future.delayed(Duration(seconds: 2), () { print("Tail recursive call to messageHandler called. This should be a rare event. If you see multiples of this log over a short period of time please log it as a bug."); - return messageHandler(context, profileOnion, contactHandle, index).then((value) => value); + return messageHandler(context, profileOnion, conversationIdentifier, index).then((value) => value); }); } // Construct the initial metadata + var messageID = messageWrapper['ID']; var timestamp = DateTime.tryParse(messageWrapper['Timestamp'])!; var senderHandle = messageWrapper['PeerID']; var senderImage = messageWrapper['ContactImage']; var flags = int.parse(messageWrapper['Flags'].toString()); var ackd = messageWrapper['Acknowledged']; var error = messageWrapper['Error'] != null; - String? signature; - // If this is a group, store the signature - if (contactHandle.length == GroupConversationHandleLength) { - signature = messageWrapper['Signature']; - } - metadata = MessageMetadata(profileOnion, contactHandle, index, timestamp, senderHandle, senderImage, signature, flags, ackd, error); + var signature = messageWrapper['Signature']; + metadata = MessageMetadata(profileOnion, conversationIdentifier, index, messageID, timestamp, senderHandle, senderImage, signature, flags, ackd, error); dynamic message = jsonDecode(messageWrapper['Message']); var content = message['d'] as dynamic; @@ -92,15 +89,16 @@ Future messageHandler(BuildContext context, String profileOnion, String } }); } catch (e) { - return Future.value(MalformedMessage(MessageMetadata(profileOnion, contactHandle, index, DateTime.now(), "", "", null, 0, false, true))); + return Future.value(MalformedMessage(MessageMetadata(profileOnion, conversationIdentifier, index, -1, DateTime.now(), "", "", null, 0, false, true))); } } class MessageMetadata extends ChangeNotifier { // meta-metadata final String profileOnion; - final String contactHandle; + final int conversationIdentifier; final int messageIndex; + final int messageID; final DateTime timestamp; final String senderHandle; @@ -129,5 +127,5 @@ class MessageMetadata extends ChangeNotifier { notifyListeners(); } - MessageMetadata(this.profileOnion, this.contactHandle, this.messageIndex, this.timestamp, this.senderHandle, this.senderImage, this.signature, this._flags, this._ackd, this._error); + MessageMetadata(this.profileOnion, this.conversationIdentifier, this.messageIndex, this.messageID, this.timestamp, this.senderHandle, this.senderImage, this.signature, this._flags, this._ackd, this._error); } diff --git a/lib/models/messages/filemessage.dart b/lib/models/messages/filemessage.dart index 0ea5cbc7..24c6e152 100644 --- a/lib/models/messages/filemessage.dart +++ b/lib/models/messages/filemessage.dart @@ -21,7 +21,7 @@ class FileMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - String idx = this.metadata.contactHandle + this.metadata.messageIndex.toString(); + String idx = this.metadata.conversationIdentifier.toString() + this.metadata.messageID.toString(); dynamic shareObj = jsonDecode(this.content); if (shareObj == null) { return MessageRow(MalformedBubble()); diff --git a/lib/models/messages/invitemessage.dart b/lib/models/messages/invitemessage.dart index df21e313..fb58f083 100644 --- a/lib/models/messages/invitemessage.dart +++ b/lib/models/messages/invitemessage.dart @@ -21,14 +21,14 @@ class InviteMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - String idx = this.metadata.contactHandle + this.metadata.messageIndex.toString(); + String idx = this.metadata.conversationIdentifier.toString() + this.metadata.messageID.toString(); String inviteTarget; String inviteNick; String invite = this.content; if (this.content.length == TorV3ContactHandleLength) { inviteTarget = this.content; - var targetContact = Provider.of(context).contactList.getContact(inviteTarget); + var targetContact = Provider.of(context).contactList.findContact(inviteTarget); inviteNick = targetContact == null ? this.content : targetContact.nickname; } else { var parts = this.content.toString().split("||"); @@ -54,7 +54,7 @@ class InviteMessage extends Message { String invite = this.content; if (this.content.length == TorV3ContactHandleLength) { inviteTarget = this.content; - var targetContact = Provider.of(context).contactList.getContact(inviteTarget); + var targetContact = Provider.of(context).contactList.findContact(inviteTarget); inviteNick = targetContact == null ? this.content : targetContact.nickname; } else { var parts = this.content.toString().split("||"); diff --git a/lib/models/messages/quotedmessage.dart b/lib/models/messages/quotedmessage.dart index 8bc0c905..6ddba3a3 100644 --- a/lib/models/messages/quotedmessage.dart +++ b/lib/models/messages/quotedmessage.dart @@ -70,7 +70,7 @@ class QuotedMessage extends Message { return MalformedMessage(this.metadata).getWidget(context); } - var quotedMessagePotentials = Provider.of(context).cwtch.GetMessageByContentHash(metadata.profileOnion, metadata.contactHandle, message["quotedHash"]); + var quotedMessagePotentials = Provider.of(context).cwtch.GetMessageByContentHash(metadata.profileOnion, metadata.conversationIdentifier, message["quotedHash"]); int messageIndex = metadata.messageIndex; Future quotedMessage = quotedMessagePotentials.then((matchingMessages) { if (matchingMessages == "[]") { @@ -94,11 +94,11 @@ class QuotedMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - String idx = this.metadata.contactHandle + this.metadata.messageIndex.toString(); + String idx = this.metadata.conversationIdentifier.toString() + this.metadata.messageID.toString(); return MessageRow( QuotedMessageBubble(message["body"], quotedMessage.then((LocallyIndexedMessage? localIndex) { if (localIndex != null) { - return messageHandler(context, metadata.profileOnion, metadata.contactHandle, localIndex.index); + return messageHandler(context, metadata.profileOnion, metadata.conversationIdentifier, localIndex.index); } return MalformedMessage(this.metadata); })), diff --git a/lib/models/messages/textmessage.dart b/lib/models/messages/textmessage.dart index a5782ac4..ac996152 100644 --- a/lib/models/messages/textmessage.dart +++ b/lib/models/messages/textmessage.dart @@ -32,7 +32,7 @@ class TextMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - String idx = this.metadata.contactHandle + this.metadata.messageIndex.toString(); + String idx = this.metadata.conversationIdentifier.toString() + this.metadata.messageID.toString(); return MessageRow(MessageBubble(this.content), key: Provider.of(bcontext).getMessageKey(idx)); }); } diff --git a/lib/views/contactsview.dart b/lib/views/contactsview.dart index 895b06ac..bb9c585c 100644 --- a/lib/views/contactsview.dart +++ b/lib/views/contactsview.dart @@ -22,7 +22,7 @@ class ContactsView extends StatefulWidget { } // selectConversation can be called from anywhere to set the active conversation -void selectConversation(BuildContext context, String handle) { +void selectConversation(BuildContext context, int handle) { // requery instead of using contactinfostate directly because sometimes listview gets confused about data that resorts var initialIndex = Provider.of(context, listen: false).contactList.getContact(handle)!.unreadMessages; Provider.of(context, listen: false).contactList.getContact(handle)!.unreadMessages = 0; @@ -36,7 +36,7 @@ void selectConversation(BuildContext context, String handle) { if (Provider.of(context, listen: false).uiColumns(isLandscape).length == 1) _pushMessageView(context, handle); } -void _pushMessageView(BuildContext context, String handle) { +void _pushMessageView(BuildContext context, int handle) { var profileOnion = Provider.of(context, listen: false).onion; Navigator.of(context).push( MaterialPageRoute( diff --git a/lib/views/doublecolview.dart b/lib/views/doublecolview.dart index 99d2aa9f..329821c7 100644 --- a/lib/views/doublecolview.dart +++ b/lib/views/doublecolview.dart @@ -34,8 +34,8 @@ class _DoubleColumnViewState extends State { MultiProvider(providers: [ ChangeNotifierProvider.value(value: Provider.of(context)), ChangeNotifierProvider.value( - value: flwtch.selectedConversation != null ? Provider.of(context).contactList.getContact(flwtch.selectedConversation!)! : ContactInfoState("", "")), - ], child: Container(key: Key(flwtch.selectedConversation??"never_this"), child: MessageView())), + value: flwtch.selectedConversation != null ? Provider.of(context).contactList.getContact(flwtch.selectedConversation!)! : ContactInfoState("", -1, "")), + ], child: Container(key: Key(flwtch.selectedConversation!.toString()), child: MessageView())), ), ], ); diff --git a/lib/views/groupsettingsview.dart b/lib/views/groupsettingsview.dart index 72afb5d2..83e57d32 100644 --- a/lib/views/groupsettingsview.dart +++ b/lib/views/groupsettingsview.dart @@ -78,9 +78,9 @@ class _GroupSettingsViewState extends State { readonly: false, onPressed: () { var profileOnion = Provider.of(context, listen: false).profileOnion; - var handle = Provider.of(context, listen: false).onion; + var handle = Provider.of(context, listen: false).identifier; Provider.of(context, listen: false).nickname = ctrlrNick.text; - Provider.of(context, listen: false).cwtch.SetGroupAttribute(profileOnion, handle, "local.name", ctrlrNick.text); + Provider.of(context, listen: false).cwtch.SetConversationAttribute(profileOnion, handle, "local.name", ctrlrNick.text); // todo translations final snackBar = SnackBar(content: Text("Group Nickname changed successfully")); ScaffoldMessenger.of(context).showSnackBar(snackBar); @@ -140,7 +140,7 @@ class _GroupSettingsViewState extends State { child: ElevatedButton.icon( onPressed: () { var profileOnion = Provider.of(context, listen: false).profileOnion; - var handle = Provider.of(context, listen: false).onion; + var handle = Provider.of(context, listen: false).identifier; // locally update cache... Provider.of(context, listen: false).isArchived = true; Provider.of(context, listen: false).cwtch.ArchiveConversation(profileOnion, handle); @@ -195,7 +195,7 @@ class _GroupSettingsViewState extends State { child: Text(AppLocalizations.of(context)!.yesLeave), onPressed: () { var profileOnion = Provider.of(context, listen: false).profileOnion; - var handle = Provider.of(context, listen: false).onion; + var handle = Provider.of(context, listen: false).identifier; // locally update cache... Provider.of(context, listen: false).isArchived = true; Provider.of(context, listen: false).cwtch.DeleteContact(profileOnion, handle); diff --git a/lib/views/messageview.dart b/lib/views/messageview.dart index f35460fb..79ae41e3 100644 --- a/lib/views/messageview.dart +++ b/lib/views/messageview.dart @@ -33,7 +33,7 @@ class MessageView extends StatefulWidget { class _MessageViewState extends State { final ctrlrCompose = TextEditingController(); final focusNode = FocusNode(); - String selectedContact = ""; + int selectedContact = -1; ItemPositionsListener scrollListener = ItemPositionsListener.create(); ItemScrollController scrollController = ItemScrollController(); @@ -180,7 +180,7 @@ class _MessageViewState extends State { ChatMessage cm = new ChatMessage(o: QuotedMessageOverlay, d: quotedMessage); Provider.of(context, listen: false) .cwtch - .SendMessage(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).onion, jsonEncode(cm)); + .SendMessage(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).identifier, jsonEncode(cm)); } catch (e) {} Provider.of(context, listen: false).selectedIndex = null; _sendMessageHelper(); @@ -189,7 +189,7 @@ class _MessageViewState extends State { ChatMessage cm = new ChatMessage(o: TextMessageOverlay, d: ctrlrCompose.value.text); Provider.of(context, listen: false) .cwtch - .SendMessage(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).onion, jsonEncode(cm)); + .SendMessage(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).identifier, jsonEncode(cm)); _sendMessageHelper(); } } @@ -198,14 +198,14 @@ class _MessageViewState extends State { void _sendInvitation([String? ignoredParam]) { Provider.of(context, listen: false) .cwtch - .SendInvitation(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).onion, this.selectedContact); + .SendInvitation(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).identifier, this.selectedContact); _sendMessageHelper(); } void _sendFile(String filePath) { Provider.of(context, listen: false) .cwtch - .ShareFile(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).onion, filePath); + .ShareFile(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).identifier, filePath); _sendMessageHelper(); } @@ -216,7 +216,7 @@ class _MessageViewState extends State { Provider.of(context, listen: false).totalMessages++; Provider.of(context, listen: false).newMarker++; // Resort the contact list... - Provider.of(context, listen: false).contactList.updateLastMessageTime(Provider.of(context, listen: false).onion, DateTime.now()); + Provider.of(context, listen: false).contactList.updateLastMessageTime(Provider.of(context, listen: false).identifier, DateTime.now()); }); } diff --git a/lib/views/peersettingsview.dart b/lib/views/peersettingsview.dart index 7b59a604..235ca8ca 100644 --- a/lib/views/peersettingsview.dart +++ b/lib/views/peersettingsview.dart @@ -200,7 +200,7 @@ class _PeerSettingsViewState extends State { child: ElevatedButton.icon( onPressed: () { var profileOnion = Provider.of(context, listen: false).profileOnion; - var handle = Provider.of(context, listen: false).onion; + var handle = Provider.of(context, listen: false).identifier; // locally update cache... Provider.of(context, listen: false).isArchived = true; Provider.of(context, listen: false).cwtch.ArchiveConversation(profileOnion, handle); @@ -239,7 +239,7 @@ class _PeerSettingsViewState extends State { child: Text(AppLocalizations.of(context)!.yesLeave), onPressed: () { var profileOnion = Provider.of(context, listen: false).profileOnion; - var handle = Provider.of(context, listen: false).onion; + var handle = Provider.of(context, listen: false).identifier; // locally update cache... Provider.of(context, listen: false).isArchived = true; Provider.of(context, listen: false).cwtch.DeleteContact(profileOnion, handle); diff --git a/lib/widgets/contactrow.dart b/lib/widgets/contactrow.dart index 6a50008a..c34e4668 100644 --- a/lib/widgets/contactrow.dart +++ b/lib/widgets/contactrow.dart @@ -105,7 +105,7 @@ class _ContactRowState extends State { ), ]), onTap: () { - selectConversation(context, contact.onion); + selectConversation(context, contact.identifier); }, )); } @@ -113,16 +113,16 @@ class _ContactRowState extends State { void _btnApprove() { Provider.of(context, listen: false) .cwtch - .AcceptContact(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).onion); + .AcceptContact(Provider.of(context, listen: false).profileOnion, Provider.of(context, listen: false).identifier); } void _btnReject() { ContactInfoState contact = Provider.of(context, listen: false); if (contact.isGroup == true) { - Provider.of(context, listen: false).cwtch.RejectInvite(Provider.of(context, listen: false).profileOnion, contact.onion); + Provider.of(context, listen: false).cwtch.RejectInvite(Provider.of(context, listen: false).profileOnion, contact.identifier); Provider.of(context, listen: false).removeContact(contact.onion); } else { - Provider.of(context, listen: false).cwtch.BlockContact(Provider.of(context, listen: false).profileOnion, contact.onion); + Provider.of(context, listen: false).cwtch.BlockContact(Provider.of(context, listen: false).profileOnion, contact.identifier); } } diff --git a/lib/widgets/filebubble.dart b/lib/widgets/filebubble.dart index 33fa503e..e3aea951 100644 --- a/lib/widgets/filebubble.dart +++ b/lib/widgets/filebubble.dart @@ -49,7 +49,7 @@ class FileBubbleState extends State { // If the sender is not us, then we want to give them a nickname... var senderDisplayStr = ""; if (!fromMe) { - ContactInfoState? contact = Provider.of(context).contactList.getContact(Provider.of(context).senderHandle); + ContactInfoState? contact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle); if (contact != null) { senderDisplayStr = contact.nickname; } else { @@ -152,9 +152,16 @@ class FileBubbleState extends State { if (Platform.isAndroid) { Provider.of(context, listen: false).downloadInit(widget.fileKey(), (widget.fileSize / 4096).ceil()); - Provider.of(context, listen: false).cwtch.UpdateMessageFlags(profileOnion, contact, idx, Provider.of(context, listen: false).flags | 0x02); + //Provider.of(context, listen: false).cwtch.UpdateMessageFlags(profileOnion, contact, idx, Provider.of(context, listen: false).flags | 0x02); Provider.of(context, listen: false).flags |= 0x02; - Provider.of(context, listen: false).cwtch.CreateDownloadableFile(profileOnion, handle, widget.nameSuggestion, widget.fileKey()); + ContactInfoState? contact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle); + if (contact != null) { + Provider + .of(context, listen: false) + .cwtch + .CreateDownloadableFile( + profileOnion, contact.identifier, widget.nameSuggestion, widget.fileKey()); + } } else { try { selectedFileName = await saveFile( @@ -165,9 +172,16 @@ class FileBubbleState extends State { print("saving to " + file.path); var manifestPath = file.path + ".manifest"; Provider.of(context, listen: false).downloadInit(widget.fileKey(), (widget.fileSize / 4096).ceil()); - Provider.of(context, listen: false).cwtch.UpdateMessageFlags(profileOnion, contact, idx, Provider.of(context, listen: false).flags | 0x02); + //Provider.of(context, listen: false).cwtch.UpdateMessageFlags(profileOnion, contact, idx, Provider.of(context, listen: false).flags | 0x02); Provider.of(context, listen: false).flags |= 0x02; - Provider.of(context, listen: false).cwtch.DownloadFile(profileOnion, handle, file.path, manifestPath, widget.fileKey()); + ContactInfoState? contact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle); + if (contact != null) { + Provider + .of(context, listen: false) + .cwtch + .DownloadFile(profileOnion, contact.identifier, file.path, manifestPath, + widget.fileKey()); + } } } catch (e) { print(e); @@ -177,7 +191,7 @@ class FileBubbleState extends State { void _btnResume() async { var profileOnion = Provider.of(context, listen: false).onion; - var handle = Provider.of(context, listen: false).senderHandle; + var handle = Provider.of(context, listen: false).conversationIdentifier; Provider.of(context, listen: false).downloadMarkResumed(widget.fileKey()); Provider.of(context, listen: false).cwtch.VerifyOrResumeDownload(profileOnion, handle, widget.fileKey()); } diff --git a/lib/widgets/invitationbubble.dart b/lib/widgets/invitationbubble.dart index 0e6b9219..e3452d91 100644 --- a/lib/widgets/invitationbubble.dart +++ b/lib/widgets/invitationbubble.dart @@ -36,7 +36,7 @@ class InvitationBubbleState extends State { Widget build(BuildContext context) { var fromMe = Provider.of(context).senderHandle == Provider.of(context).onion; var isGroup = widget.overlay == InviteGroupOverlay; - isAccepted = Provider.of(context).contactList.getContact(widget.inviteTarget) != null; + isAccepted = Provider.of(context).contactList.findContact(widget.inviteTarget) != null; var borderRadiousEh = 15.0; var showGroupInvite = Provider.of(context).isExperimentEnabled(TapirGroupsExperiment); rejected = Provider.of(context).flags & 0x01 == 0x01; @@ -45,7 +45,7 @@ class InvitationBubbleState extends State { // If the sender is not us, then we want to give them a nickname... var senderDisplayStr = ""; if (!fromMe) { - ContactInfoState? contact = Provider.of(context).contactList.getContact(Provider.of(context).senderHandle); + ContactInfoState? contact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle); if (contact != null) { senderDisplayStr = contact.nickname; } else { @@ -69,7 +69,7 @@ class InvitationBubbleState extends State { ? Text(AppLocalizations.of(context)!.groupInviteSettingsWarning) : fromMe ? senderInviteChrome( - AppLocalizations.of(context)!.sendAnInvitation, isGroup ? Provider.of(context).contactList.getContact(widget.inviteTarget)!.nickname : widget.inviteTarget) + AppLocalizations.of(context)!.sendAnInvitation, isGroup ? Provider.of(context).contactList.findContact(widget.inviteTarget)!.nickname : widget.inviteTarget) : (inviteChrome(isGroup ? AppLocalizations.of(context)!.inviteToGroup : AppLocalizations.of(context)!.contactSuggestion, widget.inviteNick, widget.inviteTarget)); Widget wdgDecorations; @@ -130,7 +130,7 @@ class InvitationBubbleState extends State { var profileOnion = Provider.of(context, listen: false).onion; var contact = Provider.of(context, listen: false).onion; var idx = Provider.of(context, listen: false).messageIndex; - Provider.of(context, listen: false).cwtch.UpdateMessageFlags(profileOnion, contact, idx, Provider.of(context, listen: false).flags | 0x01); + //Provider.of(context, listen: false).cwtch.UpdateMessageFlags(profileOnion, contact, idx, Provider.of(context, listen: false).flags | 0x01); Provider.of(context, listen: false).flags |= 0x01; }); } diff --git a/lib/widgets/messagebubble.dart b/lib/widgets/messagebubble.dart index a91378b0..55e67bc2 100644 --- a/lib/widgets/messagebubble.dart +++ b/lib/widgets/messagebubble.dart @@ -40,7 +40,7 @@ class MessageBubbleState extends State { // If the sender is not us, then we want to give them a nickname... var senderDisplayStr = ""; if (!fromMe) { - ContactInfoState? contact = Provider.of(context).contactList.getContact(Provider.of(context).senderHandle); + ContactInfoState? contact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle); if (contact != null) { senderDisplayStr = contact.nickname; } else { diff --git a/lib/widgets/messagelist.dart b/lib/widgets/messagelist.dart index 33406b72..3954ea74 100644 --- a/lib/widgets/messagelist.dart +++ b/lib/widgets/messagelist.dart @@ -76,8 +76,8 @@ class _MessageListState extends State { reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction... itemBuilder: (itemBuilderContext, index) { var profileOnion = Provider.of(outerContext, listen: false).onion; - var contactHandle = Provider.of(outerContext, listen: false).onion; - var messageIndex = Provider.of(outerContext).totalMessages - index - 1; + var contactHandle = Provider.of(outerContext, listen: false).identifier; + var messageIndex = index; return FutureBuilder( future: messageHandler(outerContext, profileOnion, contactHandle, messageIndex), diff --git a/lib/widgets/messagerow.dart b/lib/widgets/messagerow.dart index d4789266..0e9420e0 100644 --- a/lib/widgets/messagerow.dart +++ b/lib/widgets/messagerow.dart @@ -48,8 +48,8 @@ class MessageRowState extends State with SingleTickerProviderStateMi @override Widget build(BuildContext context) { var fromMe = Provider.of(context).senderHandle == Provider.of(context).onion; - var isContact = Provider.of(context).contactList.getContact(Provider.of(context).senderHandle) != null; - var isBlocked = isContact ? Provider.of(context).contactList.getContact(Provider.of(context).senderHandle)!.isBlocked : false; + var isContact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle) != null; + var isBlocked = isContact ? Provider.of(context).contactList.findContact(Provider.of(context).senderHandle)!.isBlocked : false; var actualMessage = Flexible(flex: 3, fit: FlexFit.loose, child: widget.child); _dragAffinity = fromMe ? Alignment.centerRight : Alignment.centerLeft; @@ -60,7 +60,7 @@ class MessageRowState extends State with SingleTickerProviderStateMi var senderDisplayStr = ""; if (!fromMe) { - ContactInfoState? contact = Provider.of(context).contactList.getContact(Provider.of(context).senderHandle); + ContactInfoState? contact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle); if (contact != null) { senderDisplayStr = contact.nickname; } else { @@ -249,7 +249,7 @@ class MessageRowState extends State with SingleTickerProviderStateMi } void _btnGoto() { - selectConversation(context, Provider.of(context, listen: false).senderHandle); + selectConversation(context, Provider.of(context, listen: false).conversationIdentifier); } void _btnAdd() { diff --git a/lib/widgets/quotedmessage.dart b/lib/widgets/quotedmessage.dart index 6c66c354..6d1854bc 100644 --- a/lib/widgets/quotedmessage.dart +++ b/lib/widgets/quotedmessage.dart @@ -34,7 +34,7 @@ class QuotedMessageBubbleState extends State { // If the sender is not us, then we want to give them a nickname... var senderDisplayStr = ""; if (!fromMe) { - ContactInfoState? contact = Provider.of(context).contactList.getContact(Provider.of(context).senderHandle); + ContactInfoState? contact = Provider.of(context).contactList.findContact(Provider.of(context).senderHandle); if (contact != null) { senderDisplayStr = contact.nickname; } else {