Skip to content

Commit 3987fe4

Browse files
authored
Merge pull request #133 from code-payments/fix/access-key-lsyout-cross-device-sizes
fix(accesskey): improve layout rendering across all device sizes
2 parents d20e93c + fe5218a commit 3987fe4

12 files changed

Lines changed: 84 additions & 60 deletions

File tree

app/src/main/java/com/getcode/CodeApp.kt

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import androidx.compose.animation.fadeIn
44
import androidx.compose.animation.fadeOut
55
import androidx.compose.animation.togetherWith
66
import androidx.compose.foundation.layout.Box
7+
import androidx.compose.foundation.layout.PaddingValues
78
import androidx.compose.foundation.layout.fillMaxSize
89
import androidx.compose.foundation.layout.padding
910
import androidx.compose.material.ExperimentalMaterialApi
@@ -16,6 +17,7 @@ import androidx.compose.runtime.remember
1617
import androidx.compose.runtime.setValue
1718
import androidx.compose.ui.Modifier
1819
import androidx.compose.ui.platform.LocalContext
20+
import androidx.compose.ui.unit.dp
1921
import cafe.adriel.voyager.core.stack.StackEvent
2022
import cafe.adriel.voyager.navigator.CurrentScreen
2123
import cafe.adriel.voyager.navigator.Navigator
@@ -33,6 +35,7 @@ import com.getcode.theme.CodeTheme
3335
import com.getcode.theme.LocalCodeColors
3436
import com.getcode.util.getActivity
3537
import com.getcode.util.getActivityScopedViewModel
38+
import com.getcode.util.measured
3639
import com.getcode.view.components.AuthCheck
3740
import com.getcode.view.components.BottomBarContainer
3841
import com.getcode.view.components.CodeScaffold
@@ -63,29 +66,38 @@ fun CodeApp() {
6366
codeNavigator.screensNavigator = navigator
6467
}
6568

69+
var topBarHeight by remember {
70+
mutableStateOf(0.dp)
71+
}
6672
val (isVisibleTopBar, isVisibleBackButton) = appState.isVisibleTopBar
6773
if (isVisibleTopBar && appState.currentTitle.isNotBlank()) {
6874
TitleBar(
75+
modifier = Modifier.measured { topBarHeight = it.height },
6976
title = appState.currentTitle,
7077
backButton = isVisibleBackButton,
7178
onBackIconClicked = appState::upPress
7279
)
80+
} else {
81+
topBarHeight = 0.dp
7382
}
7483

