android, desktop: fix crash on fast clicking every chat in list (#4536)

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Stanislav Dmitrenko
2024-07-30 07:33:15 +01:00
committed by GitHub
co-authored by Evgeny Poberezkin
parent 6729b1fb4f
commit 5257c6f9ca
3 changed files with 26 additions and 20 deletions
@@ -341,7 +341,7 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
}
},
openDirectChat = { contactId ->
withBGApi {
scope.launch {
openDirectChat(chatRh, contactId, chatModel)
}
},
@@ -1156,6 +1156,8 @@ private fun ScrollToBottom(chatId: ChatId, listState: LazyListState, chatItems:
* this coroutine will be canceled with the message "Current mutation had a higher priority" because of animatedScroll.
* Which breaks auto-scrolling to bottom. So just ignoring the exception
* */
} catch (e: IllegalArgumentException) {
Log.e(TAG, "Failed to scroll: ${e.stackTraceToString()}")
}
}
}
@@ -28,7 +28,7 @@ import chat.simplex.common.views.chat.item.ItemAction
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.newchat.*
import chat.simplex.res.MR
import kotlinx.coroutines.delay
import kotlinx.coroutines.*
import kotlinx.datetime.Clock
@Composable
@@ -56,6 +56,8 @@ fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) {
}
}
val scope = rememberCoroutineScope()
when (chat.chatInfo) {
is ChatInfo.Direct -> {
val contactNetworkStatus = chatModel.contactNetworkStatus(chat.chatInfo.contact)
@@ -65,7 +67,7 @@ fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) {
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, contactNetworkStatus, disabled, linkMode, inProgress = false, progressByTimeout = false)
}
},
click = { directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) },
click = { scope.launch { directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) } },
dropdownMenuItems = {
tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) {
ContactMenuItems(chat, chat.chatInfo.contact, chatModel, showMenu, showMarkRead)
@@ -84,7 +86,7 @@ fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) {
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, disabled, linkMode, inProgress.value, progressByTimeout)
}
},
click = { if (!inProgress.value) groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel, inProgress) },
click = { if (!inProgress.value) scope.launch { groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel, inProgress) } },
dropdownMenuItems = {
tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) {
GroupMenuItems(chat, chat.chatInfo.groupInfo, chatModel, showMenu, inProgress, showMarkRead)
@@ -102,7 +104,7 @@ fun ChatListNavLinkView(chat: Chat, nextChatSelected: State<Boolean>) {
ChatPreviewView(chat, showChatPreviews, chatModel.draft.value, chatModel.draftChatId.value, chatModel.currentUser.value?.profile?.displayName, null, disabled, linkMode, inProgress = false, progressByTimeout = false)
}
},
click = { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) },
click = { scope.launch { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) } },
dropdownMenuItems = {
tryOrShowError("${chat.id}ChatListNavLinkDropdown", error = {}) {
NoteFolderMenuItems(chat, showMenu, showMarkRead)
@@ -178,42 +180,42 @@ private fun ErrorChatListItem() {
}
}
fun directChatAction(rhId: Long?, contact: Contact, chatModel: ChatModel) {
suspend fun directChatAction(rhId: Long?, contact: Contact, chatModel: ChatModel) {
when {
contact.activeConn == null && contact.profile.contactLink != null -> askCurrentOrIncognitoProfileConnectContactViaAddress(chatModel, rhId, contact, close = null, openChat = true)
else -> withBGApi { openChat(rhId, ChatInfo.Direct(contact), chatModel) }
else -> openChat(rhId, ChatInfo.Direct(contact), chatModel)
}
}
fun groupChatAction(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel, inProgress: MutableState<Boolean>? = null) {
suspend fun groupChatAction(rhId: Long?, groupInfo: GroupInfo, chatModel: ChatModel, inProgress: MutableState<Boolean>? = null) {
when (groupInfo.membership.memberStatus) {
GroupMemberStatus.MemInvited -> acceptGroupInvitationAlertDialog(rhId, groupInfo, chatModel, inProgress)
GroupMemberStatus.MemAccepted -> groupInvitationAcceptedAlert(rhId)
else -> withBGApi { openChat(rhId, ChatInfo.Group(groupInfo), chatModel) }
else -> openChat(rhId, ChatInfo.Group(groupInfo), chatModel)
}
}
fun noteFolderChatAction(rhId: Long?, noteFolder: NoteFolder) {
withBGApi { openChat(rhId, ChatInfo.Local(noteFolder), chatModel) }
suspend fun noteFolderChatAction(rhId: Long?, noteFolder: NoteFolder) {
openChat(rhId, ChatInfo.Local(noteFolder), chatModel)
}
suspend fun openDirectChat(rhId: Long?, contactId: Long, chatModel: ChatModel) {
suspend fun openDirectChat(rhId: Long?, contactId: Long, chatModel: ChatModel) = coroutineScope {
val chat = chatModel.controller.apiGetChat(rhId, ChatType.Direct, contactId)
if (chat != null) {
if (chat != null && isActive) {
openLoadedChat(chat, chatModel)
}
}
suspend fun openGroupChat(rhId: Long?, groupId: Long, chatModel: ChatModel) {
suspend fun openGroupChat(rhId: Long?, groupId: Long, chatModel: ChatModel) = coroutineScope {
val chat = chatModel.controller.apiGetChat(rhId, ChatType.Group, groupId)
if (chat != null) {
if (chat != null && isActive) {
openLoadedChat(chat, chatModel)
}
}
suspend fun openChat(rhId: Long?, chatInfo: ChatInfo, chatModel: ChatModel) {
suspend fun openChat(rhId: Long?, chatInfo: ChatInfo, chatModel: ChatModel) = coroutineScope {
val chat = chatModel.controller.apiGetChat(rhId, chatInfo.chatType, chatInfo.apiId)
if (chat != null) {
if (chat != null && isActive) {
openLoadedChat(chat, chatModel)
}
}
@@ -13,6 +13,7 @@ import chat.simplex.common.model.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import kotlinx.coroutines.launch
@Composable
fun ShareListNavLinkView(
@@ -23,6 +24,7 @@ fun ShareListNavLinkView(
hasSimplexLink: Boolean
) {
val stopped = chatModel.chatRunning.value == false
val scope = rememberCoroutineScope()
when (chat.chatInfo) {
is ChatInfo.Direct -> {
val voiceProhibited = isVoice && !chat.chatInfo.featureEnabled(ChatFeature.Voice)
@@ -32,7 +34,7 @@ fun ShareListNavLinkView(
if (voiceProhibited) {
showForwardProhibitedByPrefAlert()
} else {
directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel)
scope.launch { directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) }
}
},
stopped
@@ -49,7 +51,7 @@ fun ShareListNavLinkView(
if (prohibitedByPref) {
showForwardProhibitedByPrefAlert()
} else {
groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel)
scope.launch { groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel) }
}
},
stopped
@@ -58,7 +60,7 @@ fun ShareListNavLinkView(
is ChatInfo.Local ->
ShareListNavLinkLayout(
chatLinkPreview = { SharePreviewView(chat, disabled = false) },
click = { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) },
click = { scope.launch { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) } },
stopped
)
is ChatInfo.ContactRequest, is ChatInfo.ContactConnection, is ChatInfo.InvalidJSON -> {}