2021-06-24 23:10:45 +00:00
|
|
|
import 'dart:convert';
|
2021-07-06 19:46:39 +00:00
|
|
|
import 'package:cwtch/models/message.dart';
|
2021-10-29 23:37:02 +00:00
|
|
|
import 'package:cwtch/models/profileservers.dart';
|
2021-06-24 23:10:45 +00:00
|
|
|
import 'package:cwtch/models/servers.dart';
|
|
|
|
import 'package:cwtch/notification_manager.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
|
|
|
|
import 'package:cwtch/torstatus.dart';
|
|
|
|
|
2021-06-25 05:30:46 +00:00
|
|
|
import '../config.dart';
|
2021-06-24 23:10:45 +00:00
|
|
|
import '../errorHandler.dart';
|
|
|
|
import '../model.dart';
|
|
|
|
import '../settings.dart';
|
|
|
|
|
|
|
|
// Class that handles libcwtch-go events (received either via ffi with an isolate or gomobile over a method channel from kotlin)
|
|
|
|
// Takes Notifiers and triggers them on appropriate events
|
|
|
|
class CwtchNotifier {
|
|
|
|
late ProfileListState profileCN;
|
|
|
|
late Settings settings;
|
|
|
|
late ErrorHandler error;
|
|
|
|
late TorStatus torStatus;
|
|
|
|
late NotificationsManager notificationManager;
|
|
|
|
late AppState appState;
|
2021-10-29 23:37:02 +00:00
|
|
|
late ServerListState serverListState;
|
2021-06-24 23:10:45 +00:00
|
|
|
|
2021-11-25 23:59:54 +00:00
|
|
|
CwtchNotifier(
|
|
|
|
ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN, NotificationsManager notificationManagerP, AppState appStateCN, ServerListState serverListStateCN) {
|
2021-06-24 23:10:45 +00:00
|
|
|
profileCN = pcn;
|
|
|
|
settings = settingsCN;
|
|
|
|
error = errorCN;
|
|
|
|
torStatus = torStatusCN;
|
|
|
|
notificationManager = notificationManagerP;
|
|
|
|
appState = appStateCN;
|
2021-10-29 23:37:02 +00:00
|
|
|
serverListState = serverListStateCN;
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void handleMessage(String type, dynamic data) {
|
2021-11-18 23:44:54 +00:00
|
|
|
EnvironmentConfig.debugLog("NewEvent $type $data");
|
2021-06-24 23:10:45 +00:00
|
|
|
switch (type) {
|
|
|
|
case "CwtchStarted":
|
|
|
|
appState.SetCwtchInit();
|
|
|
|
break;
|
|
|
|
case "CwtchStartError":
|
|
|
|
appState.SetAppError(data["Error"]);
|
|
|
|
break;
|
|
|
|
case "NewPeer":
|
2021-11-18 23:44:54 +00:00
|
|
|
EnvironmentConfig.debugLog("NewPeer $data");
|
2021-06-24 23:10:45 +00:00
|
|
|
// 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;
|
2021-11-18 23:44:54 +00:00
|
|
|
case "ContactCreated":
|
|
|
|
EnvironmentConfig.debugLog("NewServer $data");
|
2021-06-24 23:10:45 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(
|
|
|
|
data["ProfileOnion"],
|
2021-11-25 23:59:54 +00:00
|
|
|
int.parse(data["ConversationID"]),
|
2021-06-24 23:10:45 +00:00
|
|
|
data["RemotePeer"],
|
|
|
|
nickname: data["nick"],
|
|
|
|
status: data["status"],
|
|
|
|
imagePath: data["picture"],
|
2021-07-09 22:16:06 +00:00
|
|
|
authorization: stringToContactAuthorization(data["authorization"]),
|
2021-06-24 23:10:45 +00:00
|
|
|
savePeerHistory: data["saveConversationHistory"] == null ? "DeleteHistoryConfirmed" : data["saveConversationHistory"],
|
|
|
|
numMessages: int.parse(data["numMessages"]),
|
|
|
|
numUnread: int.parse(data["unread"]),
|
|
|
|
isGroup: data["isGroup"] == true,
|
|
|
|
server: data["groupServer"],
|
2021-08-27 20:46:13 +00:00
|
|
|
archived: data["isArchived"] == true,
|
2021-06-24 23:10:45 +00:00
|
|
|
lastMessageTime: DateTime.now(), //show at the top of the contact list even if no messages yet
|
|
|
|
));
|
|
|
|
break;
|
2021-10-29 23:37:02 +00:00
|
|
|
case "NewServer":
|
2021-11-02 02:29:58 +00:00
|
|
|
EnvironmentConfig.debugLog("NewServer $data");
|
2021-11-25 23:59:54 +00:00
|
|
|
serverListState.add(data["Onion"], data["ServerBundle"], data["Running"] == "true", data["Description"], data["Autostart"] == "true", data["StorageType"] == "storage-password");
|
2021-11-02 02:29:58 +00:00
|
|
|
break;
|
|
|
|
case "ServerIntentUpdate":
|
|
|
|
EnvironmentConfig.debugLog("ServerIntentUpdate $data");
|
|
|
|
var server = serverListState.getServer(data["Identity"]);
|
|
|
|
if (server != null) {
|
|
|
|
server.setRunning(data["Intent"] == "running");
|
|
|
|
}
|
2021-10-29 23:37:02 +00:00
|
|
|
break;
|
2021-06-24 23:10:45 +00:00
|
|
|
case "GroupCreated":
|
|
|
|
// Retrieve Server Status from Cache...
|
|
|
|
String status = "";
|
2021-10-29 23:37:02 +00:00
|
|
|
RemoteServerInfoState? serverInfoState = profileCN.getProfile(data["ProfileOnion"])?.serverList.getServer(data["GroupServer"]);
|
2021-06-24 23:10:45 +00:00
|
|
|
if (serverInfoState != null) {
|
|
|
|
status = serverInfoState.status;
|
|
|
|
}
|
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"]) == null) {
|
2021-11-18 23:44:54 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(data["ProfileOnion"], data["ConversationID"], data["GroupID"],
|
2021-07-13 21:46:47 +00:00
|
|
|
authorization: ContactAuthorization.approved,
|
|
|
|
imagePath: data["PicturePath"],
|
|
|
|
nickname: data["GroupName"],
|
|
|
|
status: status,
|
|
|
|
server: data["GroupServer"],
|
|
|
|
isGroup: true,
|
|
|
|
lastMessageTime: DateTime.now()));
|
2021-06-24 23:10:45 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["GroupID"], DateTime.now());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "PeerDeleted":
|
|
|
|
profileCN.delete(data["Identity"]);
|
|
|
|
// todo standarize
|
|
|
|
error.handleUpdate("deleteprofile.success");
|
|
|
|
break;
|
2021-11-04 01:56:53 +00:00
|
|
|
case "ServerDeleted":
|
|
|
|
error.handleUpdate("deletedserver." + data["Status"]);
|
|
|
|
if (data["Status"] == "success") {
|
|
|
|
serverListState.delete(data["Identity"]);
|
|
|
|
}
|
|
|
|
break;
|
2021-06-24 23:10:45 +00:00
|
|
|
case "DeleteContact":
|
2021-11-18 23:44:54 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["ConversationID"]);
|
2021-06-24 23:10:45 +00:00
|
|
|
break;
|
|
|
|
case "DeleteGroup":
|
2021-11-18 23:44:54 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.removeContact(data["ConversationID"]);
|
2021-06-24 23:10:45 +00:00
|
|
|
break;
|
|
|
|
case "PeerStateChange":
|
2021-11-18 23:44:54 +00:00
|
|
|
ContactInfoState? contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]);
|
2021-06-24 23:10:45 +00:00
|
|
|
if (contact != null) {
|
|
|
|
if (data["ConnectionState"] != null) {
|
|
|
|
contact.status = data["ConnectionState"];
|
|
|
|
}
|
|
|
|
if (data["authorization"] != null) {
|
2021-07-09 22:16:06 +00:00
|
|
|
contact.authorization = stringToContactAuthorization(data["authorization"]);
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
// contact.[status/isBlocked] might change the list's sort order
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.resort();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "NewMessageFromPeer":
|
|
|
|
notificationManager.notify("New Message From Peer!");
|
2021-11-18 23:44:54 +00:00
|
|
|
var identifier = int.parse(data["ConversationID"]);
|
2021-12-06 20:25:17 +00:00
|
|
|
var messageID = int.parse(data["Index"]);
|
|
|
|
var timestamp = DateTime.tryParse(data['TimestampReceived'])!;
|
|
|
|
var senderHandle = data['RemotePeer'];
|
|
|
|
var senderImage = data['Picture'];
|
2021-07-08 20:28:30 +00:00
|
|
|
|
2021-12-01 12:17:48 +00:00
|
|
|
// We might not have received a contact created for this contact yet...
|
|
|
|
// In that case the **next** event we receive will actually update these values...
|
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier) != null) {
|
|
|
|
if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != identifier) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.unreadMessages++;
|
|
|
|
} else {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.newMarker++;
|
|
|
|
}
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(identifier, DateTime.now());
|
2021-12-06 20:25:17 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.updateMessageCache(identifier, messageID, timestamp, senderHandle, senderImage, data["Data"], "");
|
2021-12-03 19:28:10 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages++;
|
2021-12-01 12:17:48 +00:00
|
|
|
|
|
|
|
// 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(identifier)!.isOnline() == false) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.status = "Authenticated";
|
|
|
|
}
|
2021-07-08 20:28:30 +00:00
|
|
|
}
|
|
|
|
|
2021-06-24 23:10:45 +00:00
|
|
|
break;
|
|
|
|
case "PeerAcknowledgement":
|
|
|
|
// We don't use these anymore, IndexedAcknowledgement is more suited to the UI front end...
|
|
|
|
break;
|
|
|
|
case "IndexedAcknowledgement":
|
2021-12-03 19:28:10 +00:00
|
|
|
var conversation = int.parse(data["ConversationID"]);
|
2021-12-06 20:25:17 +00:00
|
|
|
var messageID = int.parse(data["Index"]);
|
|
|
|
|
2021-12-03 19:28:10 +00:00
|
|
|
var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation);
|
2021-06-24 23:10:45 +00:00
|
|
|
// We return -1 for protocol message acks if there is no message
|
2021-12-06 20:25:17 +00:00
|
|
|
if (messageID == -1) break;
|
|
|
|
var key = contact!.getMessageKeyOrFail(conversation, messageID, contact.lastMessageTime);
|
2021-06-24 23:10:45 +00:00
|
|
|
if (key == null) break;
|
|
|
|
try {
|
2021-07-06 19:46:39 +00:00
|
|
|
var message = Provider.of<MessageMetadata>(key.currentContext!, listen: false);
|
2021-06-24 23:10:45 +00:00
|
|
|
if (message == null) break;
|
2021-07-08 20:28:30 +00:00
|
|
|
// 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.
|
2021-12-03 19:28:10 +00:00
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.isOnline() == false) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.status = "Authenticated";
|
2021-07-08 20:28:30 +00:00
|
|
|
}
|
2021-06-24 23:10:45 +00:00
|
|
|
message.ackd = true;
|
|
|
|
} catch (e) {
|
|
|
|
// ignore, we received an ack for a message that hasn't loaded onto the screen yet...
|
|
|
|
// the protocol was faster than the ui....yay?
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "NewMessageFromGroup":
|
2021-11-18 23:44:54 +00:00
|
|
|
var identifier = int.parse(data["ConversationID"]);
|
2021-06-24 23:10:45 +00:00
|
|
|
if (data["ProfileOnion"] != data["RemotePeer"]) {
|
2021-11-01 22:03:05 +00:00
|
|
|
var idx = int.parse(data["Index"]);
|
2021-12-06 20:25:17 +00:00
|
|
|
var senderHandle = data['RemotePeer'];
|
|
|
|
var senderImage = data['Picture'];
|
|
|
|
var timestampSent = DateTime.tryParse(data['TimestampSent'])!;
|
2021-11-18 23:44:54 +00:00
|
|
|
var currentTotal = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages;
|
2021-11-01 22:03:05 +00:00
|
|
|
|
|
|
|
// Only bother to do anything if we know about the group and the provided index is greater than our current total...
|
2021-11-01 22:15:12 +00:00
|
|
|
if (currentTotal != null && idx >= currentTotal) {
|
2021-12-06 20:25:17 +00:00
|
|
|
profileCN
|
|
|
|
.getProfile(data["ProfileOnion"])
|
|
|
|
?.contactList
|
|
|
|
.getContact(identifier)!
|
|
|
|
.updateMessageCache(identifier, idx, timestampSent, senderHandle, senderImage, data["Data"], data["Signature"]);
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages++;
|
2021-11-01 22:03:05 +00:00
|
|
|
|
2021-11-02 20:47:35 +00:00
|
|
|
//if not currently open
|
2021-11-18 23:44:54 +00:00
|
|
|
if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != identifier) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.unreadMessages++;
|
2021-11-10 23:52:34 +00:00
|
|
|
} else {
|
2021-11-18 23:44:54 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.newMarker++;
|
2021-11-02 20:47:35 +00:00
|
|
|
}
|
2021-11-01 22:03:05 +00:00
|
|
|
|
2021-11-02 20:47:35 +00:00
|
|
|
// TODO: There are 2 timestamps associated with a new group message - time sent and time received.
|
|
|
|
// Sent refers to the time a profile alleges they sent a message
|
|
|
|
// Received refers to the time we actually saw the message from the server
|
|
|
|
// These can obviously be very different for legitimate reasons.
|
|
|
|
// We also maintain a relative hash-link through PreviousMessageSignature which is the ground truth for
|
|
|
|
// order.
|
|
|
|
// In the future we will want to combine these 3 ordering mechanisms into a cohesive view of the timeline
|
|
|
|
// For now we perform some minimal checks on the sent timestamp to use to provide a useful ordering for honest contacts
|
|
|
|
// and ensure that malicious contacts in groups can only set this timestamp to a value within the range of `last seen message time`
|
|
|
|
// and `local now`.
|
2021-11-25 23:59:54 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(identifier, timestampSent.toLocal());
|
2021-11-02 20:47:35 +00:00
|
|
|
notificationManager.notify("New Message From Group!");
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-12-01 12:17:48 +00:00
|
|
|
// This is not dealt with by IndexedAcknowledgment
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "MessageCounterResync":
|
|
|
|
var contactHandle = data["RemotePeer"];
|
|
|
|
if (contactHandle == null || contactHandle == "") contactHandle = data["GroupID"];
|
2021-11-01 22:03:05 +00:00
|
|
|
var total = int.parse(data["Data"]);
|
2021-11-18 23:44:54 +00:00
|
|
|
if (total != profileCN.getProfile(data["Identity"])?.contactList.findContact(contactHandle)!.totalMessages) {
|
|
|
|
profileCN.getProfile(data["Identity"])?.contactList.findContact(contactHandle)!.totalMessages = total;
|
2021-11-01 22:03:05 +00:00
|
|
|
}
|
2021-06-24 23:10:45 +00:00
|
|
|
break;
|
2021-09-29 20:19:56 +00:00
|
|
|
case "SendMessageToPeerError":
|
|
|
|
// Ignore
|
|
|
|
break;
|
2021-06-24 23:10:45 +00:00
|
|
|
case "IndexedFailure":
|
2021-12-03 19:28:10 +00:00
|
|
|
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) {
|
2021-07-06 19:46:39 +00:00
|
|
|
var message = Provider.of<MessageMetadata>(key.currentContext!, listen: false);
|
2021-06-24 23:10:45 +00:00
|
|
|
message.error = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "AppError":
|
2021-06-25 05:30:46 +00:00
|
|
|
EnvironmentConfig.debugLog("New App Error: $data");
|
2021-06-24 23:10:45 +00:00
|
|
|
// special case for delete error (todo: standardize cwtch errors)
|
|
|
|
if (data["Error"] == "Password did not match") {
|
|
|
|
error.handleUpdate("deleteprofile.error");
|
|
|
|
} else if (data["Data"] != null) {
|
|
|
|
error.handleUpdate(data["Data"]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "UpdateGlobalSettings":
|
|
|
|
settings.handleUpdate(jsonDecode(data["Data"]));
|
|
|
|
break;
|
2021-11-25 23:59:54 +00:00
|
|
|
case "UpdatedProfileAttribute":
|
|
|
|
if (data["Key"] == "public.profile.name") {
|
2021-06-24 23:10:45 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.nickname = data["Data"];
|
|
|
|
} else {
|
2021-06-25 05:30:46 +00:00
|
|
|
EnvironmentConfig.debugLog("unhandled set attribute event: ${data['Key']}");
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "NetworkError":
|
|
|
|
var isOnline = data["Status"] == "Success";
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.isOnline = isOnline;
|
|
|
|
break;
|
|
|
|
case "ACNStatus":
|
2021-06-25 05:30:46 +00:00
|
|
|
EnvironmentConfig.debugLog("acn status: $data");
|
2021-06-24 23:10:45 +00:00
|
|
|
torStatus.handleUpdate(int.parse(data["Progress"]), data["Status"]);
|
|
|
|
break;
|
|
|
|
case "ACNVersion":
|
2021-06-25 05:30:46 +00:00
|
|
|
EnvironmentConfig.debugLog("acn version: $data");
|
2021-06-24 23:10:45 +00:00
|
|
|
torStatus.updateVersion(data["Data"]);
|
|
|
|
break;
|
|
|
|
case "UpdateServerInfo":
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.replaceServers(data["ServerList"]);
|
|
|
|
break;
|
|
|
|
case "NewGroup":
|
|
|
|
String invite = data["GroupInvite"].toString();
|
|
|
|
if (invite.startsWith("torv3")) {
|
|
|
|
String inviteJson = new String.fromCharCodes(base64Decode(invite.substring(5)));
|
|
|
|
dynamic groupInvite = jsonDecode(inviteJson);
|
|
|
|
|
|
|
|
// Retrieve Server Status from Cache...
|
|
|
|
String status = "";
|
2021-10-29 23:37:02 +00:00
|
|
|
RemoteServerInfoState? serverInfoState = profileCN.getProfile(data["ProfileOnion"])!.serverList.getServer(groupInvite["ServerHost"]);
|
2021-06-24 23:10:45 +00:00
|
|
|
if (serverInfoState != null) {
|
|
|
|
status = serverInfoState.status;
|
|
|
|
}
|
|
|
|
|
2021-11-18 23:44:54 +00:00
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(groupInvite["GroupID"]) == null) {
|
2021-12-01 12:17:48 +00:00
|
|
|
var identifier = int.parse(data["ConversationID"]);
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.add(ContactInfoState(data["ProfileOnion"], identifier, groupInvite["GroupID"],
|
2021-07-09 22:16:06 +00:00
|
|
|
authorization: ContactAuthorization.approved,
|
2021-06-24 23:10:45 +00:00
|
|
|
imagePath: data["PicturePath"],
|
|
|
|
nickname: groupInvite["GroupName"],
|
|
|
|
server: groupInvite["ServerHost"],
|
|
|
|
status: status,
|
|
|
|
isGroup: true,
|
2021-07-15 17:57:17 +00:00
|
|
|
lastMessageTime: DateTime.fromMillisecondsSinceEpoch(0)));
|
2021-12-01 12:17:48 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(identifier, DateTime.fromMillisecondsSinceEpoch(0));
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "AcceptGroupInvite":
|
2021-06-25 05:30:46 +00:00
|
|
|
EnvironmentConfig.debugLog("accept group invite");
|
2021-06-24 23:10:45 +00:00
|
|
|
|
2021-07-09 22:16:06 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.authorization = ContactAuthorization.approved;
|
2021-07-15 17:57:17 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["GroupID"], DateTime.fromMillisecondsSinceEpoch(0));
|
2021-06-24 23:10:45 +00:00
|
|
|
break;
|
|
|
|
case "ServerStateChange":
|
|
|
|
// Update the Server Cache
|
2021-12-01 12:17:48 +00:00
|
|
|
//EnvironmentConfig.debugLog("server state changes $data");
|
2021-06-24 23:10:45 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.updateServerStatusCache(data["GroupServer"], data["ConnectionState"]);
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.contacts.forEach((contact) {
|
|
|
|
if (contact.isGroup == true && contact.server == data["GroupServer"]) {
|
|
|
|
contact.status = data["ConnectionState"];
|
|
|
|
}
|
|
|
|
});
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.resort();
|
|
|
|
break;
|
|
|
|
case "SetGroupAttribute":
|
|
|
|
if (data["Key"] == "local.name") {
|
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"]) != null) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.nickname = data["Data"];
|
|
|
|
}
|
2021-08-27 20:46:13 +00:00
|
|
|
} else if (data["Key"] == "local.archived") {
|
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"]) != null) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.isArchived = data["Data"] == "true";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
EnvironmentConfig.debugLog("unhandled set group attribute event: ${data['Key']}");
|
|
|
|
}
|
|
|
|
break;
|
2021-08-27 21:02:16 +00:00
|
|
|
case "SetPeerAttribute":
|
2021-08-27 20:46:13 +00:00
|
|
|
if (data["Key"] == "local.name") {
|
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"]) != null) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.nickname = data["Data"];
|
|
|
|
}
|
|
|
|
} else if (data["Key"] == "local.archived") {
|
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"]) != null) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.isArchived = data["Data"] == "true";
|
|
|
|
}
|
2021-09-21 20:31:11 +00:00
|
|
|
} else if (data["Key"] == "LastKnowSignature") {
|
|
|
|
// group syncing information that isn't relevant to the UI...
|
2021-06-24 23:10:45 +00:00
|
|
|
} else {
|
2021-08-27 21:02:16 +00:00
|
|
|
EnvironmentConfig.debugLog("unhandled set peer attribute event: ${data['Key']}");
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "NewRetValMessageFromPeer":
|
2021-12-01 12:17:48 +00:00
|
|
|
if (data["Path"] == "profile.name") {
|
|
|
|
if (data["Data"].toString().trim().length > 0) {
|
|
|
|
// Update locally on the UI...
|
|
|
|
if (profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"]) != null) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.contactList.findContact(data["RemotePeer"])!.nickname = data["Data"];
|
|
|
|
}
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
2021-12-01 12:17:48 +00:00
|
|
|
} else if (data['Path'] == "profile.picture") {
|
|
|
|
// Not yet..
|
2021-06-24 23:10:45 +00:00
|
|
|
} else {
|
2021-12-01 12:17:48 +00:00
|
|
|
EnvironmentConfig.debugLog("unhandled ret val event: ${data['Path']}");
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
break;
|
2021-09-21 21:57:40 +00:00
|
|
|
case "ManifestSaved":
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.downloadMarkManifest(data["FileKey"]);
|
|
|
|
break;
|
|
|
|
case "FileDownloadProgressUpdate":
|
2021-11-04 22:31:50 +00:00
|
|
|
var progress = int.parse(data["Progress"]);
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.downloadUpdate(data["FileKey"], progress, int.parse(data["FileSizeInChunks"]));
|
|
|
|
// progress == -1 is a "download was interrupted" message and should contain a path
|
|
|
|
if (progress < 0) {
|
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.downloadSetPath(data["FileKey"], data["FilePath"]);
|
|
|
|
}
|
2021-09-21 21:57:40 +00:00
|
|
|
break;
|
|
|
|
case "FileDownloaded":
|
2021-09-29 20:31:01 +00:00
|
|
|
profileCN.getProfile(data["ProfileOnion"])?.downloadMarkFinished(data["FileKey"], data["FilePath"]);
|
2021-09-21 21:57:40 +00:00
|
|
|
break;
|
2021-06-24 23:10:45 +00:00
|
|
|
default:
|
2021-06-25 05:30:46 +00:00
|
|
|
EnvironmentConfig.debugLog("unhandled event: $type");
|
2021-06-24 23:10:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|