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.
This commit is contained in:
Narasimha-sc
2026-08-06 13:34:37 +00:00
parent e0cde46149
commit 4ced18a728
@@ -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<ModalViewHolder> =
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 ->