From e1697975b7e192db3aae48970729a2e920af0e55 Mon Sep 17 00:00:00 2001 From: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com> Date: Mon, 27 Jul 2026 19:08:13 +0000 Subject: [PATCH] android, desktop: do not offer to accept contact request that is being accepted --- .../chat/simplex/common/model/ChatModel.kt | 2 ++ ...ComposeContextContactRequestActionsView.kt | 12 +++++---- .../views/chatlist/ChatListNavLinkView.kt | 27 +++++++++++-------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 58c455840e..7881d363bf 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -122,6 +122,8 @@ object ChatModel { val incompleteInitializedDbRemoved = mutableStateOf(false) // map of connections network statuses, key is agent connection id val switchingUsersAndHosts = mutableStateOf(false) + // ids of contact requests being accepted, to not offer accepting the same request from another view + val acceptingContactRequests = mutableStateListOf() // current chat val chatId = mutableStateOf(null) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeContextContactRequestActionsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeContextContactRequestActionsView.kt index 106c975226..de558a894e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeContextContactRequestActionsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ComposeContextContactRequestActionsView.kt @@ -28,12 +28,14 @@ fun ComposeContextContactRequestActionsView( rhId: Long?, contactRequestId: Long ) { - val inProgress = rememberSaveable { mutableStateOf(false) } + val inProgressLocal = rememberSaveable { mutableStateOf(false) } + // the request can also be accepted from another view, e.g. via notification + val inProgress = remember(contactRequestId) { derivedStateOf { inProgressLocal.value || contactRequestId in chatModel.acceptingContactRequests } } var progressByTimeout by rememberSaveable { mutableStateOf(false) } KeyChangeEffect(chatModel.chatId.value) { - if (inProgress.value) { - inProgress.value = false + if (inProgressLocal.value) { + inProgressLocal.value = false progressByTimeout = false } } @@ -89,9 +91,9 @@ fun ComposeContextContactRequestActionsView( else acceptButtonModifier.clickable { if (chatModel.addressShortLinkDataSet()) { - acceptContactRequest(rhId, incognito = false, contactRequestId, isCurrentUser = true, chatModel = chatModel, close = null, inProgress = inProgress) + acceptContactRequest(rhId, incognito = false, contactRequestId, isCurrentUser = true, chatModel = chatModel, close = null, inProgress = inProgressLocal) } else { - showAcceptRequestAlert(rhId, contactRequestId, inProgress = inProgress) + showAcceptRequestAlert(rhId, contactRequestId, inProgress = inProgressLocal) } } Row( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt index ca1528a3ce..8401f138fe 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListNavLinkView.kt @@ -735,20 +735,25 @@ fun acceptContactRequest( ) { withBGApi { inProgress?.value = true - val contact = chatModel.controller.apiAcceptContactRequest(rhId, incognito, contactRequestId) - if (contact != null && isCurrentUser) { - val chat = Chat(remoteHostId = rhId, ChatInfo.Direct(contact), listOf()) - withContext(Dispatchers.Main) { - if (contact.contactRequestId != null) { // means contact request was initially created with contact, so we don't need to replace it - chatModel.chatsContext.updateContact(rhId, contact) - } else { - chatModel.chatsContext.replaceChat(rhId, contactRequestChatId(contactRequestId), chat) + chatModel.acceptingContactRequests.add(contactRequestId) + try { + val contact = chatModel.controller.apiAcceptContactRequest(rhId, incognito, contactRequestId) + if (contact != null && isCurrentUser) { + val chat = Chat(remoteHostId = rhId, ChatInfo.Direct(contact), listOf()) + withContext(Dispatchers.Main) { + if (contact.contactRequestId != null) { // means contact request was initially created with contact, so we don't need to replace it + chatModel.chatsContext.updateContact(rhId, contact) + } else { + chatModel.chatsContext.replaceChat(rhId, contactRequestChatId(contactRequestId), chat) + } + inProgress?.value = false } + close?.invoke(chat) + } else { inProgress?.value = false } - close?.invoke(chat) - } else { - inProgress?.value = false + } finally { + chatModel.acceptingContactRequests.remove(contactRequestId) } } }