From c42be6224d33465760119ce334ffc9a2094f5bb6 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 3 Dec 2021 11:28:10 -0800 Subject: [PATCH] Porting Android over to new API --- .../kotlin/im/cwtch/flwtch/FlwtchWorker.kt | 105 +++++++++--------- .../kotlin/im/cwtch/flwtch/MainActivity.kt | 1 + lib/cwtch/cwtch.dart | 4 - lib/cwtch/cwtchNotifier.dart | 40 ++----- lib/cwtch/ffi.dart | 21 ---- lib/cwtch/gomobile.dart | 75 +++++-------- lib/model.dart | 15 ++- lib/models/messages/filemessage.dart | 5 +- lib/models/messages/invitemessage.dart | 5 +- lib/models/messages/quotedmessage.dart | 4 +- lib/models/messages/textmessage.dart | 9 +- lib/widgets/contactrow.dart | 2 +- lib/widgets/messagelist.dart | 2 +- lib/widgets/messageloadingbubble.dart | 5 - lib/widgets/messagerow.dart | 8 +- 15 files changed, 132 insertions(+), 169 deletions(-) diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt index c82d44ff..7adbdfa9 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt @@ -181,61 +181,69 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : Cwtch.loadProfiles(pass) } "GetMessage" -> { - val profile = (a.get("profile") as? String) ?: "" - val handle = (a.get("contact") as? String) ?: "" - val indexI = a.getInt("index") - return Result.success(Data.Builder().putString("result", Cwtch.getMessage(profile, handle, indexI.toLong())).build()) + val profile = (a.get("ProfileOnion") as? String) ?: "" + val conversation = a.getInt("conversation").toLong() + val indexI = a.getInt("index").toLong() + return Result.success(Data.Builder().putString("result", Cwtch.getMessage(profile, conversation, indexI)).build()) + } + "GetMessageByID" -> { + val profile = (a.get("ProfileOnion") as? String) ?: "" + val conversation = a.getInt("conversation").toLong() + val id = a.getInt("id").toLong() + return Result.success(Data.Builder().putString("result", Cwtch.getMessageByID(profile, conversation, id)).build()) } "GetMessageByContentHash" -> { - val profile = (a.get("profile") as? String) ?: "" - val handle = (a.get("contact") as? String) ?: "" - val contentHash = (a.get("contentHash") as? String) ?: "" - return Result.success(Data.Builder().putString("result", Cwtch.getMessagesByContentHash(profile, handle, contentHash)).build()) - } - "UpdateMessageFlags" -> { - val profile = (a.get("profile") as? String) ?: "" - val handle = (a.get("contact") as? String) ?: "" - val midx = (a.get("midx") as? Long) ?: 0 - val flags = (a.get("flags") as? Long) ?: 0 - Cwtch.updateMessageFlags(profile, handle, midx, flags) - } - "AcceptContact" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val handle = (a.get("handle") as? String) ?: "" - Cwtch.acceptContact(profile, handle) + val conversation = a.getInt("conversation").toLong() + val contentHash = (a.get("contentHash") as? String) ?: "" + return Result.success(Data.Builder().putString("result", Cwtch.getMessagesByContentHash(profile, conversation, contentHash)).build()) + } + "UpdateMessageAttribute" -> { + val profile = (a.get("ProfileOnion") as? String) ?: "" + val conversation = a.getInt("conversation").toLong() + val channel = a.getInt("chanenl").toLong() + val midx = a.getInt("midx").toLong() + val key = (a.get("key") as? String) ?: "" + val value = (a.get("value") as? String) ?: "" + Cwtch.setMessageAttribute(profile, conversation, channel, midx, key, value) + } + "AcceptConversation" -> { + val profile = (a.get("ProfileOnion") as? String) ?: "" + val conversation = a.getInt("conversation").toLong() + Cwtch.acceptConversation(profile, conversation) } "BlockContact" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val handle = (a.get("handle") as? String) ?: "" - Cwtch.blockContact(profile, handle) + val conversation = a.getInt("conversation").toLong() + Cwtch.blockContact(profile, conversation) } "SendMessage" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val handle = (a.get("handle") as? String) ?: "" + val conversation = a.getInt("conversation").toLong() val message = (a.get("message") as? String) ?: "" - Cwtch.sendMessage(profile, handle, message) + Cwtch.sendMessage(profile, conversation, message) } "SendInvitation" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val handle = (a.get("handle") as? String) ?: "" - val target = (a.get("target") as? String) ?: "" - Cwtch.sendInvitation(profile, handle, target) + val conversation = a.getInt("conversation").toLong() + val target = (a.get("target") as? Long) ?: -1 + Cwtch.sendInvitation(profile, conversation, target) } "ShareFile" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val handle = (a.get("handle") as? String) ?: "" + val conversation = a.getInt("conversation").toLong() val filepath = (a.get("filepath") as? String) ?: "" - Cwtch.shareFile(profile, handle, filepath) + Cwtch.shareFile(profile, conversation, filepath) } "DownloadFile" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val handle = (a.get("handle") as? String) ?: "" + val conversation = a.getInt("conversation").toLong() val filepath = (a.get("filepath") as? String) ?: "" val manifestpath = (a.get("manifestpath") as? String) ?: "" val filekey = (a.get("filekey") as? String) ?: "" // FIXME: Prevent spurious calls by Intent if (profile != "") { - Cwtch.downloadFile(profile, handle, filepath, manifestpath, filekey) + Cwtch.downloadFile(profile, conversation, filepath, manifestpath, filekey) } } "CheckDownloadStatus" -> { @@ -245,9 +253,9 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : } "VerifyOrResumeDownload" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val handle = (a.get("handle") as? String) ?: "" + val conversation = a.getInt("conversation").toLong() val fileKey = (a.get("fileKey") as? String) ?: "" - Cwtch.verifyOrResumeDownload(profile, handle, fileKey) + Cwtch.verifyOrResumeDownload(profile, conversation, fileKey) } "SendProfileEvent" -> { val onion = (a.get("onion") as? String) ?: "" @@ -266,13 +274,6 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : val bundle = (a.get("bundle") as? String) ?: "" Cwtch.importBundle(profile, bundle) } - "SetGroupAttribute" -> { - val profile = (a.get("ProfileOnion") as? String) ?: "" - val groupHandle = (a.get("groupHandle") as? String) ?: "" - val key = (a.get("key") as? String) ?: "" - val value = (a.get("value") as? String) ?: "" - Cwtch.setGroupAttribute(profile, groupHandle, key, value) - } "CreateGroup" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" val server = (a.get("server") as? String) ?: "" @@ -286,18 +287,13 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : } "ArchiveConversation" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val contactHandle = (a.get("handle") as? String) ?: "" - Cwtch.archiveConversation(profile, contactHandle) + val conversation = (a.get("conversation") as? Long) ?: -1 + Cwtch.archiveConversation(profile, conversation) } - "DeleteContact" -> { + "DeleteConversation" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val handle = (a.get("handle") as? String) ?: "" - Cwtch.deleteContact(profile, handle) - } - "RejectInvite" -> { - val profile = (a.get("ProfileOnion") as? String) ?: "" - val groupHandle = (a.get("groupHandle") as? String) ?: "" - Cwtch.rejectInvite(profile, groupHandle) + val conversation = (a.get("conversation") as? Long) ?: -1 + Cwtch.deleteContact(profile, conversation) } "SetProfileAttribute" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" @@ -305,12 +301,12 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : val v = (a.get("Val") as? String) ?: "" Cwtch.setProfileAttribute(profile, key, v) } - "SetContactAttribute" -> { + "SetConversationAttribute" -> { val profile = (a.get("ProfileOnion") as? String) ?: "" - val contact = (a.get("Contact") as? String) ?: "" + val conversation = (a.get("conversation") as? Long) ?: -1 val key = (a.get("Key") as? String) ?: "" val v = (a.get("Val") as? String) ?: "" - Cwtch.setContactAttribute(profile, contact, key, v) + Cwtch.setConversationAttribute(profile, conversation, key, v) } "Shutdown" -> { Cwtch.shutdownCwtch(); @@ -354,7 +350,10 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : val v = (a.get("Val") as? String) ?: "" Cwtch.setServerAttribute(serverOnion, key, v) } - else -> return Result.failure() + else -> { + Log.i("FlwtchWorker", "unknown command: " + method); + return Result.failure() + } } return Result.success() } diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt index d0f6503d..61447ef5 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt @@ -152,6 +152,7 @@ class MainActivity: FlutterActivity() { Log.i("handleCwtch:WorkManager", "canceling ${workInfo.id} bc tags don't include $uniqueTag") WorkManager.getInstance(this).cancelWorkById(workInfo.id) } + WorkManager.getInstance(this).cancelWorkById(workInfo.id) } WorkManager.getInstance(this).pruneWork() diff --git a/lib/cwtch/cwtch.dart b/lib/cwtch/cwtch.dart index 9e82c817..a2606b27 100644 --- a/lib/cwtch/cwtch.dart +++ b/lib/cwtch/cwtch.dart @@ -10,8 +10,6 @@ abstract class Cwtch { // ignore: non_constant_identifier_names Future ReconnectCwtchForeground(); - // ignore: non_constant_identifier_names - void SelectProfile(String onion); // ignore: non_constant_identifier_names void CreateProfile(String nick, String pass); // ignore: non_constant_identifier_names @@ -69,8 +67,6 @@ abstract class Cwtch { // ignore: non_constant_identifier_names void ImportBundle(String profile, String bundle); // ignore: non_constant_identifier_names - 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 SetConversationAttribute(String profile, int conversation, String key, String val); diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index 6adb09b9..c68a89d1 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -139,8 +139,8 @@ class CwtchNotifier { } else { profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.newMarker++; } - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages++; profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(identifier, DateTime.now()); + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages++; // 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 @@ -155,13 +155,12 @@ class CwtchNotifier { // We don't use these anymore, IndexedAcknowledgement is more suited to the UI front end... break; case "IndexedAcknowledgement": - var messageID = data["Index"]; - var identifier = int.parse(data["ConversationID"]); - var idx = identifier.toString() + messageID; - + var conversation = int.parse(data["ConversationID"]); + var message_index = int.parse(data["Index"]); + var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation); // We return -1 for protocol message acks if there is no message - if (idx == "-1") break; - var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.getMessageKey(idx); + if (message_index == -1) break; + var key = contact!.getMessageKeyOrFail(conversation, message_index, contact.lastMessageTime); if (key == null) break; try { var message = Provider.of(key.currentContext!, listen: false); @@ -169,8 +168,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(identifier)!.isOnline() == false) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.status = "Authenticated"; + if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.isOnline() == false) { + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.status = "Authenticated"; } message.ackd = true; } catch (e) { @@ -225,27 +224,12 @@ class CwtchNotifier { // Ignore break; case "IndexedFailure": - var idx = data["Index"]; - var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"])?.getMessageKey(idx); - try { - var message = Provider.of(key!.currentContext!, listen: false); - message.error = true; - } catch (e) { - // ignore, we likely have an old key that has been replaced with an actual signature - } - break; - case "SendMessageToGroupError": - // from me (already displayed - do not update counter) - EnvironmentConfig.debugLog("SendMessageToGroupError: $data"); - var idx = data["Signature"]; - var key = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["GroupID"])!.getMessageKey(idx); - if (key == null) break; - try { + var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]); + var idx = int.parse(data["Index"]); + var key = contact?.getMessageKeyOrFail(contact.identifier, idx, contact.lastMessageTime); + if (key != null) { var message = Provider.of(key.currentContext!, listen: false); - if (message == null) break; message.error = true; - } catch (e) { - // ignore, we likely have an old key that has been replaced with an actual signature } break; case "AppError": diff --git a/lib/cwtch/ffi.dart b/lib/cwtch/ffi.dart index 38448abb..37ea80a8 100644 --- a/lib/cwtch/ffi.dart +++ b/lib/cwtch/ffi.dart @@ -261,16 +261,6 @@ class CwtchFfi implements Cwtch { } } - // ignore: non_constant_identifier_names - void SelectProfile(String onion) async { - var selectProfileC = library.lookup>("c_SelectProfile"); - // ignore: non_constant_identifier_names - final SelectProfile = selectProfileC.asFunction(); - final ut8Onion = onion.toNativeUtf8(); - SelectProfile(ut8Onion, ut8Onion.length); - malloc.free(ut8Onion); - } - // ignore: non_constant_identifier_names void CreateProfile(String nick, String pass) { var createProfileC = library.lookup>("c_CreateProfile"); @@ -460,17 +450,6 @@ class CwtchFfi implements Cwtch { malloc.free(u2); } - @override - // ignore: non_constant_identifier_names - void RejectInvite(String profileOnion, int groupHandle) { - var rejectInvite = library.lookup>("c_RejectInvite"); - // ignore: non_constant_identifier_names - final RejectInvite = rejectInvite.asFunction(); - final u1 = profileOnion.toNativeUtf8(); - RejectInvite(u1, u1.length, groupHandle); - malloc.free(u1); - } - @override // ignore: non_constant_identifier_names void CreateGroup(String profileOnion, String server, String groupName) { diff --git a/lib/cwtch/gomobile.dart b/lib/cwtch/gomobile.dart index a2cac25d..1b4c7fd0 100644 --- a/lib/cwtch/gomobile.dart +++ b/lib/cwtch/gomobile.dart @@ -66,11 +66,6 @@ class CwtchGomobile implements Cwtch { cwtchNotifier.handleMessage(call.method, obj); } - // ignore: non_constant_identifier_names - void SelectProfile(String onion) { - cwtchPlatform.invokeMethod("SelectProfile", {"profile": onion}); - } - // ignore: non_constant_identifier_names void CreateProfile(String nick, String pass) { cwtchPlatform.invokeMethod("CreateProfile", {"nick": nick, "pass": pass}); @@ -87,13 +82,13 @@ class CwtchGomobile implements Cwtch { } // ignore: non_constant_identifier_names - Future GetMessage(String profile, int handle, int index) { - return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "index": index}); + Future GetMessage(String profile, int conversation, int index) { + return cwtchPlatform.invokeMethod("GetMessage", {"ProfileOnion": profile, "conversation": conversation, "index": index}); } // ignore: non_constant_identifier_names - Future GetMessageByID(String profile, int handle, int index) { - return cwtchPlatform.invokeMethod("GetMessageByID", {"profile": profile, "contact": handle, "index": index}); + Future GetMessageByID(String profile, int conversation, int id) { + return cwtchPlatform.invokeMethod("GetMessageByID", {"ProfileOnion": profile, "conversation": conversation, "id": id}); } @override @@ -113,43 +108,43 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void AcceptContact(String profileOnion, int contactHandle) { - cwtchPlatform.invokeMethod("AcceptContact", {"ProfileOnion": profileOnion, "handle": contactHandle}); + void AcceptContact(String profileOnion, int conversation) { + cwtchPlatform.invokeMethod("AcceptContact", {"ProfileOnion": profileOnion, "conversation": conversation}); } @override // ignore: non_constant_identifier_names - void BlockContact(String profileOnion, int contactHandle) { - cwtchPlatform.invokeMethod("BlockContact", {"ProfileOnion": profileOnion, "handle": contactHandle}); + void BlockContact(String profileOnion, int conversation) { + cwtchPlatform.invokeMethod("BlockContact", {"ProfileOnion": profileOnion, "conversation": conversation}); } @override // ignore: non_constant_identifier_names - void SendMessage(String profileOnion, int contactHandle, String message) { - cwtchPlatform.invokeMethod("SendMessage", {"ProfileOnion": profileOnion, "handle": contactHandle, "message": message}); + void SendMessage(String profileOnion, int conversation, String message) { + cwtchPlatform.invokeMethod("SendMessage", {"ProfileOnion": profileOnion, "conversation": conversation, "message": message}); } @override // ignore: non_constant_identifier_names - void SendInvitation(String profileOnion, int contactHandle, int target) { - cwtchPlatform.invokeMethod("SendInvitation", {"ProfileOnion": profileOnion, "handle": contactHandle, "target": target}); + void SendInvitation(String profileOnion, int conversation, int target) { + cwtchPlatform.invokeMethod("SendInvitation", {"ProfileOnion": profileOnion, "conversation": conversation, "target": target}); } @override // ignore: non_constant_identifier_names - void ShareFile(String profileOnion, int contactHandle, String filepath) { - cwtchPlatform.invokeMethod("ShareFile", {"ProfileOnion": profileOnion, "handle": contactHandle, "filepath": filepath}); + void ShareFile(String profileOnion, int conversation, String filepath) { + cwtchPlatform.invokeMethod("ShareFile", {"ProfileOnion": profileOnion, "conversation": conversation, "filepath": filepath}); } @override // ignore: non_constant_identifier_names - 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}); + void DownloadFile(String profileOnion, int conversation, String filepath, String manifestpath, String filekey) { + cwtchPlatform.invokeMethod("DownloadFile", {"ProfileOnion": profileOnion, "conversation": conversation, "filepath": filepath, "manifestpath": manifestpath, "filekey": filekey}); } // ignore: non_constant_identifier_names - void CreateDownloadableFile(String profileOnion, int contactHandle, String filenameSuggestion, String filekey) { - cwtchPlatform.invokeMethod("CreateDownloadableFile", {"ProfileOnion": profileOnion, "handle": contactHandle, "filename": filenameSuggestion, "filekey": filekey}); + void CreateDownloadableFile(String profileOnion, int conversation, String filenameSuggestion, String filekey) { + cwtchPlatform.invokeMethod("CreateDownloadableFile", {"ProfileOnion": profileOnion, "conversation": conversation, "filename": filenameSuggestion, "filekey": filekey}); } @override @@ -160,8 +155,8 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void VerifyOrResumeDownload(String profileOnion, int contactHandle, String filekey) { - cwtchPlatform.invokeMethod("VerifyOrResumeDownload", {"ProfileOnion": profileOnion, "handle": contactHandle, "filekey": filekey}); + void VerifyOrResumeDownload(String profileOnion, int conversation, String filekey) { + cwtchPlatform.invokeMethod("VerifyOrResumeDownload", {"ProfileOnion": profileOnion, "conversation": conversation, "filekey": filekey}); } @override @@ -176,18 +171,6 @@ class CwtchGomobile implements Cwtch { cwtchPlatform.invokeMethod("ImportBundle", {"ProfileOnion": profileOnion, "bundle": bundle}); } - @override - // ignore: non_constant_identifier_names - void SetGroupAttribute(String profileOnion, String groupHandle, String key, String value) { - cwtchPlatform.invokeMethod("SetGroupAttribute", {"ProfileOnion": profileOnion, "groupHandle": groupHandle, "key": key, "value": value}); - } - - @override - // ignore: non_constant_identifier_names - void RejectInvite(String profileOnion, int groupHandle) { - cwtchPlatform.invokeMethod("RejectInvite", {"ProfileOnion": profileOnion, "groupHandle": groupHandle}); - } - @override void CreateGroup(String profileOnion, String server, String groupName) { cwtchPlatform.invokeMethod("CreateGroup", {"ProfileOnion": profileOnion, "server": server, "groupName": groupName}); @@ -195,14 +178,14 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void DeleteContact(String profileOnion, int handle) { - cwtchPlatform.invokeMethod("DeleteContact", {"ProfileOnion": profileOnion, "handle": handle}); + void DeleteContact(String profileOnion, int conversation) { + cwtchPlatform.invokeMethod("DeleteContact", {"ProfileOnion": profileOnion, "conversation": conversation}); } @override // ignore: non_constant_identifier_names - void ArchiveConversation(String profileOnion, int contactHandle) { - cwtchPlatform.invokeMethod("ArchiveConversation", {"ProfileOnion": profileOnion, "handle": contactHandle}); + void ArchiveConversation(String profileOnion, int conversation) { + cwtchPlatform.invokeMethod("ArchiveConversation", {"ProfileOnion": profileOnion, "conversation": conversation}); } @override @@ -213,8 +196,8 @@ class CwtchGomobile implements Cwtch { @override // ignore: non_constant_identifier_names - void SetConversationAttribute(String profile, int contact, String key, String val) { - cwtchPlatform.invokeMethod("SetContactAttribute", {"ProfileOnion": profile, "Contact": contact, "Key": key, "Val": val}); + void SetConversationAttribute(String profile, int conversation, String key, String val) { + cwtchPlatform.invokeMethod("SetContactAttribute", {"ProfileOnion": profile, "conversation": conversation, "Key": key, "Val": val}); } @override @@ -278,12 +261,12 @@ class CwtchGomobile implements Cwtch { } @override - Future GetMessageByContentHash(String profile, int handle, String contentHash) { - return cwtchPlatform.invokeMethod("GetMessageByContentHash", {"profile": profile, "contact": handle, "contentHash": contentHash}); + Future GetMessageByContentHash(String profile, int conversation, String contentHash) { + return cwtchPlatform.invokeMethod("GetMessageByContentHash", {"ProfileOnion": profile, "conversation": conversation, "contentHash": contentHash}); } @override void SetMessageAttribute(String profile, int conversation, int channel, int message, String key, String val) { - cwtchPlatform.invokeMethod("SetMessageAttribute", {"ProfileOnion": profile, "Conversation": conversation, "Channel": channel, "Message": message, "Key": key, "Val": val}); + cwtchPlatform.invokeMethod("SetMessageAttribute", {"ProfileOnion": profile, "conversation": conversation, "Channel": channel, "Message": message, "Key": key, "Val": val}); } } diff --git a/lib/model.dart b/lib/model.dart index 1526d190..a0db9ead 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:cwtch/config.dart'; import 'package:cwtch/widgets/messagerow.dart'; import 'package:flutter/cupertino.dart'; import 'package:cwtch/models/profileservers.dart'; @@ -657,11 +658,23 @@ class ContactInfoState extends ChangeNotifier { } } - GlobalKey getMessageKey(String index) { + GlobalKey getMessageKey(int conversation, int message, DateTime lastread) { + String index = "c: " + conversation.toString() + " m:" + message.toString(); //+ " lr:" +lastMessageTime.toIso8601String(); + //EnvironmentConfig.debugLog("looked up key $index"); if (keys[index] == null) { keys[index] = GlobalKey(); } GlobalKey ret = keys[index]!; return ret; } + + GlobalKey? getMessageKeyOrFail(int conversation, int message, DateTime lastread) { + String index = "c: " + conversation.toString() + " m:" + message.toString(); // + " lr:" +lastMessageTime.toIso8601String(); + + if (keys[index] == null) { + return null; + } + GlobalKey ret = keys[index]!; + return ret; + } } diff --git a/lib/models/messages/filemessage.dart b/lib/models/messages/filemessage.dart index 24c6e152..3097516c 100644 --- a/lib/models/messages/filemessage.dart +++ b/lib/models/messages/filemessage.dart @@ -21,7 +21,6 @@ class FileMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - String idx = this.metadata.conversationIdentifier.toString() + this.metadata.messageID.toString(); dynamic shareObj = jsonDecode(this.content); if (shareObj == null) { return MessageRow(MalformedBubble()); @@ -35,7 +34,9 @@ class FileMessage extends Message { return MessageRow(MalformedBubble()); } - return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize), key: Provider.of(bcontext).getMessageKey(idx)); + var lrt = Provider.of(bcontext).lastMessageTime; + return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize), + key: Provider.of(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt)); }); } diff --git a/lib/models/messages/invitemessage.dart b/lib/models/messages/invitemessage.dart index fb58f083..fda0e7fe 100644 --- a/lib/models/messages/invitemessage.dart +++ b/lib/models/messages/invitemessage.dart @@ -21,7 +21,6 @@ class InviteMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - String idx = this.metadata.conversationIdentifier.toString() + this.metadata.messageID.toString(); String inviteTarget; String inviteNick; String invite = this.content; @@ -40,7 +39,9 @@ class InviteMessage extends Message { return MessageRow(MalformedBubble()); } } - return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite), key: Provider.of(bcontext).getMessageKey(idx)); + var lrt = Provider.of(bcontext).lastMessageTime; + return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite), + key: Provider.of(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt)); }); } diff --git a/lib/models/messages/quotedmessage.dart b/lib/models/messages/quotedmessage.dart index 6ddba3a3..fb835989 100644 --- a/lib/models/messages/quotedmessage.dart +++ b/lib/models/messages/quotedmessage.dart @@ -94,7 +94,7 @@ class QuotedMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - String idx = this.metadata.conversationIdentifier.toString() + this.metadata.messageID.toString(); + var lrt = Provider.of(bcontext).lastMessageTime; return MessageRow( QuotedMessageBubble(message["body"], quotedMessage.then((LocallyIndexedMessage? localIndex) { if (localIndex != null) { @@ -102,7 +102,7 @@ class QuotedMessage extends Message { } return MalformedMessage(this.metadata); })), - key: Provider.of(bcontext).getMessageKey(idx)); + key: Provider.of(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt)); }); } catch (e) { return MalformedMessage(this.metadata).getWidget(context); diff --git a/lib/models/messages/textmessage.dart b/lib/models/messages/textmessage.dart index ac996152..d1f7fd6b 100644 --- a/lib/models/messages/textmessage.dart +++ b/lib/models/messages/textmessage.dart @@ -1,5 +1,8 @@ import 'package:cwtch/models/message.dart'; +import 'package:cwtch/models/messages/malformedmessage.dart'; +import 'package:cwtch/widgets/malformedbubble.dart'; import 'package:cwtch/widgets/messagebubble.dart'; +import 'package:cwtch/widgets/messageloadingbubble.dart'; import 'package:cwtch/widgets/messagerow.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; @@ -32,8 +35,10 @@ class TextMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - String idx = this.metadata.conversationIdentifier.toString() + this.metadata.messageID.toString(); - return MessageRow(MessageBubble(this.content), key: Provider.of(bcontext).getMessageKey(idx)); + var lrt = Provider.of(bcontext).lastMessageTime; + var key = Provider.of(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt); + + return MessageRow(MessageBubble(this.content), key: key); }); } } diff --git a/lib/widgets/contactrow.dart b/lib/widgets/contactrow.dart index d013e28b..93bbb655 100644 --- a/lib/widgets/contactrow.dart +++ b/lib/widgets/contactrow.dart @@ -121,7 +121,7 @@ class _ContactRowState extends State { 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.identifier); + // FIXME This flow is incrorect. Groups never just show up on the contact list anymore Provider.of(context, listen: false).removeContact(contact.onion); } else { Provider.of(context, listen: false).cwtch.BlockContact(Provider.of(context, listen: false).profileOnion, contact.identifier); diff --git a/lib/widgets/messagelist.dart b/lib/widgets/messagelist.dart index 3954ea74..f47b03c9 100644 --- a/lib/widgets/messagelist.dart +++ b/lib/widgets/messagelist.dart @@ -87,7 +87,7 @@ class _MessageListState extends State { // Already includes MessageRow,, return message.getWidget(context); } else { - return Text(''); //MessageLoadingBubble(); + return MessageLoadingBubble(); } }, ); diff --git a/lib/widgets/messageloadingbubble.dart b/lib/widgets/messageloadingbubble.dart index f9605d15..aeba1657 100644 --- a/lib/widgets/messageloadingbubble.dart +++ b/lib/widgets/messageloadingbubble.dart @@ -1,9 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import '../model.dart'; -import 'package:intl/intl.dart'; - -import '../settings.dart'; class MessageLoadingBubble extends StatefulWidget { @override diff --git a/lib/widgets/messagerow.dart b/lib/widgets/messagerow.dart index feaeae15..963a41ab 100644 --- a/lib/widgets/messagerow.dart +++ b/lib/widgets/messagerow.dart @@ -15,6 +15,7 @@ import '../settings.dart'; class MessageRow extends StatefulWidget { final Widget child; + MessageRow(this.child, {Key? key}) : super(key: key); @override @@ -28,9 +29,12 @@ class MessageRowState extends State with SingleTickerProviderStateMi late Alignment _dragAlignment = Alignment.center; Alignment _dragAffinity = Alignment.center; + late int index; + @override void initState() { super.initState(); + index = Provider.of(context, listen: false).messageIndex; _controller = AnimationController(vsync: this); _controller.addListener(() { setState(() { @@ -41,7 +45,9 @@ class MessageRowState extends State with SingleTickerProviderStateMi @override void dispose() { - _controller.dispose(); + if (_controller != null) { + _controller.dispose(); + } super.dispose(); }