75-
Box(
76-
modifier = Modifier
77-
.padding(innerPaddingModifier)
78-
) {
79-
when (navigator.lastEvent) {
80-
StackEvent.Push,
81-
StackEvent.Pop -> {
82-
when (navigator.lastItem) {
83-
is LoginScreen, is MainRoot -> CrossfadeTransition(navigator = navigator)
84-
else -> SlideTransition(navigator = navigator)
84+
CompositionLocalProvider(value = LocalTopBarPadding provides PaddingValues(top = topBarHeight)) {
85+
Box(
86+
modifier = Modifier
87+
.padding(innerPaddingModifier)
88+
) {
89+
when (navigator.lastEvent) {
90+
StackEvent.Push,
91+
StackEvent.Pop -> {
92+
when (navigator.lastItem) {
93+
is LoginScreen, is MainRoot -> CrossfadeTransition(navigator = navigator)
94+
else -> SlideTransition(navigator = navigator)
95+
}
8596
}
97+
98+
StackEvent.Idle,
99+
StackEvent.Replace -> CurrentScreen()
86100
}
87-
StackEvent.Idle,
88-
StackEvent.Replace -> CurrentScreen()
89101
}
90102
}
91103

app/src/main/java/com/getcode/CodeAppState.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,11 @@ import com.getcode.manager.TopBarManager
1212
import com.getcode.navigation.core.CodeNavigator
1313
import com.getcode.navigation.core.LocalCodeNavigator
1414
import com.getcode.navigation.screens.AccessKeyLoginScreen
15-
import com.getcode.navigation.screens.AccessKeyScreen
16-
import com.getcode.navigation.screens.LoginPhoneConfirmationScreen
1715
import com.getcode.navigation.screens.LoginPhoneVerificationScreen
1816
import com.getcode.navigation.screens.LoginScreen
1917
import com.getcode.navigation.screens.NamedScreen
20-
import com.getcode.navigation.screens.PermissionRequestScreen
2118
import kotlinx.coroutines.CoroutineScope
2219
import kotlinx.coroutines.launch
23-
import timber.log.Timber
2420

2521
/**
2622
* Remembers and creates an instance of [CodeAppState]

app/src/main/java/com/getcode/Locals.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.getcode
22

3+
import androidx.compose.foundation.layout.PaddingValues
34
import androidx.compose.runtime.ProvidableCompositionLocal
45
import androidx.compose.runtime.staticCompositionLocalOf
56
import com.getcode.analytics.AnalyticsService
@@ -15,3 +16,4 @@ val LocalNetworkObserver: ProvidableCompositionLocal<NetworkConnectivityListener
1516
val LocalPhoneFormatter: ProvidableCompositionLocal<PhoneUtils?> = staticCompositionLocalOf { null }
1617
val LocalCurrencyUtils: ProvidableCompositionLocal<CurrencyUtils?> = staticCompositionLocalOf { null }
1718
val LocalDeeplinks: ProvidableCompositionLocal<DeeplinkHandler?> = staticCompositionLocalOf { null }
19+
val LocalTopBarPadding: ProvidableCompositionLocal<PaddingValues> = staticCompositionLocalOf { PaddingValues() }

app/src/main/java/com/getcode/navigation/screens/Modals.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,8 @@ import cafe.adriel.voyager.core.screen.uniqueScreenKey
2525
import com.getcode.navigation.core.CodeNavigator
2626
import com.getcode.navigation.core.LocalCodeNavigator
2727
import com.getcode.theme.CodeTheme
28-
import com.getcode.theme.sheetHeight
29-
import com.getcode.util.keyboardAsState
3028
import com.getcode.view.components.SheetTitle
29+
import com.getcode.view.components.keyboardAsState
3130
import kotlinx.coroutines.delay
3231
import kotlinx.coroutines.launch
3332

@@ -79,7 +78,7 @@ internal fun Screen.ModalContainer(
7978
Column(
8079
modifier = Modifier
8180
.fillMaxWidth()
82-
.fillMaxHeight(sheetHeight)
81+
.fillMaxHeight(CodeTheme.dimens.modalHeightRatio)
8382
) {
8483
val lastItem by remember(navigator.lastModalItem) {
8584
derivedStateOf { navigator.lastModalItem }
@@ -93,13 +92,16 @@ internal fun Screen.ModalContainer(
9392
derivedStateOf { closeButton(lastItem) }
9493
}
9594

95+
val keyboardVisible by keyboardAsState()
9696
val keyboardController = LocalSoftwareKeyboardController.current
9797
val composeScope = rememberCoroutineScope()
9898

9999
val hideSheet = {
100100
composeScope.launch {
101-
keyboardController?.hide()
102-
delay(500)
101+
if (keyboardVisible) {
102+
keyboardController?.hide()
103+
delay(500)
104+
}
103105
navigator.hide()
104106
}
105107
}

app/src/main/java/com/getcode/navigation/screens/PhoneCountrySelection.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ private fun PhoneCountrySelection(
5757
modifier = Modifier
5858
.align(Alignment.CenterVertically)
5959
.padding(start = CodeTheme.dimens.inset)
60-
.size(CodeTheme.dimens.staticGrid.x5)
60+
.size(CodeTheme.dimens.grid.x5)
6161
.clip(CodeTheme.shapes.large),
6262
painter = painterResource(id = resId),
6363
contentDescription = ""

app/src/main/java/com/getcode/theme/Dimens.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import androidx.compose.ui.unit.dp
1010
import com.getcode.BuildConfig
1111

1212
val topBarHeight = 56.dp
13-
const val sheetHeight = 0.9f
1413

1514
internal val LocalDimens = staticCompositionLocalOf<Dimensions> {
1615
error("No Dimensions provided")
@@ -166,6 +165,7 @@ class Dimensions(
166165
val none: Dp = 0.dp,
167166
val border: Dp = 1.dp,
168167
val thickBorder: Dp = 2.dp,
168+
val modalHeightRatio: Float = 0.94f,
169169
val inset: Dp,
170170
val screenWidth: Dp = Dp.Unspecified,
171171
val screenHeight: Dp = Dp.Unspecified,

app/src/main/java/com/getcode/theme/Shape.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ val Shapes.xxl: CornerBasedShape
2424
@Composable get() = RoundedCornerShape(25.dp)
2525

2626
@Composable
27-
fun Shapes.receipt(step: Dp = CodeTheme.dimens.staticGrid.x2) = TriangleCutShape(step)
27+
fun Shapes.receipt(step: Dp = CodeTheme.dimens.grid.x2) = TriangleCutShape(step)
2828

app/src/main/java/com/getcode/view/components/CodeKeyPad.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ fun CodeKeyPad(
5959
modifier = Modifier
6060
.widthIn(min = 100.dp)
6161
.then(modifier),
62-
horizontalArrangement = Arrangement.spacedBy(CodeTheme.dimens.staticGrid.x1),
62+
horizontalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x1),
6363
verticalAlignment = Alignment.Bottom
6464
) {
6565
for (column in 1..3) {
6666
Column(
6767
modifier = Modifier.weight(1f),
68-
verticalArrangement = Arrangement.spacedBy(CodeTheme.dimens.staticGrid.x1)
68+
verticalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x1)
6969
) {
7070
for (row in 1..4) {
7171
val number = (row - 1) * 3 + column

app/src/main/java/com/getcode/view/components/OtpBox.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ fun OtpBox(
2626
) {
2727

2828
val height = when (CodeTheme.dimens.heightWindowSizeClass) {
29-
WindowSizeClass.COMPACT -> CodeTheme.dimens.staticGrid.x9
30-
else -> CodeTheme.dimens.staticGrid.x11
29+
WindowSizeClass.COMPACT -> CodeTheme.dimens.grid.x9
30+
else -> CodeTheme.dimens.grid.x11
3131
}
3232

3333
Box(
3434
modifier = modifier
3535
.padding(CodeTheme.dimens.grid.x1)
3636
.height(height)
37-
.width(CodeTheme.dimens.staticGrid.x7)
37+
.width(CodeTheme.dimens.grid.x7)
3838
.clip(CodeTheme.shapes.small)
3939
.rememberedClickable(onClick = onClick)
4040
.border(

app/src/main/java/com/getcode/view/login/AccessKey.kt

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.Arrangement
1414
import androidx.compose.foundation.layout.Box
1515
import androidx.compose.foundation.layout.Column
1616
import androidx.compose.foundation.layout.WindowInsets
17+
import androidx.compose.foundation.layout.aspectRatio
1718
import androidx.compose.foundation.layout.fillMaxHeight
1819
import androidx.compose.foundation.layout.fillMaxSize
1920
import androidx.compose.foundation.layout.fillMaxWidth
@@ -47,6 +48,7 @@ import androidx.compose.ui.zIndex
4748
import androidx.constraintlayout.compose.ConstraintLayout
4849
import androidx.constraintlayout.compose.Dimension
4950
import androidx.hilt.navigation.compose.hiltViewModel
51+
import com.getcode.LocalTopBarPadding
5052
import com.getcode.R
5153
import com.getcode.manager.BottomBarManager
5254
import com.getcode.manager.TopBarManager
@@ -57,6 +59,7 @@ import com.getcode.theme.CodeTheme
5759
import com.getcode.theme.White
5860
import com.getcode.util.IntentUtils
5961
import com.getcode.util.addIf
62+
import com.getcode.util.debugBounds
6063
import com.getcode.util.measured
6164
import com.getcode.util.swallowClicks
6265
import com.getcode.view.components.AccessKeySelectionContainer
@@ -135,10 +138,6 @@ fun AccessKey(
135138
words = dataState.words.joinToString(" ")
136139
)
137140

138-
var textHeight by remember {
139-
mutableStateOf(0.dp)
140-
}
141-
142141
AccessKeySelectionContainer(
143142
modifier = Modifier
144143
.fillMaxSize()
@@ -154,7 +153,8 @@ fun AccessKey(
154153
modifier = Modifier
155154
.fillMaxSize()
156155
.padding(horizontal = CodeTheme.dimens.inset)
157-
.padding(vertical = CodeTheme.dimens.grid.x4),
156+
.padding(vertical = CodeTheme.dimens.grid.x4)
157+
.measured { buttonHeight = it.height },
158158
) {
159159
Column(modifier = Modifier
160160
.align(Alignment.BottomCenter)
@@ -199,25 +199,36 @@ fun AccessKey(
199199
modifier = Modifier
200200
.align(Alignment.TopCenter)
201201
.fillMaxHeight()
202-
.padding(bottom = buttonHeight)
203-
,
204-
verticalArrangement = Arrangement.Center,
202+
.padding(LocalTopBarPadding.current)
203+
.padding(bottom = buttonHeight + CodeTheme.dimens.grid.x4),
205204
horizontalAlignment = Alignment.CenterHorizontally
206205
) {
207-
AnimatedVisibility(
208-
visibleState = isAccessKeyVisible,
209-
enter = fadeIn(animationSpec = tween(300, 0)),
210-
exit = fadeOut(animationSpec = tween(300, 0))
206+
Column(
207+
modifier = Modifier
208+
// highly specific aspect ratio from iOS :)
209+
.aspectRatio(0.607f, matchHeightConstraintsFirst = true)
210+
.fillMaxWidth()
211+
.weight(1f),
212+
verticalArrangement = Arrangement.Center,
213+
horizontalAlignment = Alignment.CenterHorizontally
211214
) {
212-
dataState.accessKeyCroppedBitmap?.let { bitmap ->
213-
Image(
214-
modifier = Modifier
215-
.fillMaxWidth()
216-
.weight(1f)
217-
.scale(selectionState.scale.value),
218-
bitmap = bitmap.asImageBitmap(),
219-
contentDescription = dataState.wordsFormatted,
220-
)
215+
AnimatedVisibility(
216+
visibleState = isAccessKeyVisible,
217+
enter = fadeIn(animationSpec = tween(300, 0)),
218+
exit = fadeOut(animationSpec = tween(300, 0))
219+
) {
220+
dataState.accessKeyCroppedBitmap?.let { bitmap ->
221+
Image(
222+
modifier = Modifier
223+
.aspectRatio(0.607f, matchHeightConstraintsFirst = true)
224+
.fillMaxWidth()
225+
.weight(1f)
226+
.scale(selectionState.scale.value),
227+
bitmap = bitmap.asImageBitmap(),
228+
contentScale = ContentScale.Crop,
229+
contentDescription = dataState.wordsFormatted,
230+
)
231+
}
221232
}
222233
}
223234

0 commit comments

Comments
 (0)