Skip to content

Commit

Permalink
fix: update keyboard visibility and imeAction (#350)
Browse files Browse the repository at this point in the history
* fix: update keyboard visibility and imeAction

- Hide keyboard on logistration screens
- update imeAction for long InputEditFields

-LEARNER-10032

* fix: Added error Text for editable fields on SignIn Screen

- Add error text in case of empty fields on sign in Screen

fix: LEARNER-10032

* fix: Address PR comments
  • Loading branch information
omerhabib26 authored Jul 8, 2024
1 parent 948277a commit 5abf44d
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
Expand Down Expand Up @@ -127,9 +128,9 @@ private fun RestorePasswordScreen(
) {
val scaffoldState = rememberScaffoldState()
val scrollState = rememberScrollState()
var email by rememberSaveable {
mutableStateOf("")
}
var email by rememberSaveable { mutableStateOf("") }
var isEmailError by rememberSaveable { mutableStateOf(false) }
val keyboardController = LocalSoftwareKeyboardController.current

Scaffold(
scaffoldState = scaffoldState,
Expand Down Expand Up @@ -269,12 +270,20 @@ private fun RestorePasswordScreen(
description = stringResource(id = authR.string.auth_example_email),
onValueChanged = {
email = it
isEmailError = false
},
imeAction = ImeAction.Done,
keyboardActions = {
it.clearFocus()
onRestoreButtonClick(email)
}
keyboardController?.hide()
if (email.isNotEmpty()) {
it.clearFocus()
onRestoreButtonClick(email)
} else {
isEmailError = email.isEmpty()
}
},
isError = isEmailError,
errorMessages = stringResource(id = authR.string.auth_error_empty_email)
)
Spacer(Modifier.height(50.dp))
if (uiState == RestorePasswordUIState.Loading) {
Expand All @@ -292,7 +301,12 @@ private fun RestorePasswordScreen(
modifier = buttonWidth.testTag("btn_reset_password"),
text = stringResource(id = authR.string.auth_reset_password),
onClick = {
onRestoreButtonClick(email)
keyboardController?.hide()
if (email.isNotEmpty()) {
onRestoreButtonClick(email)
} else {
isEmailError = email.isEmpty()
}
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
Expand Down Expand Up @@ -220,6 +221,9 @@ private fun AuthForm(
) {
var login by rememberSaveable { mutableStateOf("") }
var password by rememberSaveable { mutableStateOf("") }
val keyboardController = LocalSoftwareKeyboardController.current
var isEmailError by rememberSaveable { mutableStateOf(false) }
var isPasswordError by rememberSaveable { mutableStateOf(false) }

Column(horizontalAlignment = Alignment.CenterHorizontally) {
LoginTextField(
Expand All @@ -229,18 +233,30 @@ private fun AuthForm(
description = stringResource(id = R.string.auth_enter_email_username),
onValueChanged = {
login = it
})
isEmailError = false
},
isError = isEmailError,
errorMessages = stringResource(id = R.string.auth_error_empty_username_email)
)

Spacer(modifier = Modifier.height(18.dp))
PasswordTextField(
modifier = Modifier
.fillMaxWidth(),
onValueChanged = {
password = it
isPasswordError = false
},
onPressDone = {
onEvent(AuthEvent.SignIn(login = login, password = password))
}
keyboardController?.hide()
if (password.isNotEmpty()) {
onEvent(AuthEvent.SignIn(login = login, password = password))
} else {
isEmailError = login.isEmpty()
isPasswordError = password.isEmpty()
}
},
isError = isPasswordError,
)

Row(
Expand Down Expand Up @@ -282,7 +298,13 @@ private fun AuthForm(
textColor = MaterialTheme.appColors.primaryButtonText,
backgroundColor = MaterialTheme.appColors.secondaryButtonBackground,
onClick = {
onEvent(AuthEvent.SignIn(login = login, password = password))
keyboardController?.hide()
if (login.isNotEmpty() && password.isNotEmpty()) {
onEvent(AuthEvent.SignIn(login = login, password = password))
} else {
isEmailError = login.isEmpty()
isPasswordError = password.isEmpty()
}
}
)
}
Expand All @@ -294,6 +316,7 @@ private fun AuthForm(
isMicrosoftAuthEnabled = state.isMicrosoftAuthEnabled,
isSignIn = true,
) {
keyboardController?.hide()
onEvent(AuthEvent.SocialSignIn(it))
}
}
Expand All @@ -303,6 +326,7 @@ private fun AuthForm(
@Composable
private fun PasswordTextField(
modifier: Modifier = Modifier,
isError: Boolean,
onValueChanged: (String) -> Unit,
onPressDone: () -> Unit,
) {
Expand Down Expand Up @@ -361,9 +385,21 @@ private fun PasswordTextField(
focusManager.clearFocus()
onPressDone()
},
isError = isError,
textStyle = MaterialTheme.appTypography.bodyMedium,
singleLine = true
singleLine = true,
)
if (isError) {
Text(
modifier = Modifier
.testTag("txt_password_error")
.fillMaxWidth()
.padding(top = 4.dp),
text = stringResource(id = R.string.auth_error_empty_password),
style = MaterialTheme.appTypography.bodySmall,
color = MaterialTheme.appColors.error,
)
}
}

@Preview(uiMode = UI_MODE_NIGHT_NO)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ internal fun SignUpView(
textColor = MaterialTheme.appColors.primaryButtonText,
backgroundColor = MaterialTheme.appColors.secondaryButtonBackground,
onClick = {
keyboardController?.hide()
showErrorMap.clear()
onRegisterClick(AuthType.PASSWORD)
}
Expand All @@ -455,6 +456,7 @@ internal fun SignUpView(
isMicrosoftAuthEnabled = uiState.isMicrosoftAuthEnabled,
isSignIn = false,
) {
keyboardController?.hide()
onRegisterClick(it)
}
}
Expand All @@ -478,7 +480,10 @@ private fun RegistrationScreenPreview() {
SignUpView(
windowSize = WindowSize(WindowType.Compact, WindowType.Compact),
uiState = SignUpUIState(
allFields = listOf(field, field, field.copy(required = false)),
allFields = listOf(field),
requiredFields = listOf(field, field),
optionalFields = listOf(field, field),
agreementFields = listOf(field),
),
uiMessage = null,
onBackClick = {},
Expand Down
32 changes: 24 additions & 8 deletions auth/src/main/java/org/openedx/auth/presentation/ui/AuthUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
Expand Down Expand Up @@ -69,14 +70,15 @@ fun RequiredFields(
showErrorMap: MutableMap<String, Boolean?>,
selectableNamesMap: MutableMap<String, String?>,
onFieldUpdated: (String, String) -> Unit,
onSelectClick: (String, RegistrationField, List<RegistrationField.Option>) -> Unit
onSelectClick: (String, RegistrationField, List<RegistrationField.Option>) -> Unit,
) {
fields.forEach { field ->
when (field.type) {
RegistrationFieldType.TEXT,
RegistrationFieldType.EMAIL,
RegistrationFieldType.CONFIRM_EMAIL,
RegistrationFieldType.PASSWORD -> {
RegistrationFieldType.PASSWORD,
-> {
InputRegistrationField(
modifier = Modifier.fillMaxWidth(),
isErrorShown = showErrorMap[field.name] ?: true,
Expand Down Expand Up @@ -232,9 +234,11 @@ fun LoginTextField(
modifier: Modifier = Modifier,
title: String,
description: String,
isError: Boolean = false,
errorMessages: String = "",
onValueChanged: (String) -> Unit,
imeAction: ImeAction = ImeAction.Next,
keyboardActions: (FocusManager) -> Unit = { it.moveFocus(FocusDirection.Down) }
keyboardActions: (FocusManager) -> Unit = { it.moveFocus(FocusDirection.Down) },
) {
var loginTextFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(
Expand Down Expand Up @@ -281,16 +285,28 @@ fun LoginTextField(
},
textStyle = MaterialTheme.appTypography.bodyMedium,
singleLine = true,
modifier = modifier.testTag("tf_email")
modifier = modifier.testTag("tf_email"),
isError = isError
)
if (isError) {
Text(
modifier = Modifier
.testTag("txt_email_error")
.fillMaxWidth()
.padding(top = 4.dp),
text = errorMessages,
style = MaterialTheme.appTypography.bodySmall,
color = MaterialTheme.appColors.error,
)
}
}

@Composable
fun InputRegistrationField(
modifier: Modifier,
isErrorShown: Boolean,
registrationField: RegistrationField,
onValueChanged: (String, String, Boolean) -> Unit
onValueChanged: (String, String, Boolean) -> Unit,
) {
var inputRegistrationFieldValue by rememberSaveable {
mutableStateOf(registrationField.placeholder)
Expand Down Expand Up @@ -401,7 +417,7 @@ fun SelectableRegisterField(
registrationField: RegistrationField,
isErrorShown: Boolean,
initialValue: String,
onClick: (String, List<RegistrationField.Option>) -> Unit
onClick: (String, List<RegistrationField.Option>) -> Unit,
) {
val helperTextColor = if (registrationField.errorInstructions.isEmpty()) {
MaterialTheme.appColors.textSecondary
Expand Down Expand Up @@ -489,7 +505,7 @@ fun SelectableRegisterField(
fun ExpandableText(
modifier: Modifier = Modifier,
isExpanded: Boolean,
onClick: (Boolean) -> Unit
onClick: (Boolean) -> Unit,
) {
val transitionState = remember {
MutableTransitionState(isExpanded).apply {
Expand Down Expand Up @@ -537,7 +553,7 @@ fun ExpandableText(
@Composable
internal fun PasswordVisibilityIcon(
isPasswordVisible: Boolean,
onClick: () -> Unit
onClick: () -> Unit,
) {
val (image, description) = if (isPasswordVisible) {
Icons.Filled.VisibilityOff to stringResource(R.string.auth_accessibility_hide_password)
Expand Down
3 changes: 3 additions & 0 deletions auth/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
<string name="auth_restore_password_success">We have sent a password recover instructions to your email %s</string>
<string name="auth_example_email" translatable="false">[email protected]</string>
<string name="auth_enter_email_username" tools:ignore="MissingTranslation">Enter email or username</string>
<string name="auth_error_empty_username_email">Please enter your username or e-mail address and try again.</string>
<string name="auth_error_empty_email">Please enter your e-mail address and try again.</string>
<string name="auth_enter_password">Enter password</string>
<string name="auth_error_empty_password">Please enter your password and try again.</string>
<string name="auth_create_new_account">Create an account to start learning today!</string>
<string name="auth_compete_registration" translatable="false">Complete your registration</string>
<string name="auth_google" tools:ignore="ExtraTranslation">Sign in with Google</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ private fun DiscussionAddThreadScreen(
),
isSingleLine = false,
withRequiredMark = true,
imeAction = ImeAction.Done,
imeAction = ImeAction.Default,
keyboardActions = { focusManager ->
focusManager.clearFocus()
keyboardController?.hide()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@ private fun InputEditField(
},
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = keyboardType,
imeAction = ImeAction.Done
imeAction = ImeAction.Default
),
keyboardActions = KeyboardActions {
keyboardController?.hide()
Expand Down

0 comments on commit 5abf44d

Please sign in to comment.