Skip to content

Commit 972bc6f

Browse files
authored
Merge pull request #832 from synonymdev/fix/accidental-db-clicks
fix: debounce clicks and deduplicate scans
2 parents b6ea4c2 + 6fe4f4a commit 972bc6f

44 files changed

Lines changed: 416 additions & 380 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ suspend fun getData(): Result<Data> = withContext(Dispatchers.IO) {
194194
- ALWAYS use `remember` for expensive Compose computations
195195
- ALWAYS add modifiers to the last place in the argument list when calling composable functions
196196
- NEVER add parameters with default values BEFORE the `modifier` parameter in composable functions - modifier must be the FIRST optional parameter
197+
- ALWAYS use `navController.navigateTo(route)` for simple navigation; NEVER use raw `navController.navigate(route)``navigateTo` prevents duplicate destinations
197198
- ALWAYS prefer `VerticalSpacer`, `HorizontalSpacer`, `FillHeight` and `FillWidth` over `Spacer` when applicable
198199
- PREFER declaring small dependant classes, constants, interfaces or top-level functions in the same file with the core class where these are used
199200
- ALWAYS create data classes for state AFTER viewModel class in same file

app/src/main/java/to/bitkit/ui/ContentView.kt

Lines changed: 101 additions & 154 deletions
Large diffs are not rendered by default.

app/src/main/java/to/bitkit/ui/MainActivity.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,17 +237,17 @@ private fun OnboardingNav(
237237
composable<StartupRoutes.Terms> {
238238
TermsOfUseScreen(
239239
onNavigateToIntro = {
240-
startupNavController.navigate(StartupRoutes.Intro)
240+
startupNavController.navigateTo(StartupRoutes.Intro)
241241
}
242242
)
243243
}
244244
composableWithDefaultTransitions<StartupRoutes.Intro> {
245245
IntroScreen(
246246
onStartClick = {
247-
startupNavController.navigate(StartupRoutes.Slides())
247+
startupNavController.navigateTo(StartupRoutes.Slides())
248248
},
249249
onSkipClick = {
250-
startupNavController.navigate(StartupRoutes.Slides(StartupRoutes.LAST_SLIDE_INDEX))
250+
startupNavController.navigateTo(StartupRoutes.Slides(StartupRoutes.LAST_SLIDE_INDEX))
251251
},
252252
)
253253
}
@@ -257,7 +257,7 @@ private fun OnboardingNav(
257257
OnboardingSlidesScreen(
258258
currentTab = route.tab,
259259
isGeoBlocked = isGeoBlocked,
260-
onAdvancedSetupClick = { startupNavController.navigate(StartupRoutes.Advanced) },
260+
onAdvancedSetupClick = { startupNavController.navigateTo(StartupRoutes.Advanced) },
261261
onCreateClick = {
262262
scope.launch {
263263
runCatching {
@@ -270,7 +270,7 @@ private fun OnboardingNav(
270270
}
271271
},
272272
onRestoreClick = {
273-
startupNavController.navigate(
273+
startupNavController.navigateTo(
274274
StartupRoutes.WarningMultipleDevices
275275
)
276276
},
@@ -282,7 +282,7 @@ private fun OnboardingNav(
282282
startupNavController.popBackStack()
283283
},
284284
onConfirmClick = {
285-
startupNavController.navigate(StartupRoutes.Restore)
285+
startupNavController.navigateTo(StartupRoutes.Restore)
286286
}
287287
)
288288
}

app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import to.bitkit.ui.scaffold.AppTopBar
6969
import to.bitkit.ui.scaffold.DrawerNavIcon
7070
import to.bitkit.ui.scaffold.ScreenColumn
7171
import to.bitkit.ui.shared.modifiers.clickableAlpha
72+
import to.bitkit.ui.shared.modifiers.rememberDebouncedClick
7273
import to.bitkit.ui.theme.AppThemeSurface
7374
import to.bitkit.ui.theme.Colors
7475
import to.bitkit.ui.theme.Shapes
@@ -438,7 +439,7 @@ private fun PeerCard(
438439
maxLines = 1,
439440
)
440441
}
441-
IconButton(onClick = { onDisconnectPeer(peer.peerDetails) }) {
442+
IconButton(onClick = rememberDebouncedClick { onDisconnectPeer(peer.peerDetails) }) {
442443
Icon(
443444
imageVector = Icons.Default.RemoveCircleOutline,
444445
contentDescription = stringResource(R.string.common__close),

app/src/main/java/to/bitkit/ui/components/AuthCheckScreen.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import androidx.compose.runtime.Composable
44
import androidx.compose.runtime.getValue
55
import androidx.lifecycle.compose.collectAsStateWithLifecycle
66
import androidx.navigation.NavController
7-
import androidx.navigation.navOptions
87
import to.bitkit.ui.Routes
98
import to.bitkit.ui.appViewModel
9+
import to.bitkit.ui.navigateTo
1010
import to.bitkit.ui.settingsViewModel
1111

1212
@Composable
@@ -44,10 +44,9 @@ fun AuthCheckScreen(
4444
}
4545

4646
AuthCheckAction.NAV_TO_RESET -> {
47-
navController.navigate(
48-
route = Routes.ResetAndRestoreSettings,
49-
navOptions = navOptions { popUpTo(Routes.BackupSettings) }
50-
)
47+
navController.navigateTo(Routes.ResetAndRestoreSettings) {
48+
popUpTo(Routes.BackupSettings)
49+
}
5150
}
5251
}
5352
},

app/src/main/java/to/bitkit/ui/components/BalanceHeaderView.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import to.bitkit.ui.shared.modifiers.swipeToHide
3535
import to.bitkit.ui.theme.AppThemeSurface
3636
import to.bitkit.ui.theme.Colors
3737

38+
@Suppress("CyclomaticComplexMethod")
3839
@Composable
3940
fun BalanceHeaderView(
4041
sats: Long,

app/src/main/java/to/bitkit/ui/components/Button.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import androidx.compose.ui.tooling.preview.Preview
3333
import androidx.compose.ui.unit.Dp
3434
import androidx.compose.ui.unit.dp
3535
import to.bitkit.ui.shared.modifiers.alphaFeedback
36+
import to.bitkit.ui.shared.modifiers.rememberDebouncedClick
3637
import to.bitkit.ui.shared.util.primaryButtonStyle
3738
import to.bitkit.ui.theme.AppButtonDefaults
3839
import to.bitkit.ui.theme.AppThemeSurface
@@ -70,7 +71,7 @@ fun PrimaryButton(
7071
val buttonShape = MaterialTheme.shapes.large
7172

7273
Button(
73-
onClick = onClick,
74+
onClick = rememberDebouncedClick(onClick = onClick),
7475
enabled = enabled && !isLoading,
7576
colors = AppButtonDefaults.primaryColors.copy(
7677
containerColor = Color.Transparent,
@@ -139,7 +140,7 @@ fun SecondaryButton(
139140
val contentPadding = PaddingValues(horizontal = size.horizontalPadding.takeIf { text != null } ?: 0.dp)
140141
val border = BorderStroke(2.dp, if (enabled) Colors.Gray4 else Color.Transparent)
141142
OutlinedButton(
142-
onClick = onClick,
143+
onClick = rememberDebouncedClick(onClick = onClick),
143144
enabled = enabled && !isLoading,
144145
colors = AppButtonDefaults.secondaryColors,
145146
contentPadding = contentPadding,
@@ -197,7 +198,7 @@ fun TertiaryButton(
197198
) {
198199
val contentPadding = PaddingValues(horizontal = size.horizontalPadding.takeIf { text != null } ?: 0.dp)
199200
TextButton(
200-
onClick = onClick,
201+
onClick = rememberDebouncedClick(onClick = onClick),
201202
enabled = enabled && !isLoading,
202203
colors = AppButtonDefaults.tertiaryColors,
203204
contentPadding = contentPadding,

app/src/main/java/to/bitkit/ui/components/DrawerMenu.kt

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import androidx.compose.animation.AnimatedVisibility
55
import androidx.compose.animation.slideInHorizontally
66
import androidx.compose.animation.slideOutHorizontally
77
import androidx.compose.foundation.background
8-
import androidx.compose.foundation.clickable
9-
import androidx.compose.foundation.interaction.MutableInteractionSource
108
import androidx.compose.foundation.layout.Arrangement
119
import androidx.compose.foundation.layout.Box
1210
import androidx.compose.foundation.layout.Column
@@ -25,7 +23,6 @@ import androidx.compose.material3.Icon
2523
import androidx.compose.material3.Text
2624
import androidx.compose.material3.rememberDrawerState
2725
import androidx.compose.runtime.Composable
28-
import androidx.compose.runtime.remember
2926
import androidx.compose.runtime.rememberCoroutineScope
3027
import androidx.compose.ui.Alignment
3128
import androidx.compose.ui.Modifier
@@ -45,14 +42,20 @@ import androidx.navigation.compose.rememberNavController
4542
import kotlinx.coroutines.launch
4643
import to.bitkit.R
4744
import to.bitkit.ui.Routes
48-
import to.bitkit.ui.navigateIfNotCurrent
45+
import to.bitkit.ui.navigateTo
4946
import to.bitkit.ui.navigateToHome
5047
import to.bitkit.ui.shared.modifiers.clickableAlpha
5148
import to.bitkit.ui.shared.util.blockPointerInputPassthrough
5249
import to.bitkit.ui.theme.AppThemeSurface
5350
import to.bitkit.ui.theme.Colors
5451
import to.bitkit.ui.theme.InterFontFamily
5552

53+
private inline fun <reified T : Any> NavController.navigateIfNotCurrent(route: T) {
54+
if (currentBackStackEntry?.destination?.hasRoute<T>() != true) {
55+
navigateTo(route)
56+
}
57+
}
58+
5659
private const val Z_INDEX_SCRIM = 10f
5760
private const val Z_INDEX_MENU = 11f
5861
private val bgScrim = Colors.Black50
@@ -243,11 +246,7 @@ private fun Scrim(
243246
modifier = Modifier
244247
.fillMaxSize()
245248
.background(bgScrim)
246-
.clickable(
247-
interactionSource = remember { MutableInteractionSource() },
248-
indication = null,
249-
onClick = onClick,
250-
)
249+
.clickableAlpha(pressedAlpha = 1f, onClick = onClick)
251250
)
252251
}
253252
}
@@ -261,13 +260,7 @@ private fun DrawerItem(
261260
) {
262261
Column(
263262
modifier = modifier
264-
.then(
265-
if (onClick != null) {
266-
Modifier.clickable { onClick() }
267-
} else {
268-
Modifier
269-
}
270-
)
263+
.clickableAlpha(onClick = onClick)
271264
.padding(horizontal = 16.dp)
272265
) {
273266
VerticalSpacer(16.dp)

app/src/main/java/to/bitkit/ui/components/EmptyWalletView.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import androidx.compose.ui.text.AnnotatedString
2727
import androidx.compose.ui.tooling.preview.Preview
2828
import androidx.compose.ui.unit.dp
2929
import to.bitkit.R
30+
import to.bitkit.ui.shared.modifiers.rememberDebouncedClick
3031
import to.bitkit.ui.theme.AppThemeSurface
3132
import to.bitkit.ui.theme.Colors
3233
import to.bitkit.ui.utils.withAccent
@@ -66,9 +67,7 @@ fun EmptyStateView(
6667
}
6768
if (onClose != null) {
6869
IconButton(
69-
onClick = {
70-
onClose()
71-
},
70+
onClick = rememberDebouncedClick(onClick = onClose),
7271
modifier = Modifier
7372
.size(40.dp)
7473
.align(Alignment.TopEnd)

app/src/main/java/to/bitkit/ui/components/Money.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ fun MoneyCaptionB(
109109
}
110110
}
111111

112+
@Suppress("CyclomaticComplexMethod")
112113
@Composable
113114
fun rememberMoneyText(
114115
sats: Long,

0 commit comments

Comments
 (0)