Implemented LoginScreen

This commit is contained in:
dankito 2024-09-18 05:56:58 +02:00
parent 6e6449e956
commit 4697119c58
5 changed files with 108 additions and 2 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -9,6 +9,8 @@ import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch
import net.codinux.banking.ui.config.Colors
import net.codinux.banking.ui.config.DI
import net.codinux.banking.ui.model.settings.AppAuthenticationMethod
import net.codinux.banking.ui.screens.LoginScreen
import net.codinux.banking.ui.screens.MainScreen
import net.codinux.log.LoggerFactory
import org.jetbrains.compose.ui.tooling.preview.Preview
@ -25,13 +27,23 @@ fun App() {
val colors = MaterialTheme.colors.copy(primary = Colors.Primary, primaryVariant = Colors.PrimaryDark, onPrimary = Color.White,
secondary = Colors.Accent, secondaryVariant = Colors.Accent, onSecondary = Color.White)
val appSettings = DI.uiState.appSettings.collectAsState().value
var isLoggedIn by remember(appSettings.authenticationMethod) { mutableStateOf(appSettings.authenticationMethod == AppAuthenticationMethod.None) }
var isInitialized by remember { mutableStateOf(false) }
val coroutineScope = rememberCoroutineScope()
MaterialTheme(colors = colors, typography = typography) {
MainScreen()
if (isLoggedIn == false) {
LoginScreen(appSettings) {
isLoggedIn = true
}
} else {
MainScreen()
}
}

View File

@ -43,6 +43,10 @@ object DI {
fun setRepository(repository: BankingRepository) {
this.bankingRepository = repository
repository.getAppSettings()?.let { // otherwise it's the first app start, BankingService will take care of this case
uiState.appSettings.value = it
}
}

View File

@ -17,7 +17,16 @@ import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
@Composable // try BasicSecureTextField
fun PasswordTextField(password: String = "", label: String = "Passwort", modifier: Modifier = Modifier, keyboardOptions: KeyboardOptions? = null, forceHidePassword: Boolean? = null, onEnterPressed: (() -> Unit)? = null, onChange: (String) -> Unit) {
fun PasswordTextField(
password: String = "",
label: String = "Passwort",
modifier: Modifier = Modifier,
keyboardOptions: KeyboardOptions? = null,
isError: Boolean = false,
forceHidePassword: Boolean? = null,
onEnterPressed: (() -> Unit)? = null,
onChange: (String) -> Unit
) {
var passwordVisible by remember { mutableStateOf(false) }
@ -30,6 +39,7 @@ fun PasswordTextField(password: String = "", label: String = "Passwort", modifie
onValueChange = { onChange(it) },
label = { Text(label) },
modifier = modifier.fillMaxWidth(),
isError = isError,
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
val visibilityIcon = if (passwordVisible) {

View File

@ -0,0 +1,80 @@
package net.codinux.banking.ui.screens
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import bankmeister.composeapp.generated.resources.*
import bankmeister.composeapp.generated.resources.Res
import net.codinux.banking.ui.forms.PasswordTextField
import net.codinux.banking.ui.model.settings.AppAuthenticationMethod
import net.codinux.banking.ui.model.settings.AppSettings
import net.codinux.banking.ui.service.PasswordService
import org.jetbrains.compose.resources.imageResource
@Composable
fun LoginScreen(appSettings: AppSettings, onLoginSuccess: () -> Unit) {
var password by remember { mutableStateOf("") }
var showError by remember { mutableStateOf(false) }
fun checkPassword() {
if (appSettings.hashedPassword != null && PasswordService.checkPassword(password, appSettings.hashedPassword!!)) {
onLoginSuccess()
} else {
showError = true
}
}
Box(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Image(imageResource(Res.drawable.AppIcon_round), "Bankmeister's app icon", Modifier.size(144.dp).padding(bottom = 32.dp))
if (appSettings.authenticationMethod == AppAuthenticationMethod.Password) {
Text("Bitte geben Sie Ihr Passwort ein um die App zu entsperren", style = MaterialTheme.typography.h5, textAlign = TextAlign.Center)
Spacer(modifier = Modifier.height(24.dp))
PasswordTextField(
password = password,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
onEnterPressed = { checkPassword() },
isError = showError
) {
password = it
showError = false
}
if (showError) {
Spacer(modifier = Modifier.height(16.dp))
Text("Passwort ist falsch", color = MaterialTheme.colors.error, fontSize = 18.sp)
}
Button(modifier = Modifier.padding(top = 24.dp).width(300.dp).height(50.dp), onClick = { checkPassword() }) {
Text("Login", color = Color.White)
}
}
}
}
}