Porting Android over to new API
continuous-integration/drone/pr Build is pending Details

This commit is contained in:
Sarah Jamie Lewis 2021-12-03 11:28:10 -08:00
parent d6839c62e3
commit c42be6224d
15 changed files with 132 additions and 169 deletions

View File

@ -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()
}

View File

@ -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()

View File

@ -10,8 +10,6 @@ abstract class Cwtch {
// ignore: non_constant_identifier_names
Future<void> 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);

View File

@ -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<MessageMetadata>(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<MessageMetadata>(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<MessageMetadata>(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":

View File

@ -261,16 +261,6 @@ class CwtchFfi implements Cwtch {
}
}
// ignore: non_constant_identifier_names
void SelectProfile(String onion) async {
var selectProfileC = library.lookup<NativeFunction<get_json_blob_string_function>>("c_SelectProfile");
// ignore: non_constant_identifier_names
final SelectProfile = selectProfileC.asFunction<GetJsonBlobStringFn>();
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<NativeFunction<void_from_string_string_function>>("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<NativeFunction<string_int_to_void_function>>("c_RejectInvite");
// ignore: non_constant_identifier_names
final RejectInvite = rejectInvite.asFunction<VoidFromStringIntFn>();
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) {

View File

@ -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<dynamic> GetMessage(String profile, int handle, int index) {
return cwtchPlatform.invokeMethod("GetMessage", {"profile": profile, "contact": handle, "index": index});
Future<dynamic> GetMessage(String profile, int conversation, int index) {
return cwtchPlatform.invokeMethod("GetMessage", {"ProfileOnion": profile, "conversation": conversation, "index": index});
}
// ignore: non_constant_identifier_names
Future<dynamic> GetMessageByID(String profile, int handle, int index) {
return cwtchPlatform.invokeMethod("GetMessageByID", {"profile": profile, "contact": handle, "index": index});
Future<dynamic> 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});
}
}

View File

@ -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<MessageRowState> getMessageKey(String index) {
GlobalKey<MessageRowState> 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<MessageRowState>();
}
GlobalKey<MessageRowState> ret = keys[index]!;
return ret;
}
GlobalKey<MessageRowState>? 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<MessageRowState> ret = keys[index]!;
return ret;
}
}

View File

@ -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<ContactInfoState>(bcontext).getMessageKey(idx));
var lrt = Provider.of<ContactInfoState>(bcontext).lastMessageTime;
return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize),
key: Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt));
});
}

View File

@ -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<ContactInfoState>(bcontext).getMessageKey(idx));
var lrt = Provider.of<ContactInfoState>(bcontext).lastMessageTime;
return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite),
key: Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt));
});
}

View File

@ -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<ContactInfoState>(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<ContactInfoState>(bcontext).getMessageKey(idx));
key: Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt));
});
} catch (e) {
return MalformedMessage(this.metadata).getWidget(context);

View File

@ -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<ContactInfoState>(bcontext).getMessageKey(idx));
var lrt = Provider.of<ContactInfoState>(bcontext).lastMessageTime;
var key = Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt);
return MessageRow(MessageBubble(this.content), key: key);
});
}
}

View File

@ -121,7 +121,7 @@ class _ContactRowState extends State<ContactRow> {
void _btnReject() {
ContactInfoState contact = Provider.of<ContactInfoState>(context, listen: false);
if (contact.isGroup == true) {
Provider.of<FlwtchState>(context, listen: false).cwtch.RejectInvite(Provider.of<ContactInfoState>(context, listen: false).profileOnion, contact.identifier);
// FIXME This flow is incrorect. Groups never just show up on the contact list anymore
Provider.of<ProfileInfoState>(context, listen: false).removeContact(contact.onion);
} else {
Provider.of<FlwtchState>(context, listen: false).cwtch.BlockContact(Provider.of<ContactInfoState>(context, listen: false).profileOnion, contact.identifier);

View File

@ -87,7 +87,7 @@ class _MessageListState extends State<MessageList> {
// Already includes MessageRow,,
return message.getWidget(context);
} else {
return Text(''); //MessageLoadingBubble();
return MessageLoadingBubble();
}
},
);

View File

@ -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

View File

@ -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<MessageRow> with SingleTickerProviderStateMi
late Alignment _dragAlignment = Alignment.center;
Alignment _dragAffinity = Alignment.center;
late int index;
@override
void initState() {
super.initState();
index = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
_controller = AnimationController(vsync: this);
_controller.addListener(() {
setState(() {
@ -41,7 +45,9 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
@override
void dispose() {
_controller.dispose();
if (_controller != null) {
_controller.dispose();
}
super.dispose();
}