Skip to content

Commit

Permalink
fix: UI Issues on Auth Screens (#332)
Browse files Browse the repository at this point in the history
- feat: Add password visibility toggle to the password fields  
- fix: Autofill the "Full Name" and "Email" fields with SSO data
- refactor: Redesign the modal that appears after SSO

Fixes: Issue#331
  • Loading branch information
HamzaIsrar12 authored Jun 11, 2024
1 parent d845e5e commit 5c887eb
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
Expand All @@ -58,6 +59,7 @@ import org.openedx.auth.R
import org.openedx.auth.presentation.signin.AuthEvent
import org.openedx.auth.presentation.signin.SignInUIState
import org.openedx.auth.presentation.ui.LoginTextField
import org.openedx.auth.presentation.ui.PasswordVisibilityIcon
import org.openedx.auth.presentation.ui.SocialAuthView
import org.openedx.core.UIMessage
import org.openedx.core.extension.TextConverter
Expand Down Expand Up @@ -305,11 +307,11 @@ private fun PasswordTextField(
onPressDone: () -> Unit,
) {
var passwordTextFieldValue by rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(
TextFieldValue("")
)
mutableStateOf(TextFieldValue(""))
}
var isPasswordVisible by remember { mutableStateOf(false) }
val focusManager = LocalFocusManager.current

Text(
modifier = Modifier
.testTag("txt_password_label")
Expand All @@ -318,7 +320,9 @@ private fun PasswordTextField(
color = MaterialTheme.appColors.textPrimary,
style = MaterialTheme.appTypography.labelLarge
)

Spacer(modifier = Modifier.height(8.dp))

OutlinedTextField(
modifier = modifier.testTag("tf_password"),
value = passwordTextFieldValue,
Expand All @@ -341,11 +345,18 @@ private fun PasswordTextField(
style = MaterialTheme.appTypography.bodyMedium
)
},
trailingIcon = {
PasswordVisibilityIcon(
isPasswordVisible = isPasswordVisible,
onClick = { isPasswordVisible = !isPasswordVisible }
)
},
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done
),
visualTransformation = PasswordVisualTransformation(),
visualTransformation = if (isPasswordVisible) VisualTransformation.None
else PasswordVisualTransformation(),
keyboardActions = KeyboardActions {
focusManager.clearFocus()
onPressDone()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,14 @@ class SignUpViewModel(
interactor.loginSocial(socialAuth.accessToken, socialAuth.authType)
}.onFailure {
val fields = uiState.value.allFields.toMutableList()
.filter { field -> field.type != RegistrationFieldType.PASSWORD }
updateField(ApiConstants.NAME, socialAuth.name)
updateField(ApiConstants.EMAIL, socialAuth.email)
.filter { it.type != RegistrationFieldType.PASSWORD }
.map { field ->
when (field.name) {
ApiConstants.NAME -> field.copy(placeholder = socialAuth.name)
ApiConstants.EMAIL -> field.copy(placeholder = socialAuth.email)
else -> field
}
}
setErrorInstructions(emptyMap())
_uiState.update {
it.copy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Devices
Expand Down Expand Up @@ -317,10 +318,11 @@ internal fun SignUpView(
Text(
modifier = Modifier
.fillMaxWidth()
.padding(top = 4.dp),
.padding(top = 8.dp),
text = stringResource(
id = R.string.auth_compete_registration
),
fontWeight = FontWeight.Bold,
color = MaterialTheme.appColors.textPrimary,
style = MaterialTheme.appTypography.titleSmall
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ package org.openedx.auth.presentation.signup.compose
import android.content.res.Configuration
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Devices
Expand All @@ -26,21 +30,36 @@ internal fun SocialSignedView(authType: AuthType) {
Column(
modifier = Modifier
.background(
color = MaterialTheme.appColors.secondary,
color = MaterialTheme.appColors.authSSOSuccessBackground,
shape = MaterialTheme.appShapes.buttonShape
)
.padding(20.dp)
) {
Text(
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
text = stringResource(
id = R.string.auth_social_signed_title,
authType.methodName
Row {
Icon(
modifier = Modifier
.padding(end = 8.dp)
.size(20.dp),
painter = painterResource(id = coreR.drawable.ic_core_check),
tint = MaterialTheme.appColors.successBackground,
contentDescription = ""
)
)

Text(
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colors.primary,
text = stringResource(
id = R.string.auth_social_signed_title,
authType.methodName
)
)
}

Text(
modifier = Modifier.padding(top = 8.dp),
modifier = Modifier.padding(top = 8.dp, start = 28.dp),
fontSize = 14.sp,
fontWeight = FontWeight.Normal,
text = stringResource(
id = R.string.auth_social_signed_desc,
stringResource(id = coreR.string.app_name)
Expand Down
54 changes: 49 additions & 5 deletions auth/src/main/java/org/openedx/auth/presentation/ui/AuthUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ChevronRight
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -70,7 +73,10 @@ fun RequiredFields(
) {
fields.forEach { field ->
when (field.type) {
RegistrationFieldType.TEXT, RegistrationFieldType.EMAIL, RegistrationFieldType.CONFIRM_EMAIL, RegistrationFieldType.PASSWORD -> {
RegistrationFieldType.TEXT,
RegistrationFieldType.EMAIL,
RegistrationFieldType.CONFIRM_EMAIL,
RegistrationFieldType.PASSWORD -> {
InputRegistrationField(
modifier = Modifier.fillMaxWidth(),
isErrorShown = showErrorMap[field.name] ?: true,
Expand Down Expand Up @@ -289,11 +295,15 @@ fun InputRegistrationField(
var inputRegistrationFieldValue by rememberSaveable {
mutableStateOf(registrationField.placeholder)
}
var isPasswordVisible by remember { mutableStateOf(false) }

val focusManager = LocalFocusManager.current
val visualTransformation = if (registrationField.type == RegistrationFieldType.PASSWORD) {
PasswordVisualTransformation()
} else {
VisualTransformation.None
val visualTransformation = remember(isPasswordVisible) {
if (registrationField.type == RegistrationFieldType.PASSWORD && !isPasswordVisible) {
PasswordVisualTransformation()
} else {
VisualTransformation.None
}
}
val keyboardType = when (registrationField.type) {
RegistrationFieldType.CONFIRM_EMAIL, RegistrationFieldType.EMAIL -> KeyboardType.Email
Expand All @@ -315,6 +325,18 @@ fun InputRegistrationField(
} else {
registrationField.instructions
}
val trailingIcon: @Composable (() -> Unit)? =
if (registrationField.type == RegistrationFieldType.PASSWORD) {
{
PasswordVisibilityIcon(
isPasswordVisible = isPasswordVisible,
onClick = { isPasswordVisible = !isPasswordVisible }
)
}
} else {
null
}

Column {
Text(
modifier = Modifier
Expand Down Expand Up @@ -359,6 +381,7 @@ fun InputRegistrationField(
keyboardActions = KeyboardActions {
focusManager.moveFocus(FocusDirection.Down)
},
trailingIcon = trailingIcon,
textStyle = MaterialTheme.appTypography.bodyMedium,
singleLine = isSingleLine,
modifier = modifier.testTag("tf_${registrationField.name.tagId()}")
Expand Down Expand Up @@ -418,6 +441,7 @@ fun SelectableRegisterField(
OutlinedTextField(
readOnly = true,
enabled = false,
singleLine = true,
value = initialValue,
colors = TextFieldDefaults.outlinedTextFieldColors(
unfocusedBorderColor = MaterialTheme.appColors.textFieldBorder,
Expand Down Expand Up @@ -510,6 +534,26 @@ fun ExpandableText(
}
}

@Composable
internal fun PasswordVisibilityIcon(
isPasswordVisible: Boolean,
onClick: () -> Unit
) {
val (image, description) = if (isPasswordVisible) {
Icons.Filled.VisibilityOff to stringResource(R.string.auth_accessibility_hide_password)
} else {
Icons.Filled.Visibility to stringResource(R.string.auth_accessibility_show_password)
}

IconButton(onClick = onClick) {
Icon(
imageVector = image,
contentDescription = description,
tint = MaterialTheme.appColors.onSurface
)
}
}

@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
Expand Down
2 changes: 2 additions & 0 deletions auth/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@
<string name="auth_agreement_creating_account" tools:ignore="ExtraTranslation">By creating an account, you agree to the %1$s and %2$s and you acknowledge that %3$s and each Member process your personal data in accordance with the %4$s.</string>
<string name="auth_agreement_signin_in">By signing in to this app, you agree to the %1$s and %2$s and you acknowledge that %3$s and each Member process your personal data in accordance with the %4$s.</string>
<string name="auth_cdata_template" translatable="false"><![CDATA[<a href="%1$s">%2$s</a>]]></string>
<string name="auth_accessibility_show_password">Show password</string>
<string name="auth_accessibility_hide_password">Hide password</string>
</resources>
2 changes: 2 additions & 0 deletions core/src/main/java/org/openedx/core/ui/theme/AppColors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ data class AppColors(
val inactiveButtonText: Color,

val successGreen: Color,
val successBackground: Color,

val datesSectionBarPastDue: Color,
val datesSectionBarToday: Color,
val datesSectionBarThisWeek: Color,
val datesSectionBarNextWeek: Color,
val datesSectionBarUpcoming: Color,

val authSSOSuccessBackground: Color,
val authGoogleButtonBackground: Color,
val authFacebookButtonBackground: Color,
val authMicrosoftButtonBackground: Color,
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/java/org/openedx/core/ui/theme/Theme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ private val DarkColorPalette = AppColors(
inactiveButtonText = dark_primary_button_text,

successGreen = dark_success_green,
successBackground = dark_success_background,

datesSectionBarPastDue = dark_dates_section_bar_past_due,
datesSectionBarToday = dark_dates_section_bar_today,
datesSectionBarThisWeek = dark_dates_section_bar_this_week,
datesSectionBarNextWeek = dark_dates_section_bar_next_week,
datesSectionBarUpcoming = dark_dates_section_bar_upcoming,

authSSOSuccessBackground = dark_auth_sso_success_background,
authGoogleButtonBackground = dark_auth_google_button_background,
authFacebookButtonBackground = dark_auth_facebook_button_background,
authMicrosoftButtonBackground = dark_auth_microsoft_button_background,
Expand Down Expand Up @@ -156,13 +158,15 @@ private val LightColorPalette = AppColors(
inactiveButtonText = light_primary_button_text,

successGreen = light_success_green,
successBackground = light_success_background,

datesSectionBarPastDue = light_dates_section_bar_past_due,
datesSectionBarToday = light_dates_section_bar_today,
datesSectionBarThisWeek = light_dates_section_bar_this_week,
datesSectionBarNextWeek = light_dates_section_bar_next_week,
datesSectionBarUpcoming = light_dates_section_bar_upcoming,

authSSOSuccessBackground = light_auth_sso_success_background,
authGoogleButtonBackground = light_auth_google_button_background,
authFacebookButtonBackground = light_auth_facebook_button_background,
authMicrosoftButtonBackground = light_auth_microsoft_button_background,
Expand Down
4 changes: 4 additions & 0 deletions core/src/openedx/org/openedx/core/ui/theme/Colors.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ val light_info = Color(0xFF42AAFF)
val light_rate_stars = Color(0xFFFFC94D)
val light_inactive_button_background = Color(0xFFCCD4E0)
val light_success_green = Color(0xFF198571)
val light_success_background = Color(0xFF0D7D4D)
val light_dates_section_bar_past_due = light_warning
val light_dates_section_bar_today = light_info
val light_dates_section_bar_this_week = light_text_primary_variant
val light_dates_section_bar_next_week = light_text_field_border
val light_dates_section_bar_upcoming = Color(0xFFCCD4E0)
val light_auth_sso_success_background = light_secondary
val light_auth_google_button_background = Color.White
val light_auth_facebook_button_background = Color(0xFF0866FF)
val light_auth_microsoft_button_background = Color(0xFA000000)
Expand Down Expand Up @@ -124,11 +126,13 @@ val dark_onInfo = Color.White
val dark_rate_stars = Color(0xFFFFC94D)
val dark_inactive_button_background = Color(0xFFCCD4E0)
val dark_success_green = Color(0xFF198571)
val dark_success_background = Color.White
val dark_dates_section_bar_past_due = dark_warning
val dark_dates_section_bar_today = dark_info
val dark_dates_section_bar_this_week = dark_text_primary_variant
val dark_dates_section_bar_next_week = dark_text_field_border
val dark_dates_section_bar_upcoming = Color(0xFFCCD4E0)
val dark_auth_sso_success_background = dark_secondary
val dark_auth_google_button_background = Color(0xFF19212F)
val dark_auth_facebook_button_background = Color(0xFF0866FF)
val dark_auth_microsoft_button_background = Color(0xFA000000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ fun SubSectionUnitsList(
modifier = Modifier
.size(16.dp)
.alpha(if (unit.isCompleted()) 1f else 0f),
painter = painterResource(id = R.drawable.ic_course_check),
painter = painterResource(id = coreR.drawable.ic_core_check),
contentDescription = "done"
)
Text(
Expand Down

0 comments on commit 5c887eb

Please sign in to comment.