Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) }

Comment thread
HamzaIsrar12 marked this conversation as resolved.
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">username@domain.com</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