Additional logic for the login form
This commit is contained in:
parent
7c5c11b430
commit
085634c95a
4 changed files with 85 additions and 37 deletions
|
@ -27,10 +27,7 @@ class MainActivity : ComponentActivity() {
|
||||||
NavHost(navController = navController, startDestination = LoginRoute) {
|
NavHost(navController = navController, startDestination = LoginRoute) {
|
||||||
composable<LoginRoute> {
|
composable<LoginRoute> {
|
||||||
val viewModel: LoginScreenViewModel by viewModels()
|
val viewModel: LoginScreenViewModel by viewModels()
|
||||||
LoginScreen(
|
LoginScreen(viewModel)
|
||||||
viewModel.loginState,
|
|
||||||
viewModel::updateLoginUsername
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,13 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.imePadding
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.SecondaryTabRow
|
import androidx.compose.material3.SecondaryTabRow
|
||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
|
@ -23,15 +26,17 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
|
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import software.makeshift.debtpirate.R
|
import software.makeshift.debtpirate.R
|
||||||
|
|
||||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||||
@Composable
|
@Composable
|
||||||
fun LoginScreen(
|
fun LoginScreen(
|
||||||
loginState: StateFlow<LoginState>,
|
viewModel: LoginScreenViewModel
|
||||||
updateLoginUsername: (String) -> Unit
|
|
||||||
) {
|
) {
|
||||||
Scaffold(modifier = Modifier.fillMaxSize()) {
|
Scaffold(modifier = Modifier.fillMaxSize()) {
|
||||||
Column {
|
Column {
|
||||||
|
@ -42,7 +47,9 @@ fun LoginScreen(
|
||||||
)
|
)
|
||||||
|
|
||||||
LoginAndSignUpForms(
|
LoginAndSignUpForms(
|
||||||
loginState,
|
loginState = viewModel.loginState,
|
||||||
|
onUsernameUpdate = viewModel::updateLoginUsername,
|
||||||
|
onPasswordUpdate = viewModel::updateLoginPassword,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(3f)
|
.weight(3f)
|
||||||
)
|
)
|
||||||
|
@ -62,7 +69,9 @@ private fun Banner(modifier: Modifier = Modifier) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun LoginAndSignUpForms(
|
private fun LoginAndSignUpForms(
|
||||||
loginTabState: StateFlow<LoginState>,
|
loginState: LoginState,
|
||||||
|
onUsernameUpdate: (String) -> Unit,
|
||||||
|
onPasswordUpdate: (String) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
|
@ -72,13 +81,12 @@ private fun LoginAndSignUpForms(
|
||||||
selectedTabIndex = pagerState.currentPage,
|
selectedTabIndex = pagerState.currentPage,
|
||||||
modifier = Modifier.height(48.dp)
|
modifier = Modifier.height(48.dp)
|
||||||
) {
|
) {
|
||||||
val tabTextStyle = MaterialTheme.typography.titleLarge
|
|
||||||
Tab(
|
Tab(
|
||||||
selected = pagerState.currentPage == 0,
|
selected = pagerState.currentPage == 0,
|
||||||
onClick = { pagerState.requestScrollToPage(0) },
|
onClick = { pagerState.requestScrollToPage(0) },
|
||||||
text = {
|
text = {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = R.string.loginscreen_logintab_logintitle)
|
text = stringResource(id = R.string.login_screen__login)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxHeight()
|
modifier = Modifier.fillMaxHeight()
|
||||||
|
@ -88,7 +96,7 @@ private fun LoginAndSignUpForms(
|
||||||
onClick = { pagerState.requestScrollToPage(1) },
|
onClick = { pagerState.requestScrollToPage(1) },
|
||||||
text = {
|
text = {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = R.string.loginscreen_logintab_signuptitle),
|
text = stringResource(id = R.string.login_screen__signup),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxHeight()
|
modifier = Modifier.fillMaxHeight()
|
||||||
|
@ -97,11 +105,13 @@ private fun LoginAndSignUpForms(
|
||||||
|
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.imePadding()
|
||||||
) { page ->
|
) { page ->
|
||||||
when (page) {
|
when (page) {
|
||||||
0 -> {
|
0 -> {
|
||||||
Text("Page 1!")
|
LoginForm(state = loginState, onUsernameUpdate, onPasswordUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
|
@ -112,9 +122,43 @@ private fun LoginAndSignUpForms(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//@Composable
|
@Composable
|
||||||
//private fun LoginForm(state: StateFlow<LoginState>, onUsernameUpdate: (String) -> Unit, onPasswordUpdate: (String) -> Unit) {
|
private fun LoginForm(
|
||||||
// Column {
|
state: LoginState,
|
||||||
// OutlinedTextField(value = , onValueChange = )
|
onUsernameUpdate: (String) -> Unit,
|
||||||
// }
|
onPasswordUpdate: (String) -> Unit
|
||||||
//}
|
) {
|
||||||
|
val (username, password) = state
|
||||||
|
|
||||||
|
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxSize()) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = username,
|
||||||
|
label = { Text(stringResource(id = R.string.login_screen__username)) },
|
||||||
|
placeholder = { Text(stringResource(id = R.string.login_screen__username)) },
|
||||||
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
capitalization = KeyboardCapitalization.Unspecified,
|
||||||
|
keyboardType = KeyboardType.Email,
|
||||||
|
imeAction = ImeAction.Next
|
||||||
|
),
|
||||||
|
onValueChange = onUsernameUpdate
|
||||||
|
)
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
value = password,
|
||||||
|
label = { Text(stringResource(id = R.string.login_screen__password)) },
|
||||||
|
placeholder = { Text(stringResource(id = R.string.login_screen__password)) },
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
capitalization = KeyboardCapitalization.Unspecified,
|
||||||
|
keyboardType = KeyboardType.Password,
|
||||||
|
imeAction = ImeAction.Send
|
||||||
|
),
|
||||||
|
visualTransformation = PasswordVisualTransformation(),
|
||||||
|
onValueChange = onPasswordUpdate
|
||||||
|
)
|
||||||
|
|
||||||
|
Button(onClick = { /*TODO*/ }) {
|
||||||
|
Text(stringResource(id = R.string.login_screen__login))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,11 @@
|
||||||
package software.makeshift.debtpirate.usecases.login
|
package software.makeshift.debtpirate.usecases.login
|
||||||
|
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
|
|
||||||
data class LoginState(val username: String? = null, val password: String? = null)
|
data class LoginState(val username: String = "", val password: String = "")
|
||||||
|
|
||||||
data class SignUpState(
|
data class SignUpState(
|
||||||
val username: String? = null,
|
val username: String? = null,
|
||||||
|
@ -17,16 +15,22 @@ data class SignUpState(
|
||||||
)
|
)
|
||||||
|
|
||||||
class LoginScreenViewModel : ViewModel() {
|
class LoginScreenViewModel : ViewModel() {
|
||||||
private val _loginState = MutableStateFlow(LoginState())
|
var loginState by mutableStateOf(LoginState())
|
||||||
val loginState = _loginState.asStateFlow()
|
private set
|
||||||
|
|
||||||
val loginUsername: Flow<String?>
|
val loginUsername: String
|
||||||
get() = loginState.map { loginState -> loginState.username }
|
get() = loginState.username
|
||||||
|
|
||||||
fun updateLoginUsername(username: String) {
|
fun updateLoginUsername(username: String) {
|
||||||
_loginState.update { state ->
|
val (_, password) = loginState
|
||||||
val (_, password) = state
|
loginState = LoginState(username, password)
|
||||||
LoginState(username, password)
|
}
|
||||||
}
|
|
||||||
|
val loginPassword: String
|
||||||
|
get() = loginState.password
|
||||||
|
|
||||||
|
fun updateLoginPassword(password: String) {
|
||||||
|
val (username, _) = loginState
|
||||||
|
loginState = LoginState(username, password)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,6 +2,9 @@
|
||||||
<string name="app_name">Debt Pirate</string>
|
<string name="app_name">Debt Pirate</string>
|
||||||
|
|
||||||
<!-- Login Screen -->
|
<!-- Login Screen -->
|
||||||
<string name="loginscreen_logintab_logintitle">Login</string>
|
<string name="login_screen__login">Login</string>
|
||||||
<string name="loginscreen_logintab_signuptitle">Sign Up</string>
|
<string name="login_screen__signup">Sign Up</string>
|
||||||
|
<string name="login_screen__username">Username</string>
|
||||||
|
<string name="login_screen__password">Password</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
Loading…
Add table
Reference in a new issue