Remove bad usage of ElementSurface

This commit is contained in:
Benoit Marty 2023-01-26 18:01:27 +01:00 committed by Benoit Marty
parent 7d85d8da30
commit 2b7c965236
5 changed files with 384 additions and 407 deletions

View file

@ -33,9 +33,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@ -58,7 +56,6 @@ import io.element.android.libraries.designsystem.theme.ElementTheme
import io.element.android.libraries.designsystem.theme.components.ElementButton
import io.element.android.libraries.designsystem.theme.components.ElementCircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.ElementOutlinedTextField
import io.element.android.libraries.designsystem.theme.components.ElementSurface
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag
@ -68,118 +65,114 @@ fun ChangeServerView(
modifier: Modifier = Modifier,
onChangeServerSuccess: () -> Unit = {},
) {
ElementSurface(
modifier = modifier,
val eventSink = state.eventSink
val scrollState = rememberScrollState()
Box(
modifier = modifier
.fillMaxSize()
.systemBarsPadding()
.imePadding()
) {
val eventSink = state.eventSink
val scrollState = rememberScrollState()
Box(
Column(
modifier = Modifier
.fillMaxSize()
.systemBarsPadding()
.imePadding()
.verticalScroll(
state = scrollState,
)
.padding(horizontal = 16.dp)
) {
Column(
val isError = state.changeServerAction is Async.Failure
Box(
modifier = Modifier
.verticalScroll(
state = scrollState,
.padding(top = 99.dp)
.size(width = 81.dp, height = 73.dp)
.align(Alignment.CenterHorizontally)
.background(
color = ElementTheme.colors.surfaceVariant,
shape = RoundedCornerShape(32.dp)
)
.padding(horizontal = 16.dp)
) {
val isError = state.changeServerAction is Async.Failure
Box(
VectorIcon(
modifier = Modifier
.padding(top = 99.dp)
.size(width = 81.dp, height = 73.dp)
.align(Alignment.CenterHorizontally)
.background(
color = ElementTheme.colors.surfaceVariant,
shape = RoundedCornerShape(32.dp)
)
) {
VectorIcon(
modifier = Modifier
.align(Alignment.Center)
.size(width = 48.dp, height = 48.dp),
// TODO Update with design input
resourceId = R.drawable.ic_baseline_dataset_24,
)
}
Text(
text = "Your server",
modifier = Modifier
.fillMaxWidth()
.defaultMinSize(minHeight = 56.dp)
.align(Alignment.CenterHorizontally)
.padding(top = 38.dp),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
fontSize = 24.sp,
.align(Alignment.Center)
.size(width = 48.dp, height = 48.dp),
// TODO Update with design input
resourceId = R.drawable.ic_baseline_dataset_24,
)
Text(
text = "A server is a home for all your data.\n" +
"You choose your server and its easy to make one.", // TODO "Learn more.",
modifier = Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally)
.padding(top = 16.dp),
textAlign = TextAlign.Center,
fontSize = 16.sp,
color = ElementTheme.colors.secondary
}
Text(
text = "Your server",
modifier = Modifier
.fillMaxWidth()
.defaultMinSize(minHeight = 56.dp)
.align(Alignment.CenterHorizontally)
.padding(top = 38.dp),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
fontSize = 24.sp,
)
Text(
text = "A server is a home for all your data.\n" +
"You choose your server and its easy to make one.", // TODO "Learn more.",
modifier = Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally)
.padding(top = 16.dp),
textAlign = TextAlign.Center,
fontSize = 16.sp,
color = ElementTheme.colors.secondary
)
var homeserverFieldState by textFieldState(stateValue = state.homeserver)
ElementOutlinedTextField(
value = homeserverFieldState,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.changeServerServer)
.padding(top = 200.dp),
onValueChange = {
homeserverFieldState = it
eventSink(ChangeServerEvents.SetServer(it))
},
label = {
Text(text = "Server")
},
isError = isError,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(
onDone = { eventSink(ChangeServerEvents.Submit) }
)
var homeserverFieldState by textFieldState(stateValue = state.homeserver)
ElementOutlinedTextField(
value = homeserverFieldState,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.changeServerServer)
.padding(top = 200.dp),
onValueChange = {
homeserverFieldState = it
eventSink(ChangeServerEvents.SetServer(it))
},
label = {
Text(text = "Server")
},
isError = isError,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done,
)
if (state.changeServerAction is Async.Failure) {
Text(
text = changeServerError(
state.homeserver,
state.changeServerAction.error
),
keyboardActions = KeyboardActions(
onDone = { eventSink(ChangeServerEvents.Submit) }
)
)
if (state.changeServerAction is Async.Failure) {
Text(
text = changeServerError(
state.homeserver,
state.changeServerAction.error
),
color = ElementTheme.colors.error,
style = ElementTheme.typography.bodySmall,
modifier = Modifier.padding(start = 16.dp)
)
}
ElementButton(
onClick = { eventSink(ChangeServerEvents.Submit) },
enabled = state.submitEnabled,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.changeServerContinue)
.padding(top = 44.dp)
) {
Text(text = "Continue")
}
if (state.changeServerAction is Async.Success) {
onChangeServerSuccess()
}
}
if (state.changeServerAction is Async.Loading) {
ElementCircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
color = ElementTheme.colors.error,
style = ElementTheme.typography.bodySmall,
modifier = Modifier.padding(start = 16.dp)
)
}
ElementButton(
onClick = { eventSink(ChangeServerEvents.Submit) },
enabled = state.submitEnabled,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.changeServerContinue)
.padding(top = 44.dp)
) {
Text(text = "Continue")
}
if (state.changeServerAction is Async.Success) {
onChangeServerSuccess()
}
}
if (state.changeServerAction is Async.Loading) {
ElementCircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
)
}
}
}

