From 8378dd8d58e9bb407865f386ab3f6ff3e9ece43f Mon Sep 17 00:00:00 2001 From: Shade Date: Fri, 22 Nov 2024 18:53:44 +0400 Subject: [PATCH] Form Patching Support --- .../kotlin/core/models/SelectedCredential.kt | 44 ++++++++++ src/main/kotlin/core/models/UiModel.kt | 42 ++-------- .../forms/passwordmgnt/CreditCardForm.kt | 55 ++++++++---- .../components/forms/passwordmgnt/NoteForm.kt | 3 +- .../forms/passwordmgnt/PasswordForm.kt | 23 ++--- .../forms/passwordmgnt/PasswordMgntWrapper.kt | 8 +- .../passwordinfo/PasswordInfoHeader.kt | 14 +++- .../passwordlayout/PasswordFilterHeader.kt | 3 +- .../kotlin/ui/screens/PasswordMgntScreen.kt | 12 ++- .../ui/validators/CreditCardFormValidator.kt | 84 ++++++++++--------- .../ui/validators/PasswordFormValidator.kt | 22 +++-- 11 files changed, 190 insertions(+), 120 deletions(-) create mode 100644 src/main/kotlin/core/models/SelectedCredential.kt diff --git a/src/main/kotlin/core/models/SelectedCredential.kt b/src/main/kotlin/core/models/SelectedCredential.kt new file mode 100644 index 0000000..a5fbefe --- /dev/null +++ b/src/main/kotlin/core/models/SelectedCredential.kt @@ -0,0 +1,44 @@ +package core.models + +import repository.creditcard.CreditCard +import repository.password.Password +import java.util.* + +data class SelectedCredential( + val password: Password?, + val creditCard: CreditCard? +) { + + fun getTitle(type: DefaultMenuItem): String { + return when(type) { + DefaultMenuItem.PASSWORDS -> { + password?.name?.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } ?: "" + } + + DefaultMenuItem.CREDIT_CARD -> { + creditCard?.name?.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } ?: "" + } + + DefaultMenuItem.NOTES -> TODO() + } + } + + fun getDescription(type: DefaultMenuItem): String { + return when(type) { + DefaultMenuItem.PASSWORDS -> { + password?.email?.takeIf { it.isNotEmpty() } ?: password?.username ?: "" + } + + DefaultMenuItem.CREDIT_CARD -> { + creditCard?.number ?: "" + } + + DefaultMenuItem.NOTES -> TODO() + } + } + + fun isSelected(): Boolean { + return password != null || creditCard != null + } + +} \ No newline at end of file diff --git a/src/main/kotlin/core/models/UiModel.kt b/src/main/kotlin/core/models/UiModel.kt index a7a6da9..ae0366e 100644 --- a/src/main/kotlin/core/models/UiModel.kt +++ b/src/main/kotlin/core/models/UiModel.kt @@ -1,8 +1,6 @@ package core.models import androidx.compose.ui.graphics.Color -import repository.creditcard.CreditCard -import repository.password.Password import java.util.* enum class NotificationType(val color: Color) { @@ -18,41 +16,6 @@ data class CredentialDisplay( val favorite: Boolean ) -data class SelectedCredential( - val password: Password?, - val creditCard: CreditCard? -) { - - fun getTitle(type: DefaultMenuItem): String { - return when(type) { - DefaultMenuItem.PASSWORDS -> { - password?.name?.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } ?: "" - } - - DefaultMenuItem.CREDIT_CARD -> { - creditCard?.name?.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } ?: "" - } - - DefaultMenuItem.NOTES -> TODO() - } - } - - fun getDescription(type: DefaultMenuItem): String { - return when(type) { - DefaultMenuItem.PASSWORDS -> { - password?.email?.takeIf { it.isNotEmpty() } ?: password?.username ?: "" - } - - DefaultMenuItem.CREDIT_CARD -> { - creditCard?.number ?: "" - } - - DefaultMenuItem.NOTES -> TODO() - } - } - -} - enum class CredentialSort(val value: String) { NAME("Name"), FAVORITE("Favorite"), @@ -63,4 +26,9 @@ enum class DefaultMenuItem(val value: String) { PASSWORDS("Passwords"), CREDIT_CARD("Credit Cards"), NOTES("Notes") +} + +enum class FormType { + CREATION, + MODIFIATION } \ No newline at end of file diff --git a/src/main/kotlin/ui/components/forms/passwordmgnt/CreditCardForm.kt b/src/main/kotlin/ui/components/forms/passwordmgnt/CreditCardForm.kt index 20f171f..9c059fc 100644 --- a/src/main/kotlin/ui/components/forms/passwordmgnt/CreditCardForm.kt +++ b/src/main/kotlin/ui/components/forms/passwordmgnt/CreditCardForm.kt @@ -19,8 +19,10 @@ import com.dokar.sonner.ToastType import com.dokar.sonner.Toaster import com.dokar.sonner.rememberToasterState import core.form.validation.FormValidator +import core.models.FormType import core.models.UiState import kotlinx.coroutines.delay +import repository.creditcard.CreditCard import repository.user.User import ui.components.* import ui.screens.SecVaultScreen @@ -34,12 +36,15 @@ import ui.validators.toCreditCardDto import viewmodel.PasswordMgntScreenModel import kotlin.time.Duration.Companion.seconds -class CreditCardForm : Screen { +class CreditCardForm(creditCard: CreditCard?, formType: FormType) : Screen { + + private val _creditCard = creditCard + private val _formType = formType @Composable override fun Content() { - val formValidator = remember { creditCardFormValidator() } + val formValidator = remember { creditCardFormValidator(_creditCard) } val screenModel = koinScreenModel() val passwordState by screenModel.passwordState.collectAsState() val navigator = LocalNavigator.current @@ -56,7 +61,8 @@ class CreditCardForm : Screen { CreditCardFormContent( formValidator, screenModel, - navigator + navigator, + _formType ) when (val state = passwordState) { @@ -90,13 +96,17 @@ class CreditCardForm : Screen { } @Composable - fun CreditCardFormContent(formValidator: FormValidator, screenModel: PasswordMgntScreenModel, navigator: Navigator?) { + fun CreditCardFormContent( + formValidator: FormValidator, + screenModel: PasswordMgntScreenModel, + navigator: Navigator?, + formType: FormType + ) { val isFormValid by formValidator.isValid val users by remember { mutableStateOf?>(screenModel.fetchUsers()) } var selectedItem by remember { mutableStateOf?>(null) } - val cardBank = formValidator.getField(CreditCardFormFieldName.CARD_NAME) val cardOwner = formValidator.getField(CreditCardFormFieldName.CARD_OWNER) val cardNumber = formValidator.getField(CreditCardFormFieldName.CARD_NUMBER) @@ -105,6 +115,12 @@ class CreditCardForm : Screen { val expiry = formValidator.getField(CreditCardFormFieldName.CARD_EXPIRY) val notes = formValidator.getField(CreditCardFormFieldName.CARD_NOTES) + users?.find { + it.id.value.toString() == cardOwner?.value?.value + }?.let { + selectedItem = DropdownItem(it, it.userName) + } + LaunchedEffect(selectedItem) { selectedItem?.let { cardOwner?.value?.value = it.id.toString() @@ -114,32 +130,33 @@ class CreditCardForm : Screen { Column( modifier = Modifier.fillMaxSize() - .background(secondary) + .background(secondary) ) { Row( modifier = Modifier.weight(1f) - .fillMaxSize(), + .fillMaxSize(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Header( creditCardButtonShown = false, - notesButtonShown = true + notesButtonShown = (formType == FormType.CREATION), + title = if (formType == FormType.CREATION) "Create Credit Card" else "Update Credit Card" ) } Row( modifier = Modifier.weight(7.5f) - .background(primary) - .fillMaxSize(), + .background(primary) + .fillMaxSize(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { Column( modifier = Modifier.background(primary) - .padding(PaddingValues(end = 20.dp)), + .padding(PaddingValues(end = 20.dp)), horizontalAlignment = Alignment.Start, verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterVertically) ) { @@ -256,7 +273,7 @@ class CreditCardForm : Screen { Column(modifier = Modifier.height(80.dp)) { FormTextField( value = - expiry?.value?.value ?: "", + expiry?.value?.value ?: "", onValueChange = { newValue -> expiry?.value?.value = newValue formValidator.validateField(CreditCardFormFieldName.CARD_EXPIRY) @@ -305,13 +322,21 @@ class CreditCardForm : Screen { Row( modifier = Modifier.weight(1.5f) - .fillMaxSize() - .background(tertiary), + .fillMaxSize() + .background(tertiary), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(30.dp, Alignment.CenterHorizontally) ) { Footer( - { screenModel.saveCreditCard(toCreditCardDto(formValidator, screenModel.getAuthenticatedUser(), selectedItem?.id!!)) }, + { + screenModel.saveCreditCard( + toCreditCardDto( + formValidator, + screenModel.getAuthenticatedUser(), + selectedItem?.id!! + ) + ) + }, { navigator?.popUntil { screen: Screen -> screen.key == SecVaultScreen().key } }, isFormValid ) diff --git a/src/main/kotlin/ui/components/forms/passwordmgnt/NoteForm.kt b/src/main/kotlin/ui/components/forms/passwordmgnt/NoteForm.kt index 9ab0bef..67a62ad 100644 --- a/src/main/kotlin/ui/components/forms/passwordmgnt/NoteForm.kt +++ b/src/main/kotlin/ui/components/forms/passwordmgnt/NoteForm.kt @@ -62,7 +62,8 @@ class NoteForm : Screen { ) { Header( creditCardButtonShown = true, - notesButtonShown = false + notesButtonShown = false, + "" ) } diff --git a/src/main/kotlin/ui/components/forms/passwordmgnt/PasswordForm.kt b/src/main/kotlin/ui/components/forms/passwordmgnt/PasswordForm.kt index 5d87c51..5a67d05 100644 --- a/src/main/kotlin/ui/components/forms/passwordmgnt/PasswordForm.kt +++ b/src/main/kotlin/ui/components/forms/passwordmgnt/PasswordForm.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import core.form.validation.FormValidator +import core.models.FormType import core.models.dto.PasswordDto import ui.components.FormTextField import ui.components.MultiSelectDropdown @@ -32,7 +33,8 @@ fun PasswordForm( screenModel: PasswordMgntScreenModel, isFormValid: Boolean, onSaveClick: (PasswordDto) -> Unit, - onCancelClick: () -> Unit + onCancelClick: () -> Unit, + formType: FormType ) { val userName = formValidator.getField(PasswordFormFieldName.USERNAME) @@ -45,33 +47,34 @@ fun PasswordForm( Column( modifier = Modifier.fillMaxSize() - .background(secondary) + .background(secondary) ) { Row( modifier = Modifier.weight(1f) - .fillMaxSize(), + .fillMaxSize(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Header( - creditCardButtonShown = true, - notesButtonShown = true + creditCardButtonShown = (formType == FormType.CREATION), + notesButtonShown = (formType == FormType.CREATION), + title = if (formType == FormType.CREATION) "Create Password" else "Update Password", ) } Row( modifier = Modifier.weight(7.5f) - .background(primary) - .fillMaxSize(), + .background(primary) + .fillMaxSize(), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { Column( modifier = Modifier.background(primary) - .padding(PaddingValues(end = 20.dp)), + .padding(PaddingValues(end = 20.dp)), horizontalAlignment = Alignment.Start, verticalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterVertically) ) { @@ -237,8 +240,8 @@ fun PasswordForm( Row( modifier = Modifier.weight(1.5f) - .fillMaxSize() - .background(tertiary), + .fillMaxSize() + .background(tertiary), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(30.dp, Alignment.CenterHorizontally) ) { diff --git a/src/main/kotlin/ui/components/forms/passwordmgnt/PasswordMgntWrapper.kt b/src/main/kotlin/ui/components/forms/passwordmgnt/PasswordMgntWrapper.kt index 4ed473f..84cc8e8 100644 --- a/src/main/kotlin/ui/components/forms/passwordmgnt/PasswordMgntWrapper.kt +++ b/src/main/kotlin/ui/components/forms/passwordmgnt/PasswordMgntWrapper.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import cafe.adriel.voyager.navigator.LocalNavigator +import core.models.FormType.CREATION import ui.components.OutlineTextButton import ui.theme.Font import ui.theme.primary @@ -21,14 +22,15 @@ import ui.theme.secondary @Composable fun Header( creditCardButtonShown: Boolean, - notesButtonShown: Boolean + notesButtonShown: Boolean, + title: String ) { val navigator = LocalNavigator.current Row { Spacer(modifier = Modifier.width(25.dp)) Text( - text = "Create a new password", + text = title, color = Color.White, fontFamily = Font.RussoOne, fontWeight = FontWeight.Normal, @@ -45,7 +47,7 @@ fun Header( cornerSize = 4.dp, fontSize = 12.sp, text = "Credit Card", - onClick = { navigator?.push(CreditCardForm()) } + onClick = { navigator?.push(CreditCardForm(null, CREATION)) } ) } diff --git a/src/main/kotlin/ui/components/secvault/passwordinfo/PasswordInfoHeader.kt b/src/main/kotlin/ui/components/secvault/passwordinfo/PasswordInfoHeader.kt index b19a3f1..82cd5ba 100644 --- a/src/main/kotlin/ui/components/secvault/passwordinfo/PasswordInfoHeader.kt +++ b/src/main/kotlin/ui/components/secvault/passwordinfo/PasswordInfoHeader.kt @@ -20,7 +20,10 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import cafe.adriel.voyager.navigator.LocalNavigator -import ui.screens.LoginScreen +import core.models.DefaultMenuItem +import core.models.FormType.MODIFIATION +import ui.components.forms.passwordmgnt.CreditCardForm +import ui.screens.PasswordMgntScreen import ui.theme.Font import ui.theme.PasswordColors import viewmodel.SecVaultScreenModel @@ -117,7 +120,12 @@ fun PasswordInfoHeader(screenModel: SecVaultScreenModel) { val navigator = LocalNavigator.current OutlinedButton( - onClick = { navigator?.push(LoginScreen()) }, + onClick = { when(selectedMenu) { + DefaultMenuItem.PASSWORDS -> {navigator?.push(PasswordMgntScreen(selectedCredential.password, MODIFIATION))} + DefaultMenuItem.CREDIT_CARD -> {navigator?.push(CreditCardForm(selectedCredential.creditCard, MODIFIATION))} + DefaultMenuItem.NOTES -> TODO() + } }, + enabled = selectedCredential.isSelected(), modifier = Modifier.size(height = 28.dp, width = 62.dp) .hoverable(interactionSource), shape = RoundedCornerShape(size = 4.dp), @@ -125,6 +133,8 @@ fun PasswordInfoHeader(screenModel: SecVaultScreenModel) { border = BorderStroke(2.dp, color = Color.White), colors = ButtonDefaults.outlinedButtonColors( containerColor = if (isHovered) Color.White else Color.Transparent, + disabledContentColor = Color.White, + disabledContainerColor = if (isHovered) Color.White else Color.Transparent, ) ) diff --git a/src/main/kotlin/ui/components/secvault/passwordlayout/PasswordFilterHeader.kt b/src/main/kotlin/ui/components/secvault/passwordlayout/PasswordFilterHeader.kt index 1bfa173..b30f66b 100644 --- a/src/main/kotlin/ui/components/secvault/passwordlayout/PasswordFilterHeader.kt +++ b/src/main/kotlin/ui/components/secvault/passwordlayout/PasswordFilterHeader.kt @@ -17,6 +17,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import cafe.adriel.voyager.navigator.LocalNavigator +import core.models.FormType.CREATION import ui.components.RoundedFilledTextField import ui.screens.PasswordMgntScreen import ui.theme.Font @@ -59,7 +60,7 @@ fun PasswordFilterHeader(screenModel: SecVaultScreenModel) { ) { FilledIconButton( shape = IconButtonDefaults.filledShape, - onClick = {navigator?.push(PasswordMgntScreen())}, + onClick = {navigator?.push(PasswordMgntScreen(null, CREATION))}, enabled = true, modifier = Modifier.height(36.dp).width(36.dp), colors = IconButtonColors( diff --git a/src/main/kotlin/ui/screens/PasswordMgntScreen.kt b/src/main/kotlin/ui/screens/PasswordMgntScreen.kt index 1d0de14..62e9db8 100644 --- a/src/main/kotlin/ui/screens/PasswordMgntScreen.kt +++ b/src/main/kotlin/ui/screens/PasswordMgntScreen.kt @@ -8,9 +8,11 @@ import cafe.adriel.voyager.navigator.LocalNavigator import com.dokar.sonner.ToastType import com.dokar.sonner.Toaster import com.dokar.sonner.rememberToasterState +import core.models.FormType import core.models.UiState import core.models.dto.PasswordDto import kotlinx.coroutines.delay +import repository.password.Password import ui.components.LoadingScreen import ui.components.forms.passwordmgnt.PasswordForm import ui.theme.tertiary @@ -18,12 +20,15 @@ import ui.validators.passwordFormValidator import viewmodel.PasswordMgntScreenModel import kotlin.time.Duration.Companion.seconds -class PasswordMgntScreen : Screen { +class PasswordMgntScreen(password: Password?, formType: FormType) : Screen { + + private val _password = password + private val _formType = formType @Composable override fun Content() { - val formValidator = remember { passwordFormValidator() } + val formValidator = remember { passwordFormValidator(_password) } val screenModel = koinScreenModel() val passwordState by screenModel.passwordState.collectAsState() val navigator = LocalNavigator.current @@ -43,7 +48,8 @@ class PasswordMgntScreen : Screen { screenModel, isFormValid, onSaveClick = { password: PasswordDto -> screenModel.savePassword(password) }, - onCancelClick = { navigator?.pop() } + onCancelClick = { navigator?.pop() }, + _formType ) when (val state = passwordState) { diff --git a/src/main/kotlin/ui/validators/CreditCardFormValidator.kt b/src/main/kotlin/ui/validators/CreditCardFormValidator.kt index 0bcc3e0..7f358ea 100644 --- a/src/main/kotlin/ui/validators/CreditCardFormValidator.kt +++ b/src/main/kotlin/ui/validators/CreditCardFormValidator.kt @@ -1,60 +1,62 @@ package ui.validators +import androidx.compose.runtime.mutableStateOf import core.form.FormField import core.form.FormFieldName import core.form.validation.* import core.models.dto.CreditCardDto -import core.models.dto.PasswordDto +import repository.creditcard.CreditCard import repository.user.User -fun creditCardFormValidator(): FormValidator { +fun creditCardFormValidator(creditCard: CreditCard?): FormValidator { return FormValidator() - .addField( - CreditCardFormFieldName.CARD_NAME, FormField( - validator = Validator().addRule(notNullRule(CreditCardFormFieldName.CARD_NAME.fieldName)) + .addField( + CreditCardFormFieldName.CARD_NAME, FormField( + validator = Validator().addRule(notNullRule(CreditCardFormFieldName.CARD_NAME.fieldName)), + value = mutableStateOf(creditCard?.name ?: "") + ) ) - ) - .addField( - CreditCardFormFieldName.CARD_OWNER, FormField( - validator = Validator().addRule(notNullRule(CreditCardFormFieldName.CARD_OWNER.fieldName)) + .addField( + CreditCardFormFieldName.CARD_OWNER, FormField( + validator = Validator().addRule(notNullRule(CreditCardFormFieldName.CARD_OWNER.fieldName)), + value = mutableStateOf(creditCard?.owner?.id?.value?.toString() ?: "") + ) ) - ) - .addField( - CreditCardFormFieldName.CARD_NUMBER, FormField( - validator = Validator().addRule(creditCardRule) - .addRule(notNullRule(CreditCardFormFieldName.CARD_NUMBER.fieldName)) + .addField( + CreditCardFormFieldName.CARD_NUMBER, FormField( + validator = Validator().addRule(creditCardRule) + .addRule(notNullRule(CreditCardFormFieldName.CARD_NUMBER.fieldName)), + value = mutableStateOf(creditCard?.number ?: "") + ) ) - ) - .addField( - CreditCardFormFieldName.CARD_NUMBER, FormField( - validator = Validator().addRule(creditCardRule) - .addRule(notNullRule(CreditCardFormFieldName.CARD_NUMBER.fieldName)) + .addField( + CreditCardFormFieldName.CARD_PIN, FormField( + validator = Validator().addRule(creditCardPinRule) + .addRule(notNullRule(CreditCardFormFieldName.CARD_PIN.fieldName)), + value = mutableStateOf(creditCard?.pin?.toString() ?: "") + ) ) - ) - .addField( - CreditCardFormFieldName.CARD_PIN, FormField( - validator = Validator().addRule(creditCardPinRule) - .addRule(notNullRule(CreditCardFormFieldName.CARD_PIN.fieldName)) + .addField( + CreditCardFormFieldName.CARD_CVC, FormField( + validator = Validator().addRule(creditCardPinRule) + .addRule(notNullRule(CreditCardFormFieldName.CARD_CVC.fieldName)), + value = mutableStateOf(creditCard?.cvc?.toString() ?: "") + ) ) - ) - .addField( - CreditCardFormFieldName.CARD_CVC, FormField( - validator = Validator().addRule(creditCardPinRule) - .addRule(notNullRule(CreditCardFormFieldName.CARD_CVC.fieldName)) + .addField( + CreditCardFormFieldName.CARD_EXPIRY, FormField( + validator = Validator().addRule(notNullRule(CreditCardFormFieldName.CARD_EXPIRY.fieldName)) + .addRule(creditCardExpiryDateRule), + value = mutableStateOf(creditCard?.expiryDate ?: "") + ) ) - ) - .addField( - CreditCardFormFieldName.CARD_EXPIRY, FormField( - validator = Validator().addRule(notNullRule(CreditCardFormFieldName.CARD_EXPIRY.fieldName)) - .addRule(creditCardExpiryDateRule) + .addField( + CreditCardFormFieldName.CARD_NOTES, FormField( + validator = Validator(), + value = mutableStateOf(creditCard?.notes ?: "") + ) ) - ) - .addField( - CreditCardFormFieldName.CARD_NOTES, FormField( - validator = Validator() - ) - ) - .validateAllFields() + .validateAllFields() } fun toCreditCardDto(formValidator: FormValidator, user: User, owner: User): CreditCardDto { diff --git a/src/main/kotlin/ui/validators/PasswordFormValidator.kt b/src/main/kotlin/ui/validators/PasswordFormValidator.kt index 94cc58f..4dcb2dc 100644 --- a/src/main/kotlin/ui/validators/PasswordFormValidator.kt +++ b/src/main/kotlin/ui/validators/PasswordFormValidator.kt @@ -1,36 +1,42 @@ package ui.validators +import androidx.compose.runtime.mutableStateOf import core.form.FormField import core.form.FormFieldName import core.form.validation.* import core.models.dto.PasswordDto +import repository.password.Password import repository.user.User -fun passwordFormValidator(): FormValidator { +fun passwordFormValidator(password: Password?): FormValidator { val validator = FormValidator() .addField( PasswordFormFieldName.USERNAME, FormField( - validator = Validator() + validator = Validator(), + value = mutableStateOf(password?.username ?: "") ) ) .addField( PasswordFormFieldName.EMAIL, FormField( validator = Validator() - .addRule(emailIfNotNullRule) + .addRule(emailIfNotNullRule), + value = mutableStateOf(password?.email ?: "") ) ) .addField( PasswordFormFieldName.PASSWORD, FormField( validator = Validator() .addRule(notNullRule(PasswordFormFieldName.PASSWORD.fieldName)) - .addRule(passwordRule) + .addRule(passwordRule), + value = mutableStateOf(password?.password ?: "") ) ) .addField( PasswordFormFieldName.NAME, FormField( validator = Validator() .addRule(notNullRule(PasswordFormFieldName.NAME.fieldName)) - .addRule(lengthRule(PasswordFormFieldName.NAME.fieldName, 1)) + .addRule(lengthRule(PasswordFormFieldName.NAME.fieldName, 1)), + value = mutableStateOf(password?.name ?: "") ) ) .addField( @@ -38,13 +44,15 @@ fun passwordFormValidator(): FormValidator { validator = Validator() .addRule(notNullRule(PasswordFormFieldName.WEBSITE_URL.fieldName)) .addRule(lengthRule(PasswordFormFieldName.WEBSITE_URL.fieldName, 1)) - .addRule(urlRule) + .addRule(urlRule), + value = mutableStateOf(password?.website ?: "") ) ) .addField( PasswordFormFieldName.WEBSITE_ICON_URL, FormField( validator = Validator() - .addRule(urlRule) + .addRule(urlRule), + value = mutableStateOf(password?.websiteIcon ?: "") ) )