Skip to content

Commit

Permalink
refactoring change-password dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
softartdev committed Nov 3, 2024
1 parent 92a81db commit b6f2cbd
Show file tree
Hide file tree
Showing 14 changed files with 405 additions and 238 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,154 +2,88 @@ package com.softartdev.notedelight.ui.dialog.security

import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.softartdev.notedelight.shared.presentation.settings.security.change.ChangeResult
import com.softartdev.notedelight.shared.presentation.settings.security.change.ChangeViewModel
import com.softartdev.notedelight.ui.PasswordField
import com.softartdev.notedelight.ui.dialog.PreviewDialog
import kotlinx.coroutines.launch
import notedelight.shared_compose_ui.generated.resources.Res
import notedelight.shared_compose_ui.generated.resources.cancel
import notedelight.shared_compose_ui.generated.resources.dialog_title_change_password
import notedelight.shared_compose_ui.generated.resources.empty_password
import notedelight.shared_compose_ui.generated.resources.enter_new_password
import notedelight.shared_compose_ui.generated.resources.enter_old_password
import notedelight.shared_compose_ui.generated.resources.error_title
import notedelight.shared_compose_ui.generated.resources.incorrect_password
import notedelight.shared_compose_ui.generated.resources.passwords_do_not_match
import notedelight.shared_compose_ui.generated.resources.repeat_new_password
import notedelight.shared_compose_ui.generated.resources.yes
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.getString
import org.jetbrains.compose.resources.stringResource

