From 634b1094681aefc9f09eeb49ef08b57a1869f808 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 1 Jun 2026 12:52:11 -0400 Subject: [PATCH] fix(direct-send): gate Flipcash contacts discovery prompt to ContactList step Track the current SendStep so the discovery snackbar only fires when the user is on the ContactList screen, not during gate screens. --- .../com/flipcash/app/directsend/SendFlowScreen.kt | 13 +++++++++++++ .../app/directsend/internal/SendFlowViewModel.kt | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/SendFlowScreen.kt b/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/SendFlowScreen.kt index 1f7926952..9a7789eef 100644 --- a/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/SendFlowScreen.kt +++ b/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/SendFlowScreen.kt @@ -1,6 +1,7 @@ package com.flipcash.app.directsend import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -17,6 +18,7 @@ import com.getcode.navigation.annotatedEntry import com.getcode.navigation.flow.FlowExitReason import com.getcode.navigation.flow.FlowHost import com.getcode.navigation.results.NavResultStateRegistry +import com.getcode.navigation.flow.flowSharedViewModel import com.getcode.navigation.scenes.LocalBottomSheetDismissDispatcher @Composable @@ -42,12 +44,23 @@ fun SendFlowScreen(resultStateRegistry: NavResultStateRegistry) { private fun sendEntryProvider(): (NavKey) -> NavEntry = entryProvider { annotatedEntry { + SyncStep(it) PhoneGateLandingScreen() } annotatedEntry { + SyncStep(it) ContactsPermissionGateScreen() } annotatedEntry { + SyncStep(it) ContactListScreen() } +} + +@Composable +private fun SyncStep(step: SendStep) { + val viewModel = flowSharedViewModel() + LaunchedEffect(step) { + viewModel.dispatchEvent(SendFlowViewModel.Event.OnStepChanged(step)) + } } \ No newline at end of file diff --git a/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/SendFlowViewModel.kt b/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/SendFlowViewModel.kt index 7865bbf3f..aee73236c 100644 --- a/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/SendFlowViewModel.kt +++ b/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/SendFlowViewModel.kt @@ -46,6 +46,7 @@ internal class SendFlowViewModel @Inject constructor( data class State @OptIn(ExperimentalMaterial3Api::class) constructor( val steps: List = listOf(SendStep.ContactList), + val currentStep: SendStep? = null, val searchState: TextFieldState = TextFieldState(), val isPickerMode: Boolean = false, val contactSyncState: LoadingSuccessState = LoadingSuccessState(), @@ -54,6 +55,7 @@ internal class SendFlowViewModel @Inject constructor( sealed interface Event { data class StepsUpdated(val steps: List, val isPickerMode: Boolean) : Event + data class OnStepChanged(val step: SendStep) : Event data object ContactsGranted : Event data class ContactsPicked(val contacts: List) : Event @@ -164,6 +166,7 @@ internal class SendFlowViewModel @Inject constructor( contactCoordinator.state .filter { it.hasDiscoveredFlipcashContacts && it.flipcashE164s.isNotEmpty() } + .filter { stateFlow.value.currentStep is SendStep.ContactList } .take(1) .onEach { contactState -> val count = contactState.flipcashE164s.size @@ -222,6 +225,10 @@ internal class SendFlowViewModel @Inject constructor( state.copy(steps = event.steps, isPickerMode = event.isPickerMode) } + is Event.OnStepChanged -> { state -> + state.copy(currentStep = event.step) + } + is Event.ContactsGranted -> { state -> state } is Event.ContactsPicked -> { state -> state } is Event.ContactSyncStateUpdated -> { state ->