View file

@ -18,6 +18,7 @@
package io.element.android.features.login.root
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
@ -59,7 +60,6 @@ import io.element.android.libraries.designsystem.theme.ElementTheme
import io.element.android.libraries.designsystem.theme.components.ElementButton
import io.element.android.libraries.designsystem.theme.components.ElementCircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.ElementOutlinedTextField
import io.element.android.libraries.designsystem.theme.components.ElementSurface
import io.element.android.libraries.matrix.core.SessionId
import io.element.android.libraries.testtags.TestTags
import io.element.android.libraries.testtags.testTag
@ -73,153 +73,149 @@ fun LoginRootScreen(
onLoginWithSuccess: (SessionId) -> Unit = {},
) {
val eventSink = state.eventSink
ElementSurface(
modifier = modifier,
Box(
modifier = modifier
.fillMaxSize()
.systemBarsPadding()
.imePadding()
) {
Box(
val scrollState = rememberScrollState()
var loginFieldState by textFieldState(stateValue = state.formState.login)
var passwordFieldState by textFieldState(stateValue = state.formState.password)
Column(
modifier = Modifier
.fillMaxSize()
.systemBarsPadding()
.imePadding()
.verticalScroll(
state = scrollState,
)
.padding(horizontal = 16.dp),
) {
val scrollState = rememberScrollState()
var loginFieldState by textFieldState(stateValue = state.formState.login)
var passwordFieldState by textFieldState(stateValue = state.formState.password)
Column(
val isError = state.loggedInState is LoggedInState.ErrorLoggingIn
// Title
Text(
text = stringResource(id = StringR.string.ftue_auth_welcome_back_title),
modifier = Modifier
.verticalScroll(
state = scrollState,
)
.padding(horizontal = 16.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 48.dp),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
fontSize = 24.sp,
)
// Form
Column(
// modifier = Modifier.weight(1f),
) {
val isError = state.loggedInState is LoggedInState.ErrorLoggingIn
// Title
Text(
text = stringResource(id = StringR.string.ftue_auth_welcome_back_title),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 48.dp),
textAlign = TextAlign.Center,
fontWeight = FontWeight.Bold,
fontSize = 24.sp,
)
// Form
Column(
// modifier = Modifier.weight(1f),
Box(
modifier = Modifier.fillMaxWidth()
) {
Box(
modifier = Modifier.fillMaxWidth()
) {
ElementOutlinedTextField(
value = state.homeserver,
modifier = Modifier.fillMaxWidth(),
onValueChange = { /* no op */ },
enabled = false,
label = {
Text(text = "Server")
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Uri,
),
)
ElementButton(
onClick = onChangeServer,
modifier = Modifier
.align(Alignment.CenterEnd)
.testTag(TestTags.loginChangeServer)
.padding(top = 8.dp, end = 8.dp),
content = {
Text(text = "Change")
}
)
}
ElementOutlinedTextField(
value = loginFieldState,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.loginEmailUsername)
.padding(top = 60.dp),
value = state.homeserver,
modifier = Modifier.fillMaxWidth(),
onValueChange = { /* no op */ },
enabled = false,
label = {
Text(text = stringResource(id = StringR.string.login_signin_username_hint))
},
onValueChange = {
loginFieldState = it
eventSink(LoginRootEvents.SetLogin(it))
Text(text = "Server")
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
imeAction = ImeAction.Next
keyboardType = KeyboardType.Uri,
),
)
var passwordVisible by remember { mutableStateOf(false) }
if (state.loggedInState is LoggedInState.LoggingIn) {
// Ensure password is hidden when user submits the form
passwordVisible = false
}
ElementOutlinedTextField(
value = passwordFieldState,
ElementButton(
onClick = onChangeServer,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.loginPassword)
.padding(top = 24.dp),
onValueChange = {
passwordFieldState = it
eventSink(LoginRootEvents.SetPassword(it))
},
label = {
Text(text = "Password")
},
isError = isError,
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
val image =
if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
val description =
if (passwordVisible) "Hide password" else "Show password"
.align(Alignment.CenterEnd)
.testTag(TestTags.loginChangeServer)
.padding(top = 8.dp, end = 8.dp),
content = {
Text(text = "Change")
}
)
}
ElementOutlinedTextField(
value = loginFieldState,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.loginEmailUsername)
.padding(top = 60.dp),
label = {
Text(text = stringResource(id = StringR.string.login_signin_username_hint))
},
onValueChange = {
loginFieldState = it
eventSink(LoginRootEvents.SetLogin(it))
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
imeAction = ImeAction.Next
),
)
var passwordVisible by remember { mutableStateOf(false) }
if (state.loggedInState is LoggedInState.LoggingIn) {
// Ensure password is hidden when user submits the form
passwordVisible = false
}
ElementOutlinedTextField(
value = passwordFieldState,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.loginPassword)
.padding(top = 24.dp),
onValueChange = {
passwordFieldState = it
eventSink(LoginRootEvents.SetPassword(it))
},
label = {
Text(text = "Password")
},
isError = isError,
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
val image =
if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
val description =
if (passwordVisible) "Hide password" else "Show password"
IconButton(onClick = { passwordVisible = !passwordVisible }) {
Icon(imageVector = image, description)
}
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(
onDone = { eventSink(LoginRootEvents.Submit) }
),
)
if (state.loggedInState is LoggedInState.ErrorLoggingIn) {
Text(
text = loginError(state.formState, state.loggedInState.failure),
color = ElementTheme.colors.error,
style = ElementTheme.typography.bodySmall,
modifier = Modifier.padding(start = 16.dp)
)
}
}
// Submit
ElementButton(
onClick = { eventSink(LoginRootEvents.Submit) },
enabled = state.submitEnabled,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.loginContinue)
.padding(vertical = 32.dp)
) {
Text(text = "Continue")
}
when (val loggedInState = state.loggedInState) {
is LoggedInState.LoggedIn -> onLoginWithSuccess(loggedInState.sessionId)
else -> Unit
}
}
if (state.loggedInState is LoggedInState.LoggingIn) {
ElementCircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
IconButton(onClick = { passwordVisible = !passwordVisible }) {
Icon(imageVector = image, description)
}
},
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(
onDone = { eventSink(LoginRootEvents.Submit) }
),
)
if (state.loggedInState is LoggedInState.ErrorLoggingIn) {
Text(
text = loginError(state.formState, state.loggedInState.failure),
color = ElementTheme.colors.error,
style = ElementTheme.typography.bodySmall,
modifier = Modifier.padding(start = 16.dp)
)
}
}
// Submit
ElementButton(
onClick = { eventSink(LoginRootEvents.Submit) },
enabled = state.submitEnabled,
modifier = Modifier
.fillMaxWidth()
.testTag(TestTags.loginContinue)
.padding(vertical = 32.dp)
) {
Text(text = "Continue")
}
when (val loggedInState = state.loggedInState) {
is LoggedInState.LoggedIn -> onLoginWithSuccess(loggedInState.sessionId)
else -> Unit
}
}
if (state.loggedInState is LoggedInState.LoggingIn) {
ElementCircularProgressIndicator(
modifier = Modifier.align(Alignment.Center)
)
}
}
}