diff --git a/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactListScreen.kt b/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactListScreen.kt index 818796c60..f0d2d3f06 100644 --- a/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactListScreen.kt +++ b/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactListScreen.kt @@ -40,6 +40,7 @@ import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -315,9 +316,10 @@ private fun SwipeToRevealItem( } } + val currentOnDelete by rememberUpdatedState(onDelete) LaunchedEffect(state.currentValue) { if (state.currentValue == RevealValue.Dismissed) { - onDelete() + currentOnDelete() } } diff --git a/apps/flipcash/shared/permissions/src/main/kotlin/com/flipcash/app/permissions/ContactPermissionScreen.kt b/apps/flipcash/shared/permissions/src/main/kotlin/com/flipcash/app/permissions/ContactPermissionScreen.kt index 7612252c3..91331e696 100644 --- a/apps/flipcash/shared/permissions/src/main/kotlin/com/flipcash/app/permissions/ContactPermissionScreen.kt +++ b/apps/flipcash/shared/permissions/src/main/kotlin/com/flipcash/app/permissions/ContactPermissionScreen.kt @@ -41,7 +41,7 @@ fun ContactPermissionScreen(fromOnboarding: Boolean) { } } - LaunchedEffect(Unit) { + LaunchedEffect(permissionState.status) { when (permissionState.status) { PermissionResult.Granted -> navigator.navigate( route = AppRoute.Main.Scanner, diff --git a/apps/flipcash/shared/permissions/src/main/kotlin/com/flipcash/app/permissions/NotificationPermissionScreen.kt b/apps/flipcash/shared/permissions/src/main/kotlin/com/flipcash/app/permissions/NotificationPermissionScreen.kt index 9694431ec..55516fd63 100644 --- a/apps/flipcash/shared/permissions/src/main/kotlin/com/flipcash/app/permissions/NotificationPermissionScreen.kt +++ b/apps/flipcash/shared/permissions/src/main/kotlin/com/flipcash/app/permissions/NotificationPermissionScreen.kt @@ -39,7 +39,7 @@ fun NotificationPermissionScreen(fromOnboarding: Boolean = false) { } } - LaunchedEffect(Unit) { + LaunchedEffect(permissionState.status) { when (permissionState.status) { PermissionResult.Granted -> navigator.navigate( route = AppRoute.Main.Scanner, diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/SlideToConfirm.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/SlideToConfirm.kt index 5947e1ca9..de66eb614 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/SlideToConfirm.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/SlideToConfirm.kt @@ -37,6 +37,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha @@ -63,6 +64,7 @@ import com.getcode.theme.White50 import com.getcode.ui.theme.CodeCircularProgressIndicator import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import java.util.Timer import java.util.TimerTask @@ -190,26 +192,32 @@ fun SlideToConfirm( } } - LaunchedEffect(swipeFraction, enabled) { - when { - !enabled -> hintState.cancelTimer() - swipeFraction == 0f -> hintState.startTimer() - swipeFraction in 0.1f .. 0.99f -> hintState.cancelTimer() + LaunchedEffect(enabled) { + if (!enabled) { + hintState.cancelTimer() + return@LaunchedEffect } + snapshotFlow { swipeFraction } + .collect { fraction -> + when { + fraction == 0f -> hintState.startTimer() + fraction in 0.1f .. 0.99f -> hintState.cancelTimer() + } + } } - LaunchedEffect(swipeFraction) { - if (swipeFraction == 1f) { - hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - onConfirm() - // Give the caller a moment to set isLoading = true. - // If they don't, the confirmation was rejected — reset. - // Launch in composeScope so the animation isn't cancelled when - // swipeFraction changes (which would cancel this LaunchedEffect). - delay(200) - if (!currentIsLoading) { - composeScope.launch { swipeState.animateTo(Anchor.Start) } + LaunchedEffect(Unit) { + snapshotFlow { swipeFraction } + .filter { it == 1f } + .collect { + hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) + onConfirm() + // Give the caller a moment to set isLoading = true. + // If they don't, the confirmation was rejected — reset. + delay(200) + if (!currentIsLoading) { + composeScope.launch { swipeState.animateTo(Anchor.Start) } + } } - } } // Handle the loading → idle transition (e.g. after a network call completes) diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/TextInput.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/TextInput.kt index 9dab5be7f..5ed10f927 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/TextInput.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/TextInput.kt @@ -29,6 +29,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment @@ -141,9 +142,10 @@ fun TextInput( ) } + val currentOnStateChanged by rememberUpdatedState(onStateChanged) LaunchedEffect(Unit) { snapshotFlow { state.text } - .onEach { onStateChanged() } + .onEach { currentOnStateChanged() } .launchIn(this) }