diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index 9bd76e81bb..fdc038d64d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -736,22 +736,18 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a return null } - suspend fun apiSwitchContact(contactId: Long) { - return when (val r = sendCmd(CC.APISwitchContact(contactId))) { - is CR.CmdOk -> {} - else -> { - apiErrorAlert("apiSwitchContact", generalGetString(R.string.error_changing_address), r) - } - } + suspend fun apiSwitchContact(contactId: Long): ConnectionStats? { + val r = sendCmd(CC.APISwitchContact(contactId)) + if (r is CR.ContactSwitchStarted) return r.connectionStats + apiErrorAlert("apiSwitchContact", generalGetString(R.string.error_changing_address), r) + return null } - suspend fun apiSwitchGroupMember(groupId: Long, groupMemberId: Long) { - return when (val r = sendCmd(CC.APISwitchGroupMember(groupId, groupMemberId))) { - is CR.CmdOk -> {} - else -> { - apiErrorAlert("apiSwitchGroupMember", generalGetString(R.string.error_changing_address), r) - } - } + suspend fun apiSwitchGroupMember(groupId: Long, groupMemberId: Long): ConnectionStats? { + val r = sendCmd(CC.APISwitchGroupMember(groupId, groupMemberId)) + if (r is CR.GroupMemberSwitchStarted) return r.connectionStats + apiErrorAlert("apiSwitchGroupMember", generalGetString(R.string.error_changing_address), r) + return null } suspend fun apiAbortSwitchContact(contactId: Long): ConnectionStats? { @@ -3298,6 +3294,8 @@ sealed class CR { @Serializable @SerialName("networkConfig") class NetworkConfig(val networkConfig: NetCfg): CR() @Serializable @SerialName("contactInfo") class ContactInfo(val user: User, val contact: Contact, val connectionStats: ConnectionStats, val customUserProfile: Profile? = null): CR() @Serializable @SerialName("groupMemberInfo") class GroupMemberInfo(val user: User, val groupInfo: GroupInfo, val member: GroupMember, val connectionStats_: ConnectionStats? = null): CR() + @Serializable @SerialName("contactSwitchStarted") class ContactSwitchStarted(val user: User, val contact: Contact, val connectionStats: ConnectionStats): CR() + @Serializable @SerialName("groupMemberSwitchStarted") class GroupMemberSwitchStarted(val user: User, val groupInfo: GroupInfo, val member: GroupMember, val connectionStats: ConnectionStats): CR() @Serializable @SerialName("contactSwitchAborted") class ContactSwitchAborted(val user: User, val contact: Contact, val connectionStats: ConnectionStats): CR() @Serializable @SerialName("groupMemberSwitchAborted") class GroupMemberSwitchAborted(val user: User, val groupInfo: GroupInfo, val member: GroupMember, val connectionStats: ConnectionStats): CR() @Serializable @SerialName("contactCode") class ContactCode(val user: User, val contact: Contact, val connectionCode: String): CR() @@ -3414,6 +3412,8 @@ sealed class CR { is NetworkConfig -> "networkConfig" is ContactInfo -> "contactInfo" is GroupMemberInfo -> "groupMemberInfo" + is ContactSwitchStarted -> "contactSwitchStarted" + is GroupMemberSwitchStarted -> "groupMemberSwitchStarted" is ContactSwitchAborted -> "contactSwitchAborted" is GroupMemberSwitchAborted -> "groupMemberSwitchAborted" is ContactCode -> "contactCode" @@ -3527,6 +3527,8 @@ sealed class CR { is NetworkConfig -> json.encodeToString(networkConfig) is ContactInfo -> withUser(user, "contact: ${json.encodeToString(contact)}\nconnectionStats: ${json.encodeToString(connectionStats)}") is GroupMemberInfo -> withUser(user, "group: ${json.encodeToString(groupInfo)}\nmember: ${json.encodeToString(member)}\nconnectionStats: ${json.encodeToString(connectionStats_)}") + is ContactSwitchStarted -> withUser(user, "contact: ${json.encodeToString(contact)}\nconnectionStats: ${json.encodeToString(connectionStats)}") + is GroupMemberSwitchStarted -> withUser(user, "group: ${json.encodeToString(groupInfo)}\nmember: ${json.encodeToString(member)}\nconnectionStats: ${json.encodeToString(connectionStats)}") is ContactSwitchAborted -> withUser(user, "contact: ${json.encodeToString(contact)}\nconnectionStats: ${json.encodeToString(connectionStats)}") is GroupMemberSwitchAborted -> withUser(user, "group: ${json.encodeToString(groupInfo)}\nmember: ${json.encodeToString(member)}\nconnectionStats: ${json.encodeToString(connectionStats)}") is ContactCode -> withUser(user, "contact: ${json.encodeToString(contact)}\nconnectionCode: $connectionCode") diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt index 00bf8d5444..75edc77c05 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt @@ -83,7 +83,7 @@ fun ChatInfoView( switchContactAddress = { showSwitchAddressAlert(switchAddress = { withApi { - chatModel.controller.apiSwitchContact(contact.contactId) + connStats.value = chatModel.controller.apiSwitchContact(contact.contactId) } }) }, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt index cd0b1c460b..1ed56a8874 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupMemberInfoView.kt @@ -101,7 +101,7 @@ fun GroupMemberInfoView( switchMemberAddress = { showSwitchAddressAlert(switchAddress = { withApi { - chatModel.controller.apiSwitchGroupMember(groupInfo.apiId, member.groupMemberId) + connStats.value = chatModel.controller.apiSwitchGroupMember(groupInfo.apiId, member.groupMemberId) } }) }, diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 3881835fb8..3fb4833d66 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -480,12 +480,16 @@ func apiGroupMemberInfo(_ groupId: Int64, _ groupMemberId: Int64) throws -> (Con throw r } -func apiSwitchContact(contactId: Int64) async throws { - try await sendCommandOkResp(.apiSwitchContact(contactId: contactId)) +func apiSwitchContact(contactId: Int64) throws -> ConnectionStats { + let r = chatSendCmdSync(.apiSwitchContact(contactId: contactId)) + if case let .contactSwitchStarted(_, _, connectionStats) = r { return connectionStats } + throw r } -func apiSwitchGroupMember(_ groupId: Int64, _ groupMemberId: Int64) async throws { - try await sendCommandOkResp(.apiSwitchGroupMember(groupId: groupId, groupMemberId: groupMemberId)) +func apiSwitchGroupMember(_ groupId: Int64, _ groupMemberId: Int64) throws -> ConnectionStats { + let r = chatSendCmdSync(.apiSwitchGroupMember(groupId: groupId, groupMemberId: groupMemberId)) + if case let .groupMemberSwitchStarted(_, _, _, connectionStats) = r { return connectionStats } + throw r } func apiAbortSwitchContact(_ contactId: Int64) throws -> ConnectionStats { diff --git a/apps/ios/Shared/Views/Chat/ChatInfoView.swift b/apps/ios/Shared/Views/Chat/ChatInfoView.swift index 847efa9e25..a76ed8aa9a 100644 --- a/apps/ios/Shared/Views/Chat/ChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/ChatInfoView.swift @@ -368,7 +368,8 @@ struct ChatInfoView: View { private func switchContactAddress() { Task { do { - try await apiSwitchContact(contactId: contact.apiId) + let stats = try apiSwitchContact(contactId: contact.apiId) + connectionStats = stats } catch let error { logger.error("switchContactAddress apiSwitchContact error: \(responseError(error))") let a = getErrorAlert(error, "Error changing address") diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift index 71ef5a68d5..1ff145b08c 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift @@ -356,7 +356,8 @@ struct GroupMemberInfoView: View { private func switchMemberAddress() { Task { do { - try await apiSwitchGroupMember(groupInfo.apiId, member.groupMemberId) + let stats = try apiSwitchGroupMember(groupInfo.apiId, member.groupMemberId) + connectionStats = stats } catch let error { logger.error("switchMemberAddress apiSwitchGroupMember error: \(responseError(error))") let a = getErrorAlert(error, "Error changing address") diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index 212eab8ccd..41961c6930 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -403,6 +403,8 @@ public enum ChatResponse: Decodable, Error { case networkConfig(networkConfig: NetCfg) case contactInfo(user: User, contact: Contact, connectionStats: ConnectionStats, customUserProfile: Profile?) case groupMemberInfo(user: User, groupInfo: GroupInfo, member: GroupMember, connectionStats_: ConnectionStats?) + case contactSwitchStarted(user: User, contact: Contact, connectionStats: ConnectionStats) + case groupMemberSwitchStarted(user: User, groupInfo: GroupInfo, member: GroupMember, connectionStats: ConnectionStats) case contactSwitchAborted(user: User, contact: Contact, connectionStats: ConnectionStats) case groupMemberSwitchAborted(user: User, groupInfo: GroupInfo, member: GroupMember, connectionStats: ConnectionStats) case contactCode(user: User, contact: Contact, connectionCode: String) @@ -524,6 +526,8 @@ public enum ChatResponse: Decodable, Error { case .networkConfig: return "networkConfig" case .contactInfo: return "contactInfo" case .groupMemberInfo: return "groupMemberInfo" + case .contactSwitchStarted: return "contactSwitchStarted" + case .groupMemberSwitchStarted: return "groupMemberSwitchStarted" case .contactSwitchAborted: return "contactSwitchAborted" case .groupMemberSwitchAborted: return "groupMemberSwitchAborted" case .contactCode: return "contactCode" @@ -644,6 +648,8 @@ public enum ChatResponse: Decodable, Error { case let .networkConfig(networkConfig): return String(describing: networkConfig) case let .contactInfo(u, contact, connectionStats, customUserProfile): return withUser(u, "contact: \(String(describing: contact))\nconnectionStats: \(String(describing: connectionStats))\ncustomUserProfile: \(String(describing: customUserProfile))") case let .groupMemberInfo(u, groupInfo, member, connectionStats_): return withUser(u, "groupInfo: \(String(describing: groupInfo))\nmember: \(String(describing: member))\nconnectionStats_: \(String(describing: connectionStats_))") + case let .contactSwitchStarted(u, contact, connectionStats): return withUser(u, "contact: \(String(describing: contact))\nconnectionStats: \(String(describing: connectionStats))") + case let .groupMemberSwitchStarted(u, groupInfo, member, connectionStats): return withUser(u, "groupInfo: \(String(describing: groupInfo))\nmember: \(String(describing: member))\nconnectionStats: \(String(describing: connectionStats))") case let .contactSwitchAborted(u, contact, connectionStats): return withUser(u, "contact: \(String(describing: contact))\nconnectionStats: \(String(describing: connectionStats))") case let .groupMemberSwitchAborted(u, groupInfo, member, connectionStats): return withUser(u, "groupInfo: \(String(describing: groupInfo))\nmember: \(String(describing: member))\nconnectionStats: \(String(describing: connectionStats))") case let .contactCode(u, contact, connectionCode): return withUser(u, "contact: \(String(describing: contact))\nconnectionCode: \(connectionCode)")