From 4ced18a7280c730b2a92c943943ca7dd5d120017 Mon Sep 17 00:00:00 2001 From: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com> Date: Thu, 6 Aug 2026 13:34:37 +0000 Subject: [PATCH] android, desktop: don't treat a modal that is closing as still open closeModal leaves an animated modal in modalViews and only stages its index in toRemove, drained when the animation ends. hasModalOpen and isLastModalOpen scanned modalViews directly, so for the ~250ms of the close animation they still reported a dismissed modal as open. A caller that closes on "is my modal still the last one?" therefore popped the modal underneath as well - on Android, where every placement shares one stack, backing out of the create-profile form while creation was in flight dismissed the New chat screen too. Both checks now skip the entries already staged for removal. --- .../chat/simplex/common/views/helpers/ModalView.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt index 20fe22b641..3937c85124 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ModalView.kt @@ -113,9 +113,16 @@ class ModalManager(private val placement: ModalPlacement? = null) { private var passcodeView: MutableStateFlow<(@Composable (close: () -> Unit) -> Unit)?> = MutableStateFlow(null) private var onTimePasscodeView: MutableStateFlow<(@Composable (close: () -> Unit) -> Unit)?> = MutableStateFlow(null) - fun hasModalOpen(id: ModalViewId): Boolean = modalViews.any { it.id == id } + // A modal closed while its animation is still running stays in modalViews until the + // animation ends, so both checks have to skip the ones already staged for removal - + // otherwise a caller that closes on "is my modal still the last one?" pops the modal + // underneath instead. + private fun openModalViews(): List = + if (toRemove.isEmpty()) modalViews else modalViews.filterIndexed { i, _ -> i !in toRemove } - fun isLastModalOpen(id: ModalViewId): Boolean = modalViews.lastOrNull()?.id == id + fun hasModalOpen(id: ModalViewId): Boolean = openModalViews().any { it.id == id } + + fun isLastModalOpen(id: ModalViewId): Boolean = openModalViews().lastOrNull()?.id == id fun showModal(settings: Boolean = false, showClose: Boolean = true, id: ModalViewId? = null, forceAnimated: Boolean = false, cardScreen: Boolean = false, endButtons: @Composable RowScope.() -> Unit = {}, content: @Composable ModalData.() -> Unit) { showCustomModal(id = id, forceAnimated = forceAnimated) { close ->