Skip to content

Commit 39ee64f

Browse files
committed
fix: stable pairing code cells and numpad focus
1 parent 7436803 commit 39ee64f

2 files changed

Lines changed: 28 additions & 10 deletions

File tree

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import androidx.compose.ui.unit.Dp
3838
import androidx.compose.ui.unit.dp
3939
import androidx.compose.ui.unit.sp
4040
import androidx.lifecycle.compose.collectAsStateWithLifecycle
41+
import kotlinx.coroutines.delay
4142
import to.bitkit.R
4243
import to.bitkit.models.BitcoinDisplayUnit
4344
import to.bitkit.models.PrimaryDisplay
@@ -50,11 +51,14 @@ import to.bitkit.ui.theme.Colors
5051
import to.bitkit.viewmodels.AmountInputViewModel
5152
import to.bitkit.viewmodels.previewAmountInputViewModel
5253
import kotlin.time.Duration
54+
import kotlin.time.Duration.Companion.milliseconds
5355

5456
const val KEY_DELETE = "delete"
5557
const val KEY_000 = "000"
5658
const val KEY_DECIMAL = "."
5759
private val defaultHeight = 300.dp
60+
private const val FOCUS_RETRY_COUNT = 10
61+
private val FOCUS_RETRY_DELAY = 50.milliseconds
5862
private val idealButtonHeight = 75.dp
5963
private val minButtonHeight = 50.dp
6064
private const val ROWS = 4
@@ -78,7 +82,14 @@ fun NumberPad(
7882
onDeleteLongPress: (() -> Unit)? = null,
7983
) {
8084
val focusRequester = remember { FocusRequester() }
81-
LaunchedEffect(Unit) { focusRequester.requestFocus() }
85+
LaunchedEffect(Unit) {
86+
// Composing mid sheet/nav transition can drop the initial request, leaving
87+
// hardware keyboard input dead; retry briefly until the focus node takes it.
88+
repeat(FOCUS_RETRY_COUNT) {
89+
if (runCatching { focusRequester.requestFocus() }.isSuccess) return@LaunchedEffect
90+
delay(FOCUS_RETRY_DELAY)
91+
}
92+
}
8293
val safeAreaModifier = if (includeNavigationBarsPadding) {
8394
modifier.navigationBarsPadding()
8495
} else {

app/src/main/java/to/bitkit/ui/sheets/HardwareSheet.kt

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package to.bitkit.ui.sheets
22

33
import androidx.compose.foundation.Image
44
import androidx.compose.foundation.layout.Arrangement
5+
import androidx.compose.foundation.layout.Box
56
import androidx.compose.foundation.layout.BoxWithConstraints
67
import androidx.compose.foundation.layout.Column
78
import androidx.compose.foundation.layout.Row
@@ -11,6 +12,7 @@ import androidx.compose.foundation.layout.navigationBarsPadding
1112
import androidx.compose.foundation.layout.offset
1213
import androidx.compose.foundation.layout.padding
1314
import androidx.compose.foundation.layout.size
15+
import androidx.compose.foundation.layout.width
1416
import androidx.compose.runtime.Composable
1517
import androidx.compose.runtime.DisposableEffect
1618
import androidx.compose.runtime.getValue
@@ -22,9 +24,6 @@ import androidx.compose.ui.Modifier
2224
import androidx.compose.ui.platform.testTag
2325
import androidx.compose.ui.res.painterResource
2426
import androidx.compose.ui.res.stringResource
25-
import androidx.compose.ui.text.SpanStyle
26-
import androidx.compose.ui.text.buildAnnotatedString
27-
import androidx.compose.ui.text.withStyle
2827
import androidx.compose.ui.tooling.preview.Preview
2928
import androidx.compose.ui.unit.dp
3029
import androidx.navigation.compose.NavHost
@@ -173,14 +172,21 @@ private fun HardwarePairing(
173172
) {
174173
BodyM(stringResource(R.string.hardware__pairing_text), color = Colors.White64)
175174
FillHeight()
176-
Display(
177-
buildAnnotatedString {
178-
append(code)
179-
withStyle(SpanStyle(color = Colors.White32)) {
180-
repeat(PAIRING_CODE_LENGTH - code.length) { append('') }
175+
// Fixed-width cells so digits replace dots without the row shifting.
176+
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
177+
repeat(PAIRING_CODE_LENGTH) { index ->
178+
val digit = code.getOrNull(index)?.toString()
179+
Box(
180+
contentAlignment = Alignment.Center,
181+
modifier = Modifier.width(PAIRING_CELL_WIDTH)
182+
) {
183+
Display(
184+
text = digit ?: "",
185+
color = if (digit != null) Colors.White else Colors.White32,
186+
)
181187
}
182188
}
183-
)
189+
}
184190
FillHeight()
185191
}
186192
NumberPad(
@@ -210,6 +216,7 @@ sealed interface HardwareRoute {
210216
}
211217

212218
private const val PAIRING_CODE_LENGTH = 6
219+
private val PAIRING_CELL_WIDTH = 32.dp
213220

214221
// Proportions taken from the 375dp-wide Figma frame: 256dp visuals bleeding
215222
// 84dp off the left edge and 53dp off the right, staggered by 12dp vertically.

0 commit comments

Comments
 (0)