@Composable
fun ChangePasswordDialog(
changeViewModel: ChangeViewModel,
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }
) {
val changeResultState: State<ChangeResult> = changeViewModel.resultStateFlow.collectAsState()
var oldLabelResource by remember { mutableStateOf(Res.string.enter_old_password) }
var oldError by remember { mutableStateOf(false) }
val oldPasswordState: MutableState<String> = remember { mutableStateOf("") }
var newLabelResource by remember { mutableStateOf(Res.string.enter_new_password) }
var newError by remember { mutableStateOf(false) }
val newPasswordState: MutableState<String> = remember { mutableStateOf("") }
var repeatLabelResource by remember { mutableStateOf(Res.string.repeat_new_password) }
var repeatError by remember { mutableStateOf(false) }
val repeatPasswordState: MutableState<String> = remember { mutableStateOf("") }
val coroutineScope = rememberCoroutineScope()
when (val changeResult: ChangeResult = changeResultState.value) {
is ChangeResult.InitState, is ChangeResult.Loading -> Unit
is ChangeResult.OldEmptyPasswordError -> {
oldLabelResource = Res.string.empty_password
oldError = true
}
is ChangeResult.NewEmptyPasswordError -> {
newLabelResource = Res.string.empty_password
newError = true
}
is ChangeResult.PasswordsNoMatchError -> {
repeatLabelResource = Res.string.passwords_do_not_match
repeatError = true
}
is ChangeResult.IncorrectPasswordError -> {
oldLabelResource = Res.string.incorrect_password
oldError = true
}
is ChangeResult.Error -> coroutineScope.launch {
snackbarHostState.showSnackbar(
message = changeResult.message ?: getString(Res.string.error_title)
)
val result: ChangeResult by changeViewModel.stateFlow.collectAsState()

LaunchedEffect(key1 = changeViewModel, key2 = result, key3 = result.snackBarMessageType) {
result.snackBarMessageType?.let { msg: String ->
snackbarHostState.showSnackbar(msg)
result.disposeOneTimeEvents()
}
}
ShowChangePasswordDialog(
showLoaing = changeResultState.value is ChangeResult.Loading,
oldLabelResource = oldLabelResource,
oldError = oldError,
oldPasswordState = oldPasswordState,
newLabelResource = newLabelResource,
newError = newError,
newPasswordState = newPasswordState,
repeatLabelResource = repeatLabelResource,
repeatError = repeatError,
repeatPasswordState = repeatPasswordState,
snackbarHostState = snackbarHostState,
dismissDialog = changeViewModel::navigateUp,
) {
changeViewModel.checkChange(
oldPassword = oldPasswordState.value,
newPassword = newPasswordState.value,
repeatNewPassword = repeatPasswordState.value
)
}
ShowChangePasswordDialog(result)
}

@Composable
fun ShowChangePasswordDialog(
showLoaing: Boolean = true,
oldLabelResource: StringResource = Res.string.enter_old_password,
oldError: Boolean = false,
oldPasswordState: MutableState<String> = mutableStateOf("old password"),
newLabelResource: StringResource = Res.string.enter_new_password,
newError: Boolean = false,
newPasswordState: MutableState<String> = mutableStateOf("new password"),
repeatLabelResource: StringResource = Res.string.repeat_new_password,
repeatError: Boolean = true,
repeatPasswordState: MutableState<String> = mutableStateOf("repeat new password"),
snackbarHostState: SnackbarHostState = SnackbarHostState(),
dismissDialog: () -> Unit = {},
onChangeClick: () -> Unit = {},
) = AlertDialog(
fun ShowChangePasswordDialog(result: ChangeResult) = AlertDialog(
title = { Text(text = stringResource(Res.string.dialog_title_change_password)) },
text = {
Column {
if (showLoaing) LinearProgressIndicator()
if (result.loading) LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
PasswordField(
passwordState = oldPasswordState,
label = stringResource(oldLabelResource),
isError = oldError,
contentDescription = stringResource(Res.string.enter_old_password),
password = result.oldPassword,
onPasswordChange = result.onEditOldPassword,
label = result.oldPasswordFieldLabel.resString,
isError = result.isOldPasswordError,
contentDescription = stringResource(Res.string.enter_old_password)
)
Spacer(modifier = Modifier.height(8.dp))
PasswordField(
passwordState = newPasswordState,
label = stringResource(newLabelResource),
isError = newError,
contentDescription = stringResource(Res.string.enter_new_password),
password = result.newPassword,
onPasswordChange = result.onEditNewPassword,
label = result.newPasswordFieldLabel.resString,
isError = result.isNewPasswordError,
contentDescription = stringResource(Res.string.enter_new_password)
)
Spacer(modifier = Modifier.height(8.dp))
PasswordField(
passwordState = repeatPasswordState,
label = stringResource(repeatLabelResource),
isError = repeatError,
contentDescription = stringResource(Res.string.repeat_new_password),
)
SnackbarHost(
hostState = snackbarHostState,
modifier = Modifier.align(Alignment.CenterHorizontally)
password = result.repeatNewPassword,
onPasswordChange = result.onEditRepeatPassword,
label = result.repeatPasswordFieldLabel.resString,
isError = result.isRepeatPasswordError,
contentDescription = stringResource(Res.string.repeat_new_password)
)
}
},
confirmButton = { Button(onClick = onChangeClick) { Text(stringResource(Res.string.yes)) } },
dismissButton = { Button(onClick = dismissDialog) { Text(stringResource(Res.string.cancel)) } },
onDismissRequest = dismissDialog,
confirmButton = { Button(onClick = result.onChangeClick) { Text(stringResource(Res.string.yes)) } },
dismissButton = { Button(onClick = result.onCancel) { Text(stringResource(Res.string.cancel)) } },
onDismissRequest = result.onCancel
)

@Preview
@Composable
fun PreviewChangePasswordDialog() = PreviewDialog { ShowChangePasswordDialog() }
fun PreviewChangePasswordDialog() = PreviewDialog {
ShowChangePasswordDialog(ChangeResult())
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ import notedelight.shared_compose_ui.generated.resources.Res
import notedelight.shared_compose_ui.generated.resources.cancel
import notedelight.shared_compose_ui.generated.resources.confirm_password
import notedelight.shared_compose_ui.generated.resources.dialog_title_conform_password
import notedelight.shared_compose_ui.generated.resources.empty_password
import notedelight.shared_compose_ui.generated.resources.enter_password
import notedelight.shared_compose_ui.generated.resources.passwords_do_not_match
import notedelight.shared_compose_ui.generated.resources.yes
import org.jetbrains.compose.resources.stringResource

Expand Down Expand Up @@ -57,13 +55,7 @@ fun ShowConfirmPasswordDialog(result: ConfirmResult) = AlertDialog(
PasswordField(
password = result.password,
onPasswordChange = result.onEditPassword,
label = stringResource(
when (result.passwordLabelType) {
ConfirmResult.LabelType.ENTER -> Res.string.enter_password
ConfirmResult.LabelType.EMPTY -> Res.string.empty_password
ConfirmResult.LabelType.NO_MATCH -> Res.string.passwords_do_not_match
}
),
label = result.passwordFieldLabel.resString,
isError = result.isPasswordError,
contentDescription = stringResource(Res.string.enter_password)
)
Expand All @@ -73,13 +65,7 @@ fun ShowConfirmPasswordDialog(result: ConfirmResult) = AlertDialog(
PasswordField(
password = result.repeatPassword,
onPasswordChange = result.onEditRepeatPassword,
label = stringResource(
when (result.repeatPasswordLabelType) {
ConfirmResult.LabelType.ENTER -> Res.string.confirm_password
ConfirmResult.LabelType.EMPTY -> Res.string.empty_password
ConfirmResult.LabelType.NO_MATCH -> Res.string.passwords_do_not_match
}
),
label = result.repeatPasswordFieldLabel.resString,
isError = result.isRepeatPasswordError,
contentDescription = stringResource(Res.string.confirm_password)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@ import com.softartdev.notedelight.ui.dialog.PreviewDialog
import notedelight.shared_compose_ui.generated.resources.Res
import notedelight.shared_compose_ui.generated.resources.cancel
import notedelight.shared_compose_ui.generated.resources.dialog_title_enter_password
import notedelight.shared_compose_ui.generated.resources.empty_password
import notedelight.shared_compose_ui.generated.resources.enter_password
import notedelight.shared_compose_ui.generated.resources.incorrect_password
import notedelight.shared_compose_ui.generated.resources.yes
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.stringResource

@Composable
Expand All @@ -45,22 +42,15 @@ fun EnterPasswordDialog(
}

@Composable
fun ShowEnterPasswordDialog(
result: EnterResult,
labelResource: StringResource = when (result.labelType) {
EnterResult.LabelType.ENTER -> Res.string.enter_password
EnterResult.LabelType.EMPTY -> Res.string.empty_password
EnterResult.LabelType.INCORRECT -> Res.string.incorrect_password
}
) = AlertDialog(
fun ShowEnterPasswordDialog(result: EnterResult) = AlertDialog(
title = { Text(text = stringResource(Res.string.dialog_title_enter_password)) },
text = {
Column {
if (result.loading) LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
PasswordField(
password = result.password,
onPasswordChange = result.onEditPassword,
label = stringResource(labelResource),
label = result.fieldLabel.resString,
isError = result.isError,
contentDescription = stringResource(Res.string.enter_password),
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.softartdev.notedelight.ui.dialog.security

import androidx.compose.runtime.Composable
import com.softartdev.notedelight.shared.presentation.settings.security.FieldLabel
import notedelight.shared_compose_ui.generated.resources.Res
import notedelight.shared_compose_ui.generated.resources.empty_password
import notedelight.shared_compose_ui.generated.resources.enter_password
import notedelight.shared_compose_ui.generated.resources.incorrect_password
import notedelight.shared_compose_ui.generated.resources.passwords_do_not_match
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.stringResource

val FieldLabel.resString: String
@Composable get() = stringResource(this.res)

private val FieldLabel.res: StringResource
get() = when (this) {
FieldLabel.ENTER -> Res.string.enter_password
FieldLabel.EMPTY -> Res.string.empty_password
FieldLabel.INCORRECT -> Res.string.incorrect_password
FieldLabel.NO_MATCH -> Res.string.passwords_do_not_match
}
Loading

0 comments on commit b6f2cbd

Please sign in to comment.