ui prohibit sending to member if connection is not ready (#5399)

This commit is contained in:
spaced4ndy
2024-12-20 20:33:09 +04:00
committed by GitHub
parent 5aa8b8cd1b
commit a3140c2d3e
7 changed files with 98 additions and 48 deletions
@@ -162,7 +162,7 @@ struct GroupMemberInfoView: View {
}
.disabled(
connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil }
|| connStats.ratchetSyncSendProhibited
|| !member.sendMsgEnabled
)
if connStats.rcvQueuesInfo.contains(where: { $0.rcvSwitchStatus != nil }) {
Button("Abort changing address") {
@@ -170,7 +170,7 @@ struct GroupMemberInfoView: View {
}
.disabled(
connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil && !$0.canAbortSwitch }
|| connStats.ratchetSyncSendProhibited
|| !member.sendMsgEnabled
)
}
smpServers("Receiving via", connStats.rcvQueuesInfo.map { $0.rcvServer }, theme.colors.secondary)
@@ -297,7 +297,7 @@ struct GroupMemberInfoView: View {
if let contactId = member.memberContactId {
newDirectChatButton(contactId, width: buttonWidth)
} else if member.activeConn?.peerChatVRange.isCompatibleRange(CREATE_MEMBER_CONTACT_VRANGE) ?? false {
createMemberContactButton(width: buttonWidth)
createMemberContactButton(member, width: buttonWidth)
}
InfoViewButton(image: "phone.fill", title: "call", disabledLook: true, width: buttonWidth) { showSendMessageToEnableCallsAlert()
}
@@ -379,32 +379,41 @@ struct GroupMemberInfoView: View {
}
}
func createMemberContactButton(width: CGFloat) -> some View {
InfoViewButton(image: "message.fill", title: "message", width: width) {
if let connStats = connectionStats {
if connStats.ratchetSyncState == .ok {
progressIndicator = true
Task {
do {
let memberContact = try await apiCreateMemberContact(groupInfo.apiId, groupMember.groupMemberId)
await MainActor.run {
progressIndicator = false
chatModel.addChat(Chat(chatInfo: .direct(contact: memberContact)))
ItemsModel.shared.loadOpenChat(memberContact.id) {
dismissAllSheets(animated: true)
}
NetworkModel.shared.setContactNetworkStatus(memberContact, .connected)
}
} catch let error {
logger.error("createMemberContactButton apiCreateMemberContact error: \(responseError(error))")
let a = getErrorAlert(error, "Error creating member contact")
await MainActor.run {
progressIndicator = false
alert = .error(title: a.title, error: a.message)
func createMemberContactButton(_ member: GroupMember, width: CGFloat) -> some View {
InfoViewButton(
image: "message.fill",
title: "message",
disabledLook:
!(
member.sendMsgEnabled ||
(member.activeConn?.connectionStats?.ratchetSyncAllowed ?? false)
),
width: width
) {
if member.sendMsgEnabled {
progressIndicator = true
Task {
do {
let memberContact = try await apiCreateMemberContact(groupInfo.apiId, groupMember.groupMemberId)
await MainActor.run {
progressIndicator = false
chatModel.addChat(Chat(chatInfo: .direct(contact: memberContact)))
ItemsModel.shared.loadOpenChat(memberContact.id) {
dismissAllSheets(animated: true)
}
NetworkModel.shared.setContactNetworkStatus(memberContact, .connected)
}
} catch let error {
logger.error("createMemberContactButton apiCreateMemberContact error: \(responseError(error))")
let a = getErrorAlert(error, "Error creating member contact")
await MainActor.run {
progressIndicator = false
alert = .error(title: a.title, error: a.message)
}
}
} else if connStats.ratchetSyncAllowed {
}
} else if let connStats = connectionStats {
if connStats.ratchetSyncAllowed {
alert = .someAlert(alert: SomeAlert(
alert: Alert(
title: Text("Fix connection?"),
@@ -416,13 +425,21 @@ struct GroupMemberInfoView: View {
),
id: "can't message member, fix connection"
))
} else {
} else if connStats.ratchetSyncInProgress {
alert = .someAlert(alert: SomeAlert(
alert: mkAlert(
title: "Can't message member",
message: "Encryption renegotiation in progress."
),
id: "can't message contact, encryption renegotiation in progress"
id: "can't message member, encryption renegotiation in progress"
))
} else {
alert = .someAlert(alert: SomeAlert(
alert: mkAlert(
title: "Can't message member",
message: "Connection not ready."
),
id: "can't message member, connection not ready"
))
}
}
+4
View File
@@ -2034,6 +2034,10 @@ public struct ConnectionStats: Decodable, Hashable {
public var ratchetSyncSendProhibited: Bool {
[.required, .started, .agreed].contains(ratchetSyncState)
}
public var ratchetSyncInProgress: Bool {
[.started, .agreed].contains(ratchetSyncState)
}
}
public struct RcvQueueInfo: Codable, Hashable {
+8
View File
@@ -2010,6 +2010,14 @@ public struct GroupMember: Identifiable, Decodable, Hashable {
public var activeConn: Connection?
public var id: String { "#\(groupId) @\(groupMemberId)" }
public var ready: Bool { get { activeConn?.connStatus == .ready } }
public var sndReady: Bool { get { ready || activeConn?.connStatus == .sndReady } }
public var sendMsgEnabled: Bool { get {
sndReady
&& memberCurrent
&& !(activeConn?.connectionStats?.ratchetSyncSendProhibited ?? false)
&& !(activeConn?.connDisabled ?? true)
} }
public var displayName: String {
get {
let p = memberProfile
@@ -1575,6 +1575,13 @@ data class GroupMember (
var activeConn: Connection? = null
): NamedChat {
val id: String get() = "#$groupId @$groupMemberId"
val ready get() = activeConn?.connStatus == ConnStatus.Ready
val sndReady get() = ready || activeConn?.connStatus == ConnStatus.SndReady
val sendMsgEnabled get() =
sndReady
&& memberCurrent
&& !(activeConn?.connectionStats?.ratchetSyncSendProhibited ?: false)
&& !(activeConn?.connDisabled ?: true)
override val displayName: String
get() {
val p = memberProfile
@@ -6032,6 +6032,9 @@ class ConnectionStats(
val ratchetSyncSendProhibited: Boolean get() =
listOf(RatchetSyncState.Required, RatchetSyncState.Started, RatchetSyncState.Agreed).contains(ratchetSyncState)
val ratchetSyncInProgress: Boolean get() =
listOf(RatchetSyncState.Started, RatchetSyncState.Agreed).contains(ratchetSyncState)
}
@Serializable
@@ -89,29 +89,34 @@ fun GroupMemberInfoView(
}
},
createMemberContact = {
if (connectionStats != null) {
if (connectionStats.ratchetSyncState == RatchetSyncState.Ok) {
withBGApi {
progressIndicator = true
val memberContact = chatModel.controller.apiCreateMemberContact(rhId, groupInfo.apiId, member.groupMemberId)
if (memberContact != null) {
val memberChat = Chat(remoteHostId = rhId, ChatInfo.Direct(memberContact), chatItems = arrayListOf())
withChats {
addChat(memberChat)
openLoadedChat(memberChat)
}
closeAll()
chatModel.setContactNetworkStatus(memberContact, NetworkStatus.Connected())
if (member.sendMsgEnabled) {
withBGApi {
progressIndicator = true
val memberContact = chatModel.controller.apiCreateMemberContact(rhId, groupInfo.apiId, member.groupMemberId)
if (memberContact != null) {
val memberChat = Chat(remoteHostId = rhId, ChatInfo.Direct(memberContact), chatItems = arrayListOf())
withChats {
addChat(memberChat)
openLoadedChat(memberChat)
}
progressIndicator = false
closeAll()
chatModel.setContactNetworkStatus(memberContact, NetworkStatus.Connected())
}
} else if (connectionStats.ratchetSyncAllowed) {
progressIndicator = false
}
} else if (connectionStats != null) {
if (connectionStats.ratchetSyncAllowed) {
showFixConnectionAlert(syncConnection = { syncMemberConnection() })
} else {
} else if (connectionStats.ratchetSyncInProgress) {
AlertManager.shared.showAlertMsg(
generalGetString(MR.strings.cant_send_message_to_member_alert_title),
generalGetString(MR.strings.encryption_renegotiation_in_progress)
)
} else {
AlertManager.shared.showAlertMsg(
generalGetString(MR.strings.cant_send_message_to_member_alert_title),
generalGetString(MR.strings.connection_not_ready)
)
}
}
},
@@ -366,7 +371,11 @@ fun GroupMemberInfoLayout(
if (contactId != null) {
OpenChatButton(modifier = Modifier.fillMaxWidth(0.33f), onClick = { openDirectChat(contactId) }) // legacy - only relevant for direct contacts created when joining group
} else {
OpenChatButton(modifier = Modifier.fillMaxWidth(0.33f), onClick = { createMemberContact() })
OpenChatButton(
modifier = Modifier.fillMaxWidth(0.33f),
disabledLook = !(member.sendMsgEnabled || (member.activeConn?.connectionStats?.ratchetSyncAllowed ?: false)),
onClick = { createMemberContact() }
)
}
InfoViewActionButton(modifier = Modifier.fillMaxWidth(0.5f), painterResource(MR.images.ic_call), generalGetString(MR.strings.info_view_call_button), disabled = false, disabledLook = true, onClick = {
showSendMessageToEnableCallsAlert()
@@ -437,12 +446,12 @@ fun GroupMemberInfoLayout(
SectionDividerSpaced()
SectionView(title = stringResource(MR.strings.conn_stats_section_title_servers)) {
SwitchAddressButton(
disabled = cStats.rcvQueuesInfo.any { it.rcvSwitchStatus != null } || cStats.ratchetSyncSendProhibited,
disabled = cStats.rcvQueuesInfo.any { it.rcvSwitchStatus != null } || !member.sendMsgEnabled,
switchAddress = switchMemberAddress
)
if (cStats.rcvQueuesInfo.any { it.rcvSwitchStatus != null }) {
AbortSwitchAddressButton(
disabled = cStats.rcvQueuesInfo.any { it.rcvSwitchStatus != null && !it.canAbortSwitch } || cStats.ratchetSyncSendProhibited,
disabled = cStats.rcvQueuesInfo.any { it.rcvSwitchStatus != null && !it.canAbortSwitch } || !member.sendMsgEnabled,
abortSwitchAddress = abortSwitchMemberAddress
)
}
@@ -602,6 +611,7 @@ fun RemoveMemberButton(onClick: () -> Unit) {
@Composable
fun OpenChatButton(
modifier: Modifier,
disabledLook: Boolean = false,
onClick: () -> Unit
) {
InfoViewActionButton(
@@ -609,7 +619,7 @@ fun OpenChatButton(
icon = painterResource(MR.images.ic_chat_bubble),
title = generalGetString(MR.strings.info_view_message_button),
disabled = false,
disabledLook = false,
disabledLook = disabledLook,
onClick = onClick
)
}
@@ -1696,6 +1696,7 @@
<string name="cant_call_member_alert_title">Can\'t call group member</string>
<string name="cant_call_member_send_message_alert_text">Send message to enable calls.</string>
<string name="cant_send_message_to_member_alert_title">Can\'t message group member</string>
<string name="connection_not_ready">Connection not ready.</string>
<!-- GroupWelcomeView.kt -->
<string name="group_welcome_title">Welcome message</string>