diff options
| author | David Göransson <david.goransson@mullvad.net> | 2026-04-22 11:20:35 +0200 |
|---|---|---|
| committer | David Göransson <david.goransson@mullvad.net> | 2026-04-22 11:20:35 +0200 |
| commit | 042b04909bcf0e20c623bf0208a0a8153331a096 (patch) | |
| tree | e08d7b87878cd2dd22350a3d2e17d1bb485e1493 | |
| parent | bfe0141a0a2544a0f692d6729ea86407b2c233d1 (diff) | |
| download | mullvadvpn-update-login-view-to-new-design-droid-2560.tar.xz mullvadvpn-update-login-view-to-new-design-droid-2560.zip | |
| -rw-r--r-- | android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginScreen.kt | 101 |
1 files changed, 54 insertions, 47 deletions
diff --git a/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginScreen.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginScreen.kt index 5b970abdba..0cc87e56e9 100644 --- a/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginScreen.kt +++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginScreen.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -21,6 +20,7 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.input.TextFieldLineLimits +import androidx.compose.foundation.text.input.TextFieldState import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd import androidx.compose.foundation.verticalScroll @@ -134,7 +134,7 @@ private fun PreviewLoginScreen( } private const val TOP_SPACER_WEIGHT = 1f -private const val BOTTOM_SPACER_WEIGHT = 3f +private const val BOTTOM_SPACER_WEIGHT = 1f @Composable fun Login( @@ -267,17 +267,19 @@ private fun LoginScreen( .padding(bottom = Dimens.smallPadding), ) - LoginInput( - state, - onLoginClick, - onAccountNumberChange, - onDeleteHistoryClick, - onShowApiUnreachableDialog, - ) + Column { + LoginInput( + state, + onLoginClick, + onAccountNumberChange, + onDeleteHistoryClick, + onShowApiUnreachableDialog, + ) + } AnimatedVisibility(state.loginState is LoginState.Idle) { Column { - Spacer(modifier = Modifier.size(Dimens.mediumSpacer)) + Spacer(modifier = Modifier.height(Dimens.mediumSpacer)) VariantButton( isEnabled = state.loginButtonEnabled, onClick = { onLoginClick(state.accountNumberInput) }, @@ -286,6 +288,7 @@ private fun LoginScreen( ) Spacer(modifier = Modifier.height(Dimens.largePadding)) OrDivier() + Spacer(modifier = Modifier.height(Dimens.mediumSpacer)) PrimaryTextButton( modifier = Modifier.align(Alignment.CenterHorizontally), text = stringResource(id = R.string.create_new_account), @@ -301,10 +304,7 @@ private fun LoginScreen( @Composable fun OrDivier() { - Row( - modifier = Modifier.defaultMinSize(minHeight = Dimens.orDivierMinHeight), - verticalAlignment = Alignment.CenterVertically, - ) { + Row(verticalAlignment = Alignment.CenterVertically) { HorizontalDivider( modifier = Modifier.weight(1f), color = MaterialTheme.colorScheme.onBackground, @@ -358,7 +358,11 @@ private fun ColumnScope.LoginInput( it } }, - state = accountState, + state = + if (state.loginState is LoginState.Loading.CreatingAccount) TextFieldState("") + else { + accountState + }, labelPosition = TextFieldLabelPosition.Above(), label = { Text( @@ -368,22 +372,31 @@ private fun ColumnScope.LoginInput( ) }, lineLimits = TextFieldLineLimits.SingleLine, - trailingIcon = { - IconButton( - modifier = Modifier.testTag(LOGIN_REVEAL_INPUT_BUTTON_TEST_TAG), - onClick = { showPassword = !showPassword }, - ) { - Icon( - imageVector = - if (showPassword) Icons.Outlined.VisibilityOff - else Icons.Outlined.Visibility, - contentDescription = - if (showPassword) stringResource(id = R.string.hide_account_number) - else stringResource(id = R.string.show_account_number), - ) + trailingIcon = + if (state.loginState is LoginState.Idle) { + { + IconButton( + modifier = Modifier.testTag(LOGIN_REVEAL_INPUT_BUTTON_TEST_TAG), + onClick = { showPassword = !showPassword }, + ) { + Icon( + imageVector = + if (showPassword) Icons.Outlined.VisibilityOff + else Icons.Outlined.Visibility, + contentDescription = + if (showPassword) stringResource(id = R.string.hide_account_number) + else stringResource(id = R.string.show_account_number), + ) + } + } + } else null, + placeholder = { + if (state.loginState == LoginState.Loading.CreatingAccount) { + Text("Generating...") + } else { + Text(stringResource(R.string.login_description)) } }, - placeholder = { Text(stringResource(R.string.login_description)) }, onKeyboardAction = { onLoginClick(state.accountNumberInput) }, keyboardOptions = KeyboardOptions( @@ -421,11 +434,13 @@ private fun ColumnScope.LoginInput( } } - SupportingText( - Modifier.padding(bottom = Dimens.smallPadding), - onShowApiUnreachableDialog = onShowApiUnreachableDialog, - state = state, - ) + val text = state.loginState.supportingText(onShowApiUnreachableDialog) + AnimatedVisibility(text != null) { + SupportingText( + Modifier.padding(top = Dimens.tinyPadding), + text = text ?: AnnotatedString(""), + ) + } } @Composable @@ -468,21 +483,12 @@ private fun LoginState.title(): String = ) @Composable -private fun SupportingText( - modifier: Modifier = Modifier, - state: LoginUiState, - onShowApiUnreachableDialog: (LoginUiStateError) -> Unit, -) { +private fun SupportingText(modifier: Modifier = Modifier, text: AnnotatedString) { Text( modifier = modifier, - text = state.loginState.supportingText(onShowApiUnreachableDialog) ?: AnnotatedString(""), + text = text, style = MaterialTheme.typography.labelLarge, - color = - if (state.loginState.isError()) { - MaterialTheme.colorScheme.error - } else { - MaterialTheme.colorScheme.onPrimary - }, + color = MaterialTheme.colorScheme.error, ) } @@ -621,6 +627,7 @@ private fun AccountDropDownItem( private fun LoginUiStateError.toLoginAction(): LoginAction = when (this) { is LoginUiStateError.LoginError.ApiUnreachable -> LoginAction.LOGIN -// is LoginUiStateError.CreateAccountError.ApiUnreachable -> LoginAction.CREATE_ACCOUNT + // is LoginUiStateError.CreateAccountError.ApiUnreachable -> + // LoginAction.CREATE_ACCOUNT else -> throw IllegalArgumentException("Not an API unreachable error") } |
