From 52041f4bcd76a9b4182113d8cab3eac7ef5a9b1b Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:24:30 -0400 Subject: [PATCH 01/13] fix(compose): prevent stale onConfirm capture in SlideToConfirm onConfirm was captured by a LaunchedEffect(Unit) without rememberUpdatedState. If the caller recomposes with a new lambda, the stale version executes on swipe-to-confirm. --- .../main/kotlin/com/getcode/ui/components/SlideToConfirm.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 de66eb614..8797ffb82 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 @@ -162,6 +162,7 @@ fun SlideToConfirm( }, ) { val currentIsLoading by rememberUpdatedState(isLoading) + val currentOnConfirm by rememberUpdatedState(onConfirm) val hapticFeedback = LocalHapticFeedback.current val density = LocalDensity.current val thumbSize = Thumb.Size @@ -210,7 +211,7 @@ fun SlideToConfirm( .filter { it == 1f } .collect { hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress) - onConfirm() + currentOnConfirm() // Give the caller a moment to set isLoading = true. // If they don't, the confirmation was rejected — reset. delay(200) From 76e81c6e6d07ae07d26fb21fa78b38f483bb9c18 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:26:12 -0400 Subject: [PATCH 02/13] fix(compose): cache collection transforms in per-item composables Wrap sortedBy/groupBy, map, and forEachIndexed transforms in remember(key) so they do not re-run on every recomposition inside LazyColumn item factories. --- .../app/bill/customization/features/TextureControls.kt | 9 ++++++--- .../ui/components/chat/messagecontents/Feedback.kt | 8 +++++--- .../chat/messagecontents/MessageTextContent.kt | 4 +++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/features/TextureControls.kt b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/features/TextureControls.kt index f36709b95..a08a7b4ae 100644 --- a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/features/TextureControls.kt +++ b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/features/TextureControls.kt @@ -91,10 +91,13 @@ internal fun TextureControls( } } + val blendModes = remember(state.blendModes) { + state.blendModes.map { it.blendMode } + } + val selectedTabIndex by remember(state.selectedBlendMode) { derivedStateOf { - val option = state.selectedBlendMode.blendMode - state.blendModes.map { it.blendMode }.indexOf(option).takeIf { it >= 0 } ?: 0 + blendModes.indexOf(state.selectedBlendMode.blendMode).takeIf { it >= 0 } ?: 0 } } @@ -106,7 +109,7 @@ internal fun TextureControls( indicator = {}, // no indicator divider = {} // no divider ) { - state.blendModes.map { it.blendMode }.forEachIndexed { index, mode -> + blendModes.forEachIndexed { index, mode -> BlendModeTab( mode = mode, isSelected = index == selectedTabIndex, diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/messagecontents/Feedback.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/messagecontents/Feedback.kt index 8ee49dcdf..855af1f55 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/messagecontents/Feedback.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/messagecontents/Feedback.kt @@ -67,9 +67,11 @@ internal fun Feedback( ) } - val rxns = reactions - .sortedBy { it.sentAt } - .groupBy { it.emoji } + val rxns = remember(reactions) { + reactions + .sortedBy { it.sentAt } + .groupBy { it.emoji } + } rxns.onEach { (emoji, occurrences) -> EmojiCounter( diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/messagecontents/MessageTextContent.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/messagecontents/MessageTextContent.kt index 2a35dccca..5b03d15de 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/messagecontents/MessageTextContent.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/messagecontents/MessageTextContent.kt @@ -352,7 +352,9 @@ private fun MarkupTextHandler( options.onMarkupClicked != null -> { val markupTextHelper = remember { MarkupTextHelper() } - val markups = options.markupsToResolve.map { Markup.create(it) } + val markups = remember(options.markupsToResolve) { + options.markupsToResolve.map { Markup.create(it) } + } val annotatedString = markupTextHelper.annotate(text.text, markups) val markupHoist = LocalTextLayoutResult.current From 28400b04a065c7a98b41df76be2dbcd8039cf3fa Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:26:28 -0400 Subject: [PATCH 03/13] fix(compose): use collectAsStateWithLifecycle in CashScreenContent Last remaining collectAsState() call in production code. Stops flow collection when the app is backgrounded. --- .../com/flipcash/app/cash/internal/CashScreenContent.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/flipcash/features/cash/src/main/kotlin/com/flipcash/app/cash/internal/CashScreenContent.kt b/apps/flipcash/features/cash/src/main/kotlin/com/flipcash/app/cash/internal/CashScreenContent.kt index 8de8bb958..0e8910a57 100644 --- a/apps/flipcash/features/cash/src/main/kotlin/com/flipcash/app/cash/internal/CashScreenContent.kt +++ b/apps/flipcash/features/cash/src/main/kotlin/com/flipcash/app/cash/internal/CashScreenContent.kt @@ -7,7 +7,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -22,7 +22,7 @@ import com.getcode.ui.theme.CodeButton @Composable internal fun GiveScreenContent(viewModel: CashScreenViewModel) { val navigator = LocalCodeNavigator.current - val state by viewModel.stateFlow.collectAsState() + val state by viewModel.stateFlow.collectAsStateWithLifecycle() Column( modifier = Modifier.fillMaxSize(), ) { From f592e6e20f82d7f53090afded91fc19b19b20e22 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:26:55 -0400 Subject: [PATCH 04/13] fix(compose): use mutableLongStateOf to avoid autoboxing Replace mutableStateOf(0L) with mutableLongStateOf(0L) to avoid Long autoboxing on every state read. --- .../src/main/kotlin/com/getcode/ui/biometrics/Biometrics.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/biometrics/src/main/kotlin/com/getcode/ui/biometrics/Biometrics.kt b/ui/biometrics/src/main/kotlin/com/getcode/ui/biometrics/Biometrics.kt index d50a45d10..87ebe97bd 100644 --- a/ui/biometrics/src/main/kotlin/com/getcode/ui/biometrics/Biometrics.kt +++ b/ui/biometrics/src/main/kotlin/com/getcode/ui/biometrics/Biometrics.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.ProvidableCompositionLocal import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableLongStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -62,7 +63,7 @@ fun rememberBiometricsState( } var lastAuthTimestamp by remember { - mutableStateOf(0L) + mutableLongStateOf(0L) } LaunchedEffect(checkBiometrics, requireBiometrics, canAuthenticate) { From 65fa033aefa910f4bf1a3fb05e3c86539ba9fc5e Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:34:07 -0400 Subject: [PATCH 05/13] fix(compose): defer animation reads to draw phase via graphicsLayer Replace Modifier.alpha(animatedFloat) and Modifier.rotate(animatedFloat) with graphicsLayer equivalents so animated values are read in the draw phase instead of triggering recomposition every frame. --- .../com/flipcash/app/internal/ui/navigation/MainRoot.kt | 4 ++-- .../app/shareapp/internal/ShareAppScreenContent.kt | 6 +++--- .../com/getcode/ui/components/bars/BottomBarContainer.kt | 7 +++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/ui/navigation/MainRoot.kt b/apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/ui/navigation/MainRoot.kt index 499192d8c..4392ab73d 100644 --- a/apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/ui/navigation/MainRoot.kt +++ b/apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/ui/navigation/MainRoot.kt @@ -18,7 +18,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.res.painterResource import androidx.navigation3.runtime.NavKey import com.flipcash.app.android.R @@ -79,7 +79,7 @@ internal fun MainRoot(deepLink: () -> DeepLink?) { label = "loading visibility" ) CodeCircularProgressIndicator( - modifier = Modifier.alpha(loadingAlpha) + modifier = Modifier.graphicsLayer { alpha = loadingAlpha } ) } } diff --git a/apps/flipcash/features/shareapp/src/main/kotlin/com/flipcash/app/shareapp/internal/ShareAppScreenContent.kt b/apps/flipcash/features/shareapp/src/main/kotlin/com/flipcash/app/shareapp/internal/ShareAppScreenContent.kt index 8397e5f10..defd0a3cc 100644 --- a/apps/flipcash/features/shareapp/src/main/kotlin/com/flipcash/app/shareapp/internal/ShareAppScreenContent.kt +++ b/apps/flipcash/features/shareapp/src/main/kotlin/com/flipcash/app/shareapp/internal/ShareAppScreenContent.kt @@ -21,7 +21,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.draw.scale import androidx.compose.ui.geometry.Rect import androidx.compose.ui.layout.boundsInWindow @@ -113,7 +113,7 @@ internal fun ShareAppScreenContent() { Text( modifier = Modifier .padding(bottom = CodeTheme.dimens.grid.x4) - .alpha(contentAlpha), + .graphicsLayer { alpha = contentAlpha }, text = stringResource(R.string.subtitle_scanToDownload), style = CodeTheme.typography.textLarge, textAlign = TextAlign.Center @@ -139,7 +139,7 @@ internal fun ShareAppScreenContent() { ) Row( - modifier = Modifier.alpha(contentAlpha), + modifier = Modifier.graphicsLayer { alpha = contentAlpha }, horizontalArrangement = Arrangement.spacedBy( space = CodeTheme.dimens.inset, alignment = Alignment.CenterHorizontally diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/bars/BottomBarContainer.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/bars/BottomBarContainer.kt index 2e25040e3..485128179 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/bars/BottomBarContainer.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/bars/BottomBarContainer.kt @@ -42,9 +42,8 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clipToBounds -import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString @@ -121,7 +120,7 @@ fun BottomBarContainer(barMessages: BarMessages, onShown: (BottomBarManager.Bott Box( modifier = Modifier .fillMaxSize() - .alpha(scrimAlpha) + .graphicsLayer { alpha = scrimAlpha } .background(CodeTheme.colors.scrim) .rememberedClickable( indication = null, @@ -257,7 +256,7 @@ fun BottomBarView( color = LocalContentColor.current.copy(alpha = 0.8f), ) Icon( - modifier = Modifier.rotate(rotation), + modifier = Modifier.graphicsLayer { rotationZ = rotation }, imageVector = Icons.Rounded.ExpandMore, contentDescription = null, tint = LocalContentColor.current.copy(alpha = 0.8f), From a8b5cba5b457686578e8ecb28dc28a48894cad31 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:35:11 -0400 Subject: [PATCH 06/13] fix(compose): use viewModel as LaunchedEffect key for event flow collection Replace LaunchedEffect(Unit) with LaunchedEffect(viewModel) so the effect restarts if the ViewModel instance changes, and is consistent across composables. --- .../app/directsend/internal/screens/ContactListScreen.kt | 4 ++-- .../internal/screens/ContactsPermissionGateScreen.kt | 2 +- .../kotlin/com/flipcash/app/tokens/PhantomWalletScreens.kt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) 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 cf04d946e..c43e33558 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 @@ -88,7 +88,7 @@ internal fun ContactListScreen() { val state by viewModel.stateFlow.collectAsStateWithLifecycle() - LaunchedEffect(Unit) { + LaunchedEffect(viewModel) { viewModel.eventFlow .filterIsInstance() .collect { event -> @@ -96,7 +96,7 @@ internal fun ContactListScreen() { } } - LaunchedEffect(Unit) { + LaunchedEffect(viewModel) { viewModel.eventFlow .filterIsInstance() .collect { event -> diff --git a/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactsPermissionGateScreen.kt b/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactsPermissionGateScreen.kt index 23775602b..241097756 100644 --- a/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactsPermissionGateScreen.kt +++ b/apps/flipcash/features/direct-send/src/main/kotlin/com/flipcash/app/directsend/internal/screens/ContactsPermissionGateScreen.kt @@ -50,7 +50,7 @@ internal fun ContactsPermissionGateScreen() { } } - LaunchedEffect(Unit) { + LaunchedEffect(viewModel) { viewModel.eventFlow .filterIsInstance() .collect { flowNavigator.proceed() } diff --git a/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/PhantomWalletScreens.kt b/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/PhantomWalletScreens.kt index 44776c399..d6ee1bcd3 100644 --- a/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/PhantomWalletScreens.kt +++ b/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/PhantomWalletScreens.kt @@ -47,7 +47,7 @@ internal fun PhantomConnectConfirmationScreen() { .launchIn(this) } - LaunchedEffect(Unit) { + LaunchedEffect(viewModel) { viewModel.eventFlow .filterIsInstance() .onEach { flowNavigator.navigateTo(SwapStep.PhantomConfirmTransaction) } From 640e1b52299715325af57dbc9109a2d6701dd275 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:35:55 -0400 Subject: [PATCH 07/13] fix(compose): add stable keys to lazy lists Add key parameters to items() calls in DeviceLogsScreen, UserFlagsEditor, FrequentlyUsedEmojis, and EmojiSearch so Compose can diff items correctly during recomposition instead of recomposing every item. --- .../app/devicelogs/internal/DeviceLogsScreen.kt | 5 ++++- .../flipcash/app/userflags/internal/UserFlagsEditor.kt | 10 ++++++++-- .../main/kotlin/com/getcode/ui/emojis/EmojiSearch.kt | 5 ++++- .../com/getcode/ui/emojis/FrequentlyUsedEmojis.kt | 5 ++++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/apps/flipcash/features/device-logs/src/main/kotlin/com/flipcash/app/devicelogs/internal/DeviceLogsScreen.kt b/apps/flipcash/features/device-logs/src/main/kotlin/com/flipcash/app/devicelogs/internal/DeviceLogsScreen.kt index e2d5cd2e2..401642dd6 100644 --- a/apps/flipcash/features/device-logs/src/main/kotlin/com/flipcash/app/devicelogs/internal/DeviceLogsScreen.kt +++ b/apps/flipcash/features/device-logs/src/main/kotlin/com/flipcash/app/devicelogs/internal/DeviceLogsScreen.kt @@ -196,7 +196,10 @@ private fun LogList( ), verticalArrangement = Arrangement.spacedBy(2.dp), ) { - items(lines.asReversed()) { line -> + items( + items = lines.asReversed(), + key = { it.hashCode() }, + ) { line -> LogLine(line = line, filter = filter) } } diff --git a/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/UserFlagsEditor.kt b/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/UserFlagsEditor.kt index d7abc992a..ada552e55 100644 --- a/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/UserFlagsEditor.kt +++ b/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/UserFlagsEditor.kt @@ -75,13 +75,19 @@ private fun UserFlagsEditor( ) { // Read-only section item { SectionHeader("Read-Only") } - items(state.readOnlyEntries) { entry -> + items( + items = state.readOnlyEntries, + key = { it.label }, + ) { entry -> ReadOnlyRow(entry) } // Editable section item { SectionHeader("Overridable") } - items(state.editableEntries) { entry -> + items( + items = state.editableEntries, + key = { it.field.label }, + ) { entry -> EditableRow( modifier = Modifier.fillMaxWidth(), entry = entry, diff --git a/ui/emojis/src/main/kotlin/com/getcode/ui/emojis/EmojiSearch.kt b/ui/emojis/src/main/kotlin/com/getcode/ui/emojis/EmojiSearch.kt index 8d429c651..7d033dfe2 100644 --- a/ui/emojis/src/main/kotlin/com/getcode/ui/emojis/EmojiSearch.kt +++ b/ui/emojis/src/main/kotlin/com/getcode/ui/emojis/EmojiSearch.kt @@ -51,7 +51,10 @@ fun EmojiSearchResults( bottom = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + CodeTheme.dimens.grid.x2 ) ) { - items(results.orEmpty()) { emoji -> + items( + items = results.orEmpty(), + key = { it.unicode }, + ) { emoji -> Row( modifier = Modifier .clickable { onSelected(emoji.unicode) }, diff --git a/ui/emojis/src/main/kotlin/com/getcode/ui/emojis/FrequentlyUsedEmojis.kt b/ui/emojis/src/main/kotlin/com/getcode/ui/emojis/FrequentlyUsedEmojis.kt index c4082662d..2f3a7fc60 100644 --- a/ui/emojis/src/main/kotlin/com/getcode/ui/emojis/FrequentlyUsedEmojis.kt +++ b/ui/emojis/src/main/kotlin/com/getcode/ui/emojis/FrequentlyUsedEmojis.kt @@ -49,7 +49,10 @@ fun FrequentlyUsedEmojis( .height(CodeTheme.dimens.grid.x9), contentPadding = PaddingValues(horizontal = CodeTheme.dimens.inset) ) { - items(frequentlyUsedEmojis) { emoji -> + items( + items = frequentlyUsedEmojis, + key = { it }, + ) { emoji -> EmojiRender( emoji = emoji, size = DpSize( From a01061299527f565e6a74c266eb3e3bba5096ab1 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:37:46 -0400 Subject: [PATCH 08/13] fix(compose): use rememberSaveable for user-driven UI flags Replace remember with rememberSaveable for isExportSeedRequested and isStoragePermissionGranted so these flags survive configuration changes. --- .../app/backupkey/internal/BackupKeyScreenContent.kt | 5 +++-- .../app/login/internal/screens/AccessKeyScreenContent.kt | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/flipcash/features/backupkey/src/main/kotlin/com/flipcash/app/backupkey/internal/BackupKeyScreenContent.kt b/apps/flipcash/features/backupkey/src/main/kotlin/com/flipcash/app/backupkey/internal/BackupKeyScreenContent.kt index 8226304cb..641a70e01 100644 --- a/apps/flipcash/features/backupkey/src/main/kotlin/com/flipcash/app/backupkey/internal/BackupKeyScreenContent.kt +++ b/apps/flipcash/features/backupkey/src/main/kotlin/com/flipcash/app/backupkey/internal/BackupKeyScreenContent.kt @@ -25,6 +25,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -59,8 +60,8 @@ internal fun BackupKeyScreenContent(viewModel: BackupKeyScreenViewModel) { val resources = LocalResources.current val dataState by viewModel.uiFlow.collectAsStateWithLifecycle() - var isExportSeedRequested by remember { mutableStateOf(false) } - var isStoragePermissionGranted by remember { mutableStateOf(false) } + var isExportSeedRequested by rememberSaveable { mutableStateOf(false) } + var isStoragePermissionGranted by rememberSaveable { mutableStateOf(false) } val isAccessKeyVisible = remember { MutableTransitionState(false) } val onPermissionResult = { result: PermissionResult -> diff --git a/apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/internal/screens/AccessKeyScreenContent.kt b/apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/internal/screens/AccessKeyScreenContent.kt index 5f347c7ff..0c741b026 100644 --- a/apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/internal/screens/AccessKeyScreenContent.kt +++ b/apps/flipcash/features/login/src/main/kotlin/com/flipcash/app/login/internal/screens/AccessKeyScreenContent.kt @@ -28,6 +28,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -78,8 +79,8 @@ internal fun AccessKeyScreen( val composeScope = rememberCoroutineScope() - var isExportSeedRequested by remember { mutableStateOf(false) } - var isStoragePermissionGranted by remember { mutableStateOf(false) } + var isExportSeedRequested by rememberSaveable { mutableStateOf(false) } + var isStoragePermissionGranted by rememberSaveable { mutableStateOf(false) } val onPermissionResult = { result: PermissionResult -> isStoragePermissionGranted = result == PermissionResult.Granted From 3a1f8a1036c700134b8ca7e7a17103233714d3ad Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:38:17 -0400 Subject: [PATCH 09/13] fix(compose): use staticCompositionLocalOf for singleton controllers LocalAppUpdater and LocalCoinbaseOnRampController are provided once at app startup and never change. Using staticCompositionLocalOf avoids unnecessary recomposition tracking overhead. --- .../main/kotlin/com/flipcash/app/updates/LocalAppUpdater.kt | 4 ++-- .../kotlin/com/flipcash/app/onramp/CoinbaseOnRampLocal.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/flipcash/shared/appupdates/src/main/kotlin/com/flipcash/app/updates/LocalAppUpdater.kt b/apps/flipcash/shared/appupdates/src/main/kotlin/com/flipcash/app/updates/LocalAppUpdater.kt index 46a09b29e..59f9283f4 100644 --- a/apps/flipcash/shared/appupdates/src/main/kotlin/com/flipcash/app/updates/LocalAppUpdater.kt +++ b/apps/flipcash/shared/appupdates/src/main/kotlin/com/flipcash/app/updates/LocalAppUpdater.kt @@ -1,10 +1,10 @@ package com.flipcash.app.updates -import androidx.compose.runtime.compositionLocalOf +import androidx.compose.runtime.staticCompositionLocalOf import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow -val LocalAppUpdater = compositionLocalOf { StubAppUpdateController() } +val LocalAppUpdater = staticCompositionLocalOf { StubAppUpdateController() } class StubAppUpdateController(updateInfo: UpdateInfo? = null): AppUpdateController { override val availableUpdate: StateFlow = MutableStateFlow(updateInfo) diff --git a/apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampLocal.kt b/apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampLocal.kt index 28ea59547..2490308fb 100644 --- a/apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampLocal.kt +++ b/apps/flipcash/shared/onramp/coinbase/src/main/kotlin/com/flipcash/app/onramp/CoinbaseOnRampLocal.kt @@ -1,6 +1,6 @@ package com.flipcash.app.onramp -import androidx.compose.runtime.compositionLocalOf +import androidx.compose.runtime.staticCompositionLocalOf val LocalCoinbaseOnRampController = - compositionLocalOf { throw IllegalStateException() } + staticCompositionLocalOf { throw IllegalStateException() } From ae4c2ccfa9cbc3b254877757bf05a73d3d04f0be Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:50:56 -0400 Subject: [PATCH 10/13] fix(compose): correct parameter ordering in shared components Reorder parameters to follow Compose API guidelines: required params first, then modifier, then optional params, then trailing lambdas. Also fix modifier chain ordering in Pill and CodeToggleSwitch so the caller modifier is applied outermost. --- .../src/main/kotlin/com/getcode/ui/components/Badge.kt | 2 +- .../src/main/kotlin/com/getcode/ui/components/Pill.kt | 5 ++--- .../kotlin/com/getcode/ui/components/SegmentedControl.kt | 6 +++--- .../kotlin/com/getcode/ui/theme/CodeSegmentedControl.kt | 4 ++-- .../src/main/kotlin/com/getcode/ui/theme/CodeSwitch.kt | 6 +++--- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/Badge.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/Badge.kt index 878998cdb..d105c6e28 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/Badge.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/Badge.kt @@ -23,8 +23,8 @@ import com.getcode.theme.CodeTheme @Composable fun Badge( - modifier: Modifier = Modifier, count: Int, + modifier: Modifier = Modifier, showMoreUnread: Boolean = count > 99, color: Color = CodeTheme.colors.brand, contentColor: Color = Color.White, diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/Pill.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/Pill.kt index a10b56465..fa3d3fe15 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/Pill.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/Pill.kt @@ -20,11 +20,11 @@ import com.getcode.theme.CodeTheme @Composable fun Pill( + text: String, modifier: Modifier = Modifier, backgroundColor: Color = Black50, contentColor: Color = Color.White, shape: CornerBasedShape = CircleShape, - text: String, textStyle: TextStyle = CodeTheme.typography.caption, contentPadding: PaddingValues = PaddingValues( horizontal = CodeTheme.dimens.grid.x2, @@ -60,11 +60,10 @@ fun Pill( content: @Composable () -> Unit, ) { Row( - modifier = Modifier + modifier = modifier .wrapContentSize() .clip(shape) .background(backgroundColor) - .then(modifier) .padding(contentPadding) ) { CompositionLocalProvider(LocalContentColor provides contentColor) { diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/SegmentedControl.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/SegmentedControl.kt index 804c9b0d8..da4f15297 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/SegmentedControl.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/SegmentedControl.kt @@ -14,12 +14,12 @@ import androidx.compose.ui.unit.Dp fun SegmentedControl( options: List, selected: T?, + onSelectionChanged: (T) -> Unit, + modifier: Modifier = Modifier, colors: SegmentedButtonColors = SegmentedButtonDefaults.colors(), contentPadding: PaddingValues = SegmentedButtonDefaults.ContentPadding, - mapper: @Composable SingleChoiceSegmentedButtonRowScope.(T) -> Unit, space: Dp = SegmentedButtonDefaults.BorderWidth, - modifier: Modifier = Modifier, - onSelectionChanged: (T) -> Unit, + mapper: @Composable SingleChoiceSegmentedButtonRowScope.(T) -> Unit, ) { SingleChoiceSegmentedButtonRow( modifier = modifier, diff --git a/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeSegmentedControl.kt b/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeSegmentedControl.kt index 7e03d8927..e76df86e4 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeSegmentedControl.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeSegmentedControl.kt @@ -14,9 +14,9 @@ import com.getcode.ui.components.SegmentedControl fun CodeSegmentedControl( options: List, selected: T?, - mapper: @Composable SingleChoiceSegmentedButtonRowScope.(T) -> Unit, - modifier: Modifier = Modifier, onSelectionChanged: (T) -> Unit, + modifier: Modifier = Modifier, + mapper: @Composable SingleChoiceSegmentedButtonRowScope.(T) -> Unit, ) { SegmentedControl( options = options, diff --git a/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeSwitch.kt b/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeSwitch.kt index 30b772e94..f21fb3a05 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeSwitch.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeSwitch.kt @@ -40,9 +40,9 @@ object CodeToggleSwitchDefaults { @Composable fun CodeToggleSwitch( + checked: Boolean, modifier: Modifier = Modifier, enabled: Boolean = true, - checked: Boolean, onCheckedChange: ((Boolean) -> Unit)? = null, ) { val width = 51.dp @@ -62,7 +62,7 @@ fun CodeToggleSwitch( val trackColor by colors.trackColor(enabled = enabled, checked = checked) val thumbColor by colors.thumbColor(enabled = enabled, checked = checked) Canvas( - modifier = Modifier + modifier = modifier .size(width = width, height = height) .addIf(onCheckedChange != null) { Modifier.pointerInput(Unit) { @@ -72,7 +72,7 @@ fun CodeToggleSwitch( } ) } - }.then(modifier) + } ) { drawRoundRect( color = trackColor, From 7ad1fdf8e0808785e2b2442d7944a0643a329ea2 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:51:11 -0400 Subject: [PATCH 11/13] fix(compose): add modifier parameter to ConnectionStatus Shared reusable component was missing a modifier parameter, preventing callers from controlling its layout. --- .../com/getcode/ui/components/ConnectionStatusComponent.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/ConnectionStatusComponent.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/ConnectionStatusComponent.kt index 3ad26108f..20d932c5c 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/ConnectionStatusComponent.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/ConnectionStatusComponent.kt @@ -16,8 +16,8 @@ import com.getcode.utils.network.NetworkState import com.getcode.utils.network.connectivity.NetworkStateProvider @Composable -fun ConnectionStatus(state: NetworkState) { - Row { +fun ConnectionStatus(state: NetworkState, modifier: Modifier = Modifier) { + Row(modifier = modifier) { when { !state.connected && state.type != ConnectionType.Unknown -> { CodeCircularProgressIndicator( From 1414b1c87ea7fb032588f6f66f4541000c66018a Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 10:51:27 -0400 Subject: [PATCH 12/13] fix(compose): key BillCustomizationScreen effect on changing state LaunchedEffect(Unit) was reading state.customizations and state.purchaseAmount but only running once. Key on these values so the effect re-fires when they change. --- .../currencycreator/internal/screens/BillCustomizationScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/flipcash/features/currency-creator/src/main/kotlin/com/flipcash/app/currencycreator/internal/screens/BillCustomizationScreen.kt b/apps/flipcash/features/currency-creator/src/main/kotlin/com/flipcash/app/currencycreator/internal/screens/BillCustomizationScreen.kt index 1dae52e10..6b12f0b64 100644 --- a/apps/flipcash/features/currency-creator/src/main/kotlin/com/flipcash/app/currencycreator/internal/screens/BillCustomizationScreen.kt +++ b/apps/flipcash/features/currency-creator/src/main/kotlin/com/flipcash/app/currencycreator/internal/screens/BillCustomizationScreen.kt @@ -34,7 +34,7 @@ internal fun BillCustomizationScreen() { BillCustomizationContent(state, viewModel::dispatchEvent) - LaunchedEffect(Unit) { + LaunchedEffect(state.customizations, state.purchaseAmount) { controller.dispatchEvent( Event.Load( customizations = state.customizations, From 1970c0532dbb97c9ba1cd91b1a6e5ee58ad6837a Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Thu, 4 Jun 2026 11:09:30 -0400 Subject: [PATCH 13/13] refactor(compose): remove rememberedClickable/rememberedLongClickable wrappers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With Strong Skipping Mode enabled, the remember-based lambda caching in rememberedClickable is redundant — Compose auto-stabilizes lambdas. The Modifier.composed wrapper also allocates a sub-composition per element per recomposition. - Delete both rememberedClickable overloads from Modifier.kt - Rename rememberedLongClickable to longClickable (no composed) - Simplify noRippleClickable (no composed, null interactionSource) - Keep unboundedClickable (needs composed for @Composable ripple()) - Migrate 38 call sites across the codebase: - Simple .rememberedClickable -> .clickable (standard foundation) - No-ripple pattern -> .noRippleClickable - Long click -> .longClickable - Remove unused MutableInteractionSource imports --- .../com/flipcash/app/core/ui/TileButton.kt | 4 +- .../app/core/ui/TokenSelectionPill.kt | 6 +- .../internal/components/CashReservesRow.kt | 4 +- .../BillCustomizationScaffold.kt | 8 +-- .../components/BillPlayground.kt | 4 +- .../components/ColorOptionItem.kt | 4 +- .../customization/components/ColorPanel.kt | 4 +- .../customization/components/ColorSlots.kt | 3 +- .../components/HueControlButton.kt | 4 +- .../customization/features/TextureControls.kt | 6 +- .../internal/phone/PhoneCountryCodeScreen.kt | 4 +- .../deposit/internal/DepositScreenContent.kt | 4 +- .../internal/screens/ContactListScreen.kt | 4 +- .../internal/components/TokenMetricsRow.kt | 6 +- .../app/invite/InviteContactScreen.kt | 4 +- .../flipcash/app/myaccount/MyAccountScreen.kt | 9 +-- .../myaccount/internal/AccountInfoHeader.kt | 4 +- .../internal/UserProfileScreenContent.kt | 6 +- .../internal/bills/BillManagementOptions.kt | 6 +- .../internal/ui/components/DecorView.kt | 9 +-- .../internal/ShareAppScreenContent.kt | 4 +- .../internal/components/info/SocialChip.kt | 4 +- .../internal/components/EditableRow.kt | 4 +- .../userflags/internal/components/Editors.kt | 6 +- .../app/phone/components/OtpInputField.kt | 4 +- .../app/phone/components/PhoneInputField.kt | 4 +- .../internal/components/ListRowItem.kt | 4 +- .../ui/components/CircularIconButton.kt | 4 +- .../com/getcode/ui/components/ListItem.kt | 4 +- .../ui/components/SelectionContainer.kt | 4 +- .../ui/components/SettingsSwitchRow.kt | 4 +- .../getcode/ui/components/SwipeActionRow.kt | 4 +- .../ui/components/bars/BottomBarContainer.kt | 17 ++--- .../ui/components/bars/TopBarContainer.kt | 7 +-- .../getcode/ui/components/chat/ChatInput.kt | 6 +- .../getcode/ui/components/chat/ChatNode.kt | 4 +- .../getcode/ui/components/text/AmountArea.kt | 4 +- .../kotlin/com/getcode/ui/theme/CodeKeyPad.kt | 4 +- .../kotlin/com/getcode/ui/core/Modifier.kt | 63 ++++--------------- 39 files changed, 104 insertions(+), 154 deletions(-) diff --git a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TileButton.kt b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TileButton.kt index 7b1794dda..22d58b92f 100644 --- a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TileButton.kt +++ b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TileButton.kt @@ -18,7 +18,7 @@ import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.unit.dp import com.getcode.theme.CodeTheme import com.getcode.theme.extraSmall -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable fun TileButton( @@ -35,7 +35,7 @@ fun TileButton( shape = CodeTheme.shapes.extraSmall, ) .clip(CodeTheme.shapes.extraSmall) - .rememberedClickable(onClick = onClick) + .clickable(onClick = onClick) .padding(contentPadding), contentAlignment = Alignment.Center, ) { diff --git a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TokenSelectionPill.kt b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TokenSelectionPill.kt index df4c94d67..65875ead5 100644 --- a/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TokenSelectionPill.kt +++ b/apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TokenSelectionPill.kt @@ -16,7 +16,7 @@ import androidx.compose.ui.res.painterResource import com.getcode.opencode.model.financial.Token import com.getcode.theme.CodeTheme import com.getcode.ui.core.R -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable fun TokenSelectionPill(token: Token?, onClick: () -> Unit) { @@ -29,7 +29,7 @@ fun TokenSelectionPill(token: Token?, onClick: () -> Unit) { Row( modifier = Modifier .clip(CircleShape) - .rememberedClickable { onClick() }, + .clickable { onClick() }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy( space = CodeTheme.dimens.grid.x1, @@ -71,7 +71,7 @@ fun TokenSelectionPill( Row( modifier = Modifier .clip(CircleShape) - .rememberedClickable { onClick() }, + .clickable { onClick() }, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy( space = CodeTheme.dimens.grid.x1, diff --git a/apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/components/CashReservesRow.kt b/apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/components/CashReservesRow.kt index 6f4c3ec5d..242d3679f 100644 --- a/apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/components/CashReservesRow.kt +++ b/apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/components/CashReservesRow.kt @@ -16,7 +16,7 @@ import com.flipcash.features.balance.R import com.getcode.opencode.model.financial.LocalFiat import com.getcode.theme.CodeTheme import com.getcode.ui.components.text.AnimatedNumberText -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun CashReservesRow( @@ -26,7 +26,7 @@ internal fun CashReservesRow( Row( modifier = Modifier .fillMaxWidth() - .rememberedClickable { + .clickable { onClick() } .padding( diff --git a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/BillCustomizationScaffold.kt b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/BillCustomizationScaffold.kt index 26fe9c18e..53554b1fa 100644 --- a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/BillCustomizationScaffold.kt +++ b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/BillCustomizationScaffold.kt @@ -46,7 +46,7 @@ import com.flipcash.features.bill.playground.R import com.getcode.theme.CodeTheme import com.getcode.ui.components.AppBarDefaults import com.getcode.ui.core.measured -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.utils.AnimationUtils @OptIn(ExperimentalMaterialApi::class) @@ -192,7 +192,7 @@ private fun TopBar( modifier = Modifier .background(Color.Black.copy(0.19f), CircleShape) .clip(CircleShape) - .rememberedClickable(enabled = canUndo) { onUndo() } + .clickable(enabled = canUndo) { onUndo() } .padding(2.dp), painter = painterResource(R.drawable.ic_undo), colorFilter = ColorFilter.tint(Color.White.copy(undoAlpha)), @@ -203,7 +203,7 @@ private fun TopBar( modifier = Modifier .background(Color.Black.copy(0.19f), CircleShape) .clip(CircleShape) - .rememberedClickable { onCopy() } + .clickable { onCopy() } .padding( horizontal = CodeTheme.dimens.grid.x2, vertical = CodeTheme.dimens.grid.x1 @@ -216,7 +216,7 @@ private fun TopBar( modifier = Modifier .background(Color.Black.copy(0.19f), CircleShape) .clip(CircleShape) - .rememberedClickable { onDone() } + .clickable { onDone() } .padding( horizontal = CodeTheme.dimens.grid.x2, vertical = CodeTheme.dimens.grid.x1 diff --git a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/BillPlayground.kt b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/BillPlayground.kt index 43c0602ea..8c885db37 100644 --- a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/BillPlayground.kt +++ b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/BillPlayground.kt @@ -56,7 +56,7 @@ import com.getcode.theme.CodeTheme import com.getcode.ui.components.Pill import com.getcode.ui.core.addIf import com.getcode.ui.core.measured -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.core.swallowClicks @OptIn(ExperimentalSharedTransitionApi::class) @@ -196,7 +196,7 @@ private fun FeatureTab( color = Color.White, shape = CodeTheme.shapes.medium, ) - .rememberedClickable(onClick = onClick), + .clickable(onClick = onClick), backgroundColor = backgroundColor, contentColor = contentColor, text = stringResource(feature.labelRes), diff --git a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorOptionItem.kt b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorOptionItem.kt index b6a437f80..e5e04d0a8 100644 --- a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorOptionItem.kt +++ b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorOptionItem.kt @@ -10,7 +10,7 @@ import com.getcode.opencode.model.ui.BillBackground import com.flipcash.app.bill.customization.Event.Colors as ColorEvent import com.getcode.theme.CodeTheme import com.getcode.ui.core.addIf -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.utils.hexToColor import com.getcode.ui.utils.hsv @@ -55,7 +55,7 @@ internal fun ColorOptionItem( shape = CodeTheme.shapes.small ) } - .rememberedClickable { + .clickable { when (option) { is BillBackground.Gradient -> dispatchEvent( ColorEvent.LoadBackground( diff --git a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorPanel.kt b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorPanel.kt index d0b4b43bb..866810d05 100644 --- a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorPanel.kt +++ b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorPanel.kt @@ -28,7 +28,7 @@ import androidx.compose.ui.unit.dp import com.flipcash.app.theme.FlipcashPreview import com.flipcash.features.bill.playground.R import com.getcode.theme.CodeTheme -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.utils.Hsv import com.getcode.ui.utils.hsv @@ -72,7 +72,7 @@ internal fun ColorPanel( shape = CodeTheme.shapes.small ) .clip(CodeTheme.shapes.small) - .rememberedClickable { onClose() } + .clickable { onClose() } .padding(CodeTheme.dimens.grid.x3), contentAlignment = Alignment.Center ) { diff --git a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorSlots.kt b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorSlots.kt index bd8dec4f6..ccc4e7482 100644 --- a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorSlots.kt +++ b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/ColorSlots.kt @@ -44,8 +44,7 @@ import com.flipcash.app.bill.customization.Event.Colors as ColorEvent import com.flipcash.app.bill.customization.models.ColorStore import com.flipcash.features.bill.playground.R import com.getcode.theme.CodeTheme -import com.getcode.ui.core.rememberedClickable -import com.getcode.ui.core.rememberedLongClickable + @OptIn(ExperimentalSharedTransitionApi::class, ExperimentalAnimatableApi::class) @Composable diff --git a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/HueControlButton.kt b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/HueControlButton.kt index a9164a673..82da29560 100644 --- a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/HueControlButton.kt +++ b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/components/HueControlButton.kt @@ -26,7 +26,7 @@ import com.flipcash.app.theme.FlipcashPreview import com.flipcash.features.bill.playground.R import com.getcode.theme.CodeTheme import com.getcode.theme.extraSmall -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun HueControlButton( @@ -39,7 +39,7 @@ internal fun HueControlButton( .fillMaxHeight() .rainbowBackground() .clip(CodeTheme.shapes.small) - .rememberedClickable { onClick() } + .clickable { onClick() } .padding(CodeTheme.dimens.thickBorder) .background( color = Color.Black.copy(0.50f), diff --git a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/features/TextureControls.kt b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/features/TextureControls.kt index a08a7b4ae..f0a054df7 100644 --- a/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/features/TextureControls.kt +++ b/apps/flipcash/features/bill-customization/src/main/kotlin/com/flipcash/app/bill/customization/features/TextureControls.kt @@ -35,7 +35,7 @@ import com.flipcash.app.bill.customization.internal.features.BlendMode import com.flipcash.app.bill.customization.internal.features.GraphicState import com.getcode.theme.CodeTheme import com.getcode.ui.components.Pill -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.flipcash.app.bill.customization.Event.Graphics as GraphicsEvent @Composable @@ -76,7 +76,7 @@ internal fun TextureControls( shape = CodeTheme.shapes.large ) .clip(CodeTheme.shapes.large) - .rememberedClickable { + .clickable { dispatchEvent(GraphicsEvent.ApplyGraphic(index)) }, contentAlignment = Alignment.Center, @@ -157,7 +157,7 @@ internal fun BlendModeTab( Pill( modifier = modifier .alpha(alpha) - .rememberedClickable(onClick = onClick), + .clickable(onClick = onClick), backgroundColor = backgroundColor, contentColor = Color.White, text = stringResource(mode.labelRes), diff --git a/apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/phone/PhoneCountryCodeScreen.kt b/apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/phone/PhoneCountryCodeScreen.kt index de9261173..213601de8 100644 --- a/apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/phone/PhoneCountryCodeScreen.kt +++ b/apps/flipcash/features/contact-verification/src/main/kotlin/com/flipcash/app/contact/verification/internal/phone/PhoneCountryCodeScreen.kt @@ -27,7 +27,7 @@ import com.flipcash.app.phone.LocalPhoneUtils import com.flipcash.app.theme.FlipcashPreview import com.flipcash.shared.phone.R import com.getcode.theme.CodeTheme -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun PhoneCountryCodeScreen( @@ -62,7 +62,7 @@ private fun PhoneCountrySelectionList( Row( modifier = Modifier .fillMaxWidth() - .rememberedClickable { onSelection(countryCode) }, + .clickable { onSelection(countryCode) }, ) { countryCode.resId?.let { resId -> Image( diff --git a/apps/flipcash/features/deposit/src/main/kotlin/com/flipcash/app/deposit/internal/DepositScreenContent.kt b/apps/flipcash/features/deposit/src/main/kotlin/com/flipcash/app/deposit/internal/DepositScreenContent.kt index 76b93354d..81fd3ab32 100644 --- a/apps/flipcash/features/deposit/src/main/kotlin/com/flipcash/app/deposit/internal/DepositScreenContent.kt +++ b/apps/flipcash/features/deposit/src/main/kotlin/com/flipcash/app/deposit/internal/DepositScreenContent.kt @@ -28,7 +28,7 @@ import com.getcode.theme.CodeTheme import com.getcode.theme.White import com.getcode.theme.White05 import com.getcode.theme.extraSmall -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.theme.ButtonState import com.getcode.ui.theme.CodeButton import com.getcode.ui.theme.CodeScaffold @@ -95,7 +95,7 @@ private fun DepositScreenContent( .fillMaxWidth() .height(CodeTheme.dimens.grid.x10) .background(White05) - .rememberedClickable { dispatchEvent(DepositViewModel.Event.CopyAddress) } + .clickable { dispatchEvent(DepositViewModel.Event.CopyAddress) } .padding( start = CodeTheme.dimens.grid.x3, top = CodeTheme.dimens.grid.x2, 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 c43e33558..0a354c1cf 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 @@ -72,7 +72,7 @@ import com.getcode.ui.components.CircularIconButton import com.getcode.ui.components.SearchInput import com.getcode.ui.components.SwipeAction import com.getcode.ui.components.SwipeActionRow -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.core.verticalScrollStateGradient import com.getcode.ui.theme.CodeCircularProgressIndicator import com.getcode.ui.theme.CodeScaffold @@ -346,7 +346,7 @@ private fun ContactRowItem( Row( modifier = Modifier .fillMaxWidth() - .rememberedClickable(onClick = onClick) + .clickable(onClick = onClick) .padding( vertical = CodeTheme.dimens.inset, horizontal = CodeTheme.dimens.inset, diff --git a/apps/flipcash/features/discovery/src/main/kotlin/com/flipcash/app/discovery/internal/components/TokenMetricsRow.kt b/apps/flipcash/features/discovery/src/main/kotlin/com/flipcash/app/discovery/internal/components/TokenMetricsRow.kt index 43fc96723..9c12aa3e8 100644 --- a/apps/flipcash/features/discovery/src/main/kotlin/com/flipcash/app/discovery/internal/components/TokenMetricsRow.kt +++ b/apps/flipcash/features/discovery/src/main/kotlin/com/flipcash/app/discovery/internal/components/TokenMetricsRow.kt @@ -32,7 +32,7 @@ import com.getcode.opencode.model.ui.WindowedRange import com.getcode.theme.CodeTheme import com.getcode.ui.components.charts.LineTrend import com.getcode.ui.core.addIf -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable @@ -43,7 +43,7 @@ internal fun RankedTokenMetricsRow( onClick: () -> Unit, ) { Row( - modifier = Modifier.rememberedClickable(onClick = onClick).then(modifier), + modifier = Modifier.clickable(onClick = onClick).then(modifier), verticalAlignment = Alignment.CenterVertically ) { RankBadge(rank) @@ -61,7 +61,7 @@ internal fun TokenMetricsRow( Row( modifier = modifier .addIf(onClick != null) { - Modifier.rememberedClickable(onClick = { onClick?.invoke() }) + Modifier.clickable(onClick = { onClick?.invoke() }) }, horizontalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x2), verticalAlignment = Alignment.CenterVertically, diff --git a/apps/flipcash/features/invite/src/main/kotlin/com/flipcash/app/invite/InviteContactScreen.kt b/apps/flipcash/features/invite/src/main/kotlin/com/flipcash/app/invite/InviteContactScreen.kt index baf0c06d1..4b631d6a4 100644 --- a/apps/flipcash/features/invite/src/main/kotlin/com/flipcash/app/invite/InviteContactScreen.kt +++ b/apps/flipcash/features/invite/src/main/kotlin/com/flipcash/app/invite/InviteContactScreen.kt @@ -23,7 +23,7 @@ import coil3.compose.AsyncImage import com.flipcash.core.R import com.getcode.navigation.scenes.LocalBottomSheetDismissDispatcher import com.getcode.theme.CodeTheme -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable fun InviteContactScreen(phoneNumber: String) { @@ -71,7 +71,7 @@ private fun ChannelItem( ) { Column( modifier = Modifier - .rememberedClickable(onClick = onClick) + .clickable(onClick = onClick) .padding(CodeTheme.dimens.grid.x2), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x1), diff --git a/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/MyAccountScreen.kt b/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/MyAccountScreen.kt index 81414cfb8..ccef20424 100644 --- a/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/MyAccountScreen.kt +++ b/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/MyAccountScreen.kt @@ -1,6 +1,6 @@ package com.flipcash.app.myaccount -import androidx.compose.foundation.interaction.MutableInteractionSource + import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable @@ -17,7 +17,7 @@ import com.flipcash.core.R import com.getcode.navigation.core.LocalCodeNavigator import com.getcode.ui.components.AppBarDefaults import com.getcode.ui.components.AppBarWithTitle -import com.getcode.ui.core.rememberedClickable +import com.getcode.ui.core.noRippleClickable import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -35,10 +35,7 @@ fun MyAccountScreen() { AppBarWithTitle( title = { AppBarDefaults.Title( - modifier = Modifier.rememberedClickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null - ) { viewModel.dispatchEvent(MyAccountScreenViewModel.Event.OnTitleClicked) }, + modifier = Modifier.noRippleClickable { viewModel.dispatchEvent(MyAccountScreenViewModel.Event.OnTitleClicked) }, text = stringResource(R.string.title_myAccount), ) }, diff --git a/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/AccountInfoHeader.kt b/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/AccountInfoHeader.kt index 52a261cb4..03261895a 100644 --- a/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/AccountInfoHeader.kt +++ b/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/AccountInfoHeader.kt @@ -24,7 +24,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.getcode.ui.components.BetaIndicator import com.getcode.theme.CodeTheme -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun AccountInfoHeader( @@ -83,7 +83,7 @@ private fun CopyableTextEntry( onCopy: () -> Unit ) { Column( - modifier = modifier.rememberedClickable(onClick = onCopy) + modifier = modifier.clickable(onClick = onCopy) ) { Row( verticalAlignment = Alignment.CenterVertically diff --git a/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/UserProfileScreenContent.kt b/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/UserProfileScreenContent.kt index 9e7890bb6..535c0488d 100644 --- a/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/UserProfileScreenContent.kt +++ b/apps/flipcash/features/myaccount/src/main/kotlin/com/flipcash/app/myaccount/internal/UserProfileScreenContent.kt @@ -23,7 +23,7 @@ import com.flipcash.core.R import com.flipcash.services.models.SocialAccount import com.getcode.theme.CodeTheme import com.getcode.ui.components.text.SectionHeader -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun UserProfileScreenContent( @@ -139,7 +139,7 @@ private fun ContactMethodRow( ) { Row( modifier = Modifier - .rememberedClickable { onRowClick() } + .clickable { onRowClick() } .fillMaxWidth() .padding( horizontal = CodeTheme.dimens.inset, @@ -222,7 +222,7 @@ private fun AddContactMethodRow( ) { Row( modifier = Modifier - .rememberedClickable { onClick() } + .clickable { onClick() } .fillMaxWidth() .padding( horizontal = CodeTheme.dimens.inset, diff --git a/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/bills/BillManagementOptions.kt b/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/bills/BillManagementOptions.kt index e7b99ba10..459c33afe 100644 --- a/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/bills/BillManagementOptions.kt +++ b/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/bills/BillManagementOptions.kt @@ -22,7 +22,7 @@ import com.getcode.theme.CodeTheme import com.getcode.theme.White import com.getcode.ui.theme.CodeCircularProgressIndicator import com.getcode.ui.components.Pill -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun BillManagementOptions( @@ -46,7 +46,7 @@ internal fun BillManagementOptions( if (primaryAction != null) { Pill( modifier = Modifier - .rememberedClickable(enabled = !isSending) { primaryAction.action() }, + .clickable(enabled = !isSending) { primaryAction.action() }, contentPadding = PaddingValues(0.dp), backgroundColor = CodeTheme.colors.action, ) { @@ -89,7 +89,7 @@ internal fun BillManagementOptions( if (secondaryAction != null) { Pill( modifier = Modifier - .rememberedClickable(enabled = isInteractable) { secondaryAction.action() }, + .clickable(enabled = isInteractable) { secondaryAction.action() }, contentPadding = PaddingValues(0.dp), backgroundColor = CodeTheme.colors.action, ) { diff --git a/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/ui/components/DecorView.kt b/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/ui/components/DecorView.kt index d4a531e42..942e435b8 100644 --- a/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/ui/components/DecorView.kt +++ b/apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/ui/components/DecorView.kt @@ -6,7 +6,7 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.interaction.MutableInteractionSource + import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -48,7 +48,7 @@ import com.flipcash.features.scanner.R import com.getcode.theme.CodeTheme import com.getcode.theme.xxl import com.getcode.ui.components.Pill -import com.getcode.ui.core.rememberedClickable +import com.getcode.ui.core.noRippleClickable import com.getcode.ui.core.unboundedClickable import com.getcode.utils.network.LocalNetworkObserver @@ -87,10 +87,7 @@ internal fun DecorView( .padding(horizontal = CodeTheme.dimens.grid.x3) .align(Alignment.TopStart) .width(CodeTheme.dimens.staticGrid.x18) - .rememberedClickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null - ) { + .noRippleClickable { onAction(ScannerDecorItem.Logo) }.testTag("flipcash_logo"), painter = painterResource(R.drawable.ic_flipcash_logo_w_name), diff --git a/apps/flipcash/features/shareapp/src/main/kotlin/com/flipcash/app/shareapp/internal/ShareAppScreenContent.kt b/apps/flipcash/features/shareapp/src/main/kotlin/com/flipcash/app/shareapp/internal/ShareAppScreenContent.kt index defd0a3cc..a3755a536 100644 --- a/apps/flipcash/features/shareapp/src/main/kotlin/com/flipcash/app/shareapp/internal/ShareAppScreenContent.kt +++ b/apps/flipcash/features/shareapp/src/main/kotlin/com/flipcash/app/shareapp/internal/ShareAppScreenContent.kt @@ -39,7 +39,7 @@ import com.getcode.theme.CodeTheme import com.getcode.ui.components.Cloudy import com.getcode.ui.components.SelectionContainer import com.getcode.ui.components.rememberSelectionState -import com.getcode.ui.core.rememberedLongClickable +import com.getcode.ui.core.longClickable import com.getcode.ui.theme.ButtonState import com.getcode.ui.theme.CodeButton import com.getcode.ui.theme.CodeCircularProgressIndicator @@ -123,7 +123,7 @@ internal fun ShareAppScreenContent() { Image( modifier = Modifier .onPlaced { contentRect = it.boundsInWindow() } - .rememberedLongClickable { + .longClickable { onClick() } .scale(selectionState.scale.value), diff --git a/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/SocialChip.kt b/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/SocialChip.kt index 7648b6a56..01eea1cd0 100644 --- a/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/SocialChip.kt +++ b/apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/components/info/SocialChip.kt @@ -20,7 +20,7 @@ import com.getcode.opencode.model.financial.SocialLink import com.getcode.theme.CodeTheme import com.getcode.theme.White50 import com.getcode.theme.extraSmall -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun SocialChip( @@ -33,7 +33,7 @@ internal fun SocialChip( modifier = modifier .background(CodeTheme.colors.surfaceVariant, CodeTheme.shapes.extraSmall) .clip(CodeTheme.shapes.extraSmall) - .rememberedClickable { + .clickable { uriHandler.openUri(socialLink.uri) }.padding( horizontal = CodeTheme.dimens.grid.x3, diff --git a/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/components/EditableRow.kt b/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/components/EditableRow.kt index 82725d45a..82de8a738 100644 --- a/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/components/EditableRow.kt +++ b/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/components/EditableRow.kt @@ -24,7 +24,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.flipcash.app.userflags.internal.EditableEntry import com.getcode.theme.CodeTheme -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun EditableRow( @@ -35,7 +35,7 @@ internal fun EditableRow( ) { Row( modifier = modifier - .rememberedClickable { onClick() } + .clickable { onClick() } .padding(horizontal = CodeTheme.dimens.grid.x3), verticalAlignment = Alignment.CenterVertically, ) { diff --git a/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/components/Editors.kt b/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/components/Editors.kt index 879e27f5f..33a9930f0 100644 --- a/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/components/Editors.kt +++ b/apps/flipcash/features/userflags/src/main/kotlin/com/flipcash/app/userflags/internal/components/Editors.kt @@ -25,7 +25,7 @@ import com.flipcash.app.userflags.internal.EditableEntry import com.flipcash.app.userflags.internal.UserFlagsViewModel import com.getcode.theme.CodeTheme import com.getcode.ui.components.TextInput -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.theme.CodeButton import com.getcode.ui.theme.CodeCheckbox import com.getcode.ui.theme.CodeRadioButton @@ -90,7 +90,7 @@ internal fun MultiSelectContent( Row( modifier = Modifier .fillMaxWidth() - .rememberedClickable { + .clickable { if (value in selected) selected.remove(value) else selected.add(value) } .padding(vertical = CodeTheme.dimens.grid.x2), @@ -135,7 +135,7 @@ internal fun SingleSelectContent( Row( modifier = Modifier .fillMaxWidth() - .rememberedClickable { selected = value } + .clickable { selected = value } .padding(vertical = CodeTheme.dimens.grid.x2), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x2), diff --git a/apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/components/OtpInputField.kt b/apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/components/OtpInputField.kt index feee3c010..abba90565 100644 --- a/apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/components/OtpInputField.kt +++ b/apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/components/OtpInputField.kt @@ -34,7 +34,7 @@ import com.flipcash.app.theme.FlipcashPreview import com.getcode.theme.CodeTheme import com.getcode.theme.WindowSizeClass import com.getcode.ui.components.TextInput -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.utils.rememberKeyboardController import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn @@ -132,7 +132,7 @@ private fun OtpBox( .height(height) .width(CodeTheme.dimens.grid.x7) .clip(CodeTheme.shapes.small) - .rememberedClickable(onClick = onClick) + .clickable(onClick = onClick) .border( border = if (isHighlighted) BorderStroke(CodeTheme.dimens.thickBorder, color = Color.White.copy(0.34f)) diff --git a/apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/components/PhoneInputField.kt b/apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/components/PhoneInputField.kt index f0d7f5313..5f13fb883 100644 --- a/apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/components/PhoneInputField.kt +++ b/apps/flipcash/shared/phone/src/main/kotlin/com/flipcash/app/phone/components/PhoneInputField.kt @@ -44,7 +44,7 @@ import com.getcode.theme.CodeTheme import com.getcode.ui.components.TextInput import com.getcode.ui.components.VerticalDivider import com.getcode.ui.core.rememberAnimationScale -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.core.scaled import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -84,7 +84,7 @@ fun PhoneInputField( Row( modifier = Modifier .height(CodeTheme.dimens.grid.x12) - .rememberedClickable { + .clickable { composeScope.launch { focusManager.clearFocus(true) delay(300.scaled(animationScale)) diff --git a/apps/flipcash/shared/region-selection/ui/src/main/kotlin/com/flipcash/app/currency/internal/components/ListRowItem.kt b/apps/flipcash/shared/region-selection/ui/src/main/kotlin/com/flipcash/app/currency/internal/components/ListRowItem.kt index 29244c053..2d72bb4de 100644 --- a/apps/flipcash/shared/region-selection/ui/src/main/kotlin/com/flipcash/app/currency/internal/components/ListRowItem.kt +++ b/apps/flipcash/shared/region-selection/ui/src/main/kotlin/com/flipcash/app/currency/internal/components/ListRowItem.kt @@ -24,7 +24,7 @@ import com.flipcash.app.currency.internal.RegionListItem import com.flipcash.features.currency.R import com.getcode.theme.CodeTheme import com.getcode.ui.components.SwipeActionRow -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable internal fun ListRowItem( @@ -41,7 +41,7 @@ internal fun ListRowItem( .background(CodeTheme.colors.background) .let { if (item.currency.rate > 0) { - it.rememberedClickable { onClick() } + it.clickable { onClick() } } else it } ) { diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/CircularIconButton.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/CircularIconButton.kt index e508552a7..3a27fb2b7 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/CircularIconButton.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/CircularIconButton.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.getcode.ui.components.AppBarDefaults.IconSize -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable private val ButtonSize = 40.dp private val ButtonBackground = Color.White.copy(alpha = 0.1f) @@ -31,7 +31,7 @@ fun CircularIconButton( .size(ButtonSize) .background(ButtonBackground, CircleShape) .clip(CircleShape) - .rememberedClickable { onClick() } + .clickable { onClick() } .then(if (testTag != null) Modifier.testTag(testTag) else Modifier), contentAlignment = Alignment.Center, ) { diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/ListItem.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/ListItem.kt index b027123c7..fe4b1c3e1 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/ListItem.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/ListItem.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.getcode.theme.CodeTheme -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable fun ListItem( @@ -33,7 +33,7 @@ fun ListItem( ) { Row( modifier = modifier - .rememberedClickable { onClick() } + .clickable { onClick() } .padding(CodeTheme.dimens.grid.x5) .fillMaxWidth() .wrapContentHeight(), diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/SelectionContainer.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/SelectionContainer.kt index f62345aa8..66d7da34e 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/SelectionContainer.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/SelectionContainer.kt @@ -25,7 +25,7 @@ import androidx.compose.ui.platform.TextToolbar import androidx.compose.ui.text.AnnotatedString import androidx.lifecycle.Lifecycle import com.getcode.ui.core.addIf -import com.getcode.ui.core.rememberedLongClickable +import com.getcode.ui.core.longClickable import com.getcode.ui.core.swallowClicks import com.getcode.util.vibration.LocalVibrator @@ -82,7 +82,7 @@ fun SelectionContainer( .addIf(contentRect == null) { Modifier .onPlaced { _contentRect = it.boundsInParent() } - .rememberedLongClickable { + .longClickable { onClick() } }, diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/SettingsSwitchRow.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/SettingsSwitchRow.kt index f1eb3075b..48981430c 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/SettingsSwitchRow.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/SettingsSwitchRow.kt @@ -27,7 +27,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.getcode.theme.CodeTheme import com.getcode.ui.theme.CodeToggleSwitch -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable fun SettingsSwitchRow( @@ -41,7 +41,7 @@ fun SettingsSwitchRow( ) { Row( modifier = modifier - .rememberedClickable(enabled) { onClick() } + .clickable(enabled = enabled) { onClick() } .padding(horizontal = CodeTheme.dimens.grid.x3), verticalAlignment = Alignment.CenterVertically ) { diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/SwipeActionRow.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/SwipeActionRow.kt index 7e551652d..9321dc7c4 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/SwipeActionRow.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/SwipeActionRow.kt @@ -46,7 +46,7 @@ import androidx.compose.ui.unit.IntOffset import com.getcode.theme.CodeTheme import com.getcode.theme.DesignSystem import com.getcode.theme.White50 -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.util.resources.R import kotlin.math.abs import kotlinx.coroutines.launch @@ -166,7 +166,7 @@ fun SwipeActionRow( modifier = Modifier .clip(RoundedCornerShape(50)) .background(action.background) - .rememberedClickable { + .clickable { scope.launch { state.snapTo(SwipeState.Settled) } action.onTriggered() }, diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/bars/BottomBarContainer.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/bars/BottomBarContainer.kt index 485128179..a34113f46 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/bars/BottomBarContainer.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/bars/BottomBarContainer.kt @@ -11,7 +11,7 @@ import androidx.compose.animation.slideOutVertically import androidx.compose.animation.togetherWith import androidx.compose.foundation.background import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource + import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -58,7 +58,8 @@ import com.getcode.theme.White import com.getcode.theme.White50 import com.getcode.ui.core.addIf import com.getcode.ui.core.rememberAnimationScale -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable +import com.getcode.ui.core.noRippleClickable import com.getcode.ui.core.scaled import com.getcode.ui.theme.ButtonState import com.getcode.ui.theme.CodeButton @@ -122,10 +123,7 @@ fun BottomBarContainer(barMessages: BarMessages, onShown: (BottomBarManager.Bott .fillMaxSize() .graphicsLayer { alpha = scrimAlpha } .background(CodeTheme.colors.scrim) - .rememberedClickable( - indication = null, - interactionSource = remember { MutableInteractionSource() } - ) { + .noRippleClickable { if (it.isDismissible) { scope.launch { onClose(SelectedBottomBarAction(-1), false) } } @@ -136,10 +134,7 @@ fun BottomBarContainer(barMessages: BarMessages, onShown: (BottomBarManager.Bott Box( modifier = Modifier .fillMaxSize() - .rememberedClickable( - indication = null, - interactionSource = remember { MutableInteractionSource() } - ) { + .noRippleClickable { scope.launch { onClose(SelectedBottomBarAction(-1), false) } } ) @@ -356,7 +351,7 @@ fun BottomBarView( Text( modifier = Modifier .fillMaxWidth() - .rememberedClickable { + .clickable { onClose(SelectedBottomBarAction(-1)) } .padding(vertical = CodeTheme.dimens.grid.x3), diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/bars/TopBarContainer.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/bars/TopBarContainer.kt index f0d61a214..620134972 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/bars/TopBarContainer.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/bars/TopBarContainer.kt @@ -6,7 +6,7 @@ import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.interaction.MutableInteractionSource + import androidx.compose.foundation.layout.* import androidx.compose.material.* import androidx.compose.runtime.* @@ -27,7 +27,7 @@ import com.getcode.manager.TopBarManager.TopBarMessageType.* import com.getcode.theme.* import com.getcode.ui.components.R import com.getcode.ui.components.VerticalDivider -import com.getcode.ui.core.rememberedClickable +import com.getcode.ui.core.noRippleClickable import kotlinx.coroutines.delay @Composable @@ -60,8 +60,7 @@ fun TopBarContainer( modifier = Modifier .fillMaxSize() .background(CodeTheme.colors.scrim) - .rememberedClickable(indication = null, - interactionSource = remember { MutableInteractionSource() }) {} + .noRippleClickable { } ) } diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatInput.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatInput.kt index 0388fcae4..0b7ab3c9d 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatInput.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatInput.kt @@ -41,7 +41,7 @@ import com.getcode.theme.extraLarge import com.getcode.theme.inputColors import com.getcode.ui.components.R import com.getcode.ui.components.TextInput -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable @Composable fun ChatInput( @@ -72,7 +72,7 @@ fun ChatInput( .align(Alignment.Bottom) .border(width = 1.dp, color = Color.White, shape = CircleShape) .clip(CircleShape) - .rememberedClickable { onSendCash() } + .clickable { onSendCash() } .size(ChatInput_Size) .padding(8.dp), contentAlignment = Alignment.Center, @@ -126,7 +126,7 @@ fun ChatInput( .align(Alignment.Bottom) .background(CodeTheme.colors.tertiary, shape = CircleShape) .clip(CircleShape) - .rememberedClickable { onSendMessage() } + .clickable { onSendMessage() } .padding(8.dp), contentAlignment = Alignment.Center, ) { diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatNode.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatNode.kt index 89bb66fdc..cfd2b27a7 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatNode.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/chat/ChatNode.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextOverflow import com.getcode.theme.CodeTheme import com.getcode.ui.components.Badge -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.util.DateUtils import com.getcode.util.formatTimeRelatively @@ -45,7 +45,7 @@ fun ChatNode( ) { Row( modifier = modifier - .rememberedClickable { onClick() } + .clickable { onClick() } .padding( vertical = CodeTheme.dimens.grid.x3, horizontal = CodeTheme.dimens.inset diff --git a/ui/components/src/main/kotlin/com/getcode/ui/components/text/AmountArea.kt b/ui/components/src/main/kotlin/com/getcode/ui/components/text/AmountArea.kt index 4e7aa4b25..971c660ab 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/components/text/AmountArea.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/components/text/AmountArea.kt @@ -26,7 +26,7 @@ import com.getcode.theme.White import com.getcode.theme.bolded import com.getcode.ui.components.ConnectionStatus import com.getcode.ui.components.R -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import com.getcode.ui.utils.ConstraintMode import com.getcode.utils.network.LocalNetworkObserver import com.getcode.utils.network.NetworkState @@ -57,7 +57,7 @@ fun AmountArea( ) { Column( modifier - .let { if (isClickable) it.rememberedClickable { onClick() } else it }, + .let { if (isClickable) it.clickable { onClick() } else it }, horizontalAlignment = CenterHorizontally ) { if (!isLoading) { diff --git a/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeKeyPad.kt b/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeKeyPad.kt index 24d09de85..612fa59fa 100644 --- a/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeKeyPad.kt +++ b/ui/components/src/main/kotlin/com/getcode/ui/theme/CodeKeyPad.kt @@ -39,7 +39,7 @@ import com.getcode.theme.CodeTheme import com.getcode.theme.Transparent import com.getcode.theme.White10 import com.getcode.ui.components.R -import com.getcode.ui.core.rememberedClickable +import androidx.compose.foundation.clickable import java.text.DecimalFormatSymbols @@ -150,7 +150,7 @@ private fun KeyBoardButton( } buttonPressed } - .rememberedClickable { buttonPressed = false }, + .clickable { buttonPressed = false }, contentAlignment = Alignment.Center ) { CompositionLocalProvider(LocalContentColor provides Color.White) { diff --git a/ui/core/src/main/kotlin/com/getcode/ui/core/Modifier.kt b/ui/core/src/main/kotlin/com/getcode/ui/core/Modifier.kt index 31b3ebfdc..e0a55fdd7 100644 --- a/ui/core/src/main/kotlin/com/getcode/ui/core/Modifier.kt +++ b/ui/core/src/main/kotlin/com/getcode/ui/core/Modifier.kt @@ -68,14 +68,13 @@ inline fun Modifier.addIf( } } -fun Modifier.noRippleClickable(enabled: Boolean = true, onClick: () -> Unit) = composed { +fun Modifier.noRippleClickable(enabled: Boolean = true, onClick: () -> Unit) = this.clickable( enabled = enabled, indication = null, - interactionSource = remember { MutableInteractionSource() }, + interactionSource = null, onClick = onClick ) -} fun Modifier.unboundedClickable( enabled: Boolean = true, @@ -86,7 +85,7 @@ fun Modifier.unboundedClickable( ) = this.composed { val interaction = interactionSource ?: remember { MutableInteractionSource() } - rememberedClickable( + clickable( onClick = onClick, enabled = enabled, role = role, @@ -99,58 +98,22 @@ fun Modifier.unboundedClickable( fun Modifier.debugBounds(color: Color = Color.Magenta, shape: Shape = RectangleShape) = this.border(1.dp, color, shape) -fun Modifier.rememberedClickable( - enabled: Boolean = true, - onClickLabel: String? = null, - interactionSource: MutableInteractionSource? = null, - role: Role? = null, - onClick: () -> Unit -) = composed { - val clicker = remember(enabled, onClickLabel, role, interactionSource, onClick) { - Modifier.clickable(enabled, onClickLabel, role, interactionSource, onClick) - } - - this.then(clicker) -} - @OptIn(ExperimentalFoundationApi::class) -fun Modifier.rememberedLongClickable( +fun Modifier.longClickable( enabled: Boolean = true, onLongClickLabel: String? = null, indication: Indication? = null, role: Role? = null, onLongClick: () -> Unit -) = composed { - val interactionSource = remember { MutableInteractionSource() } - val clicker = remember(enabled, onLongClickLabel, role, onLongClick) { - Modifier.combinedClickable( - interactionSource = interactionSource, - indication = indication, - enabled = enabled, - onLongClickLabel = onLongClickLabel, - onLongClick = onLongClick, - role = role, - onClick = {} - ) - } - - this.then(clicker) -} - -fun Modifier.rememberedClickable( - interactionSource: MutableInteractionSource, - indication: Indication?, - enabled: Boolean = true, - onClickLabel: String? = null, - role: Role? = null, - onClick: () -> Unit -) = composed { - - val clicker = remember(interactionSource, indication, enabled, onClickLabel, role, onClick) { - Modifier.clickable(interactionSource, indication, enabled, onClickLabel, role, onClick) - } - this.then(clicker) -} +) = this.combinedClickable( + interactionSource = null, + indication = indication, + enabled = enabled, + onLongClickLabel = onLongClickLabel, + onLongClick = onLongClick, + role = role, + onClick = {} +) fun Modifier.measured(block: (DpSize) -> Unit): Modifier = composed { val density = LocalDensity.current