WIP: cambiar password

This commit is contained in:
erik-everardo 2024-01-22 00:09:06 -06:00
parent 4bb6c57c38
commit 1be245cfa7
5 changed files with 178 additions and 26 deletions

View File

@ -0,0 +1,17 @@
package com.isolaatti.auth.domain
import android.content.Context
import com.isolaatti.auth.data.local.TokenStorage
import com.isolaatti.settings.domain.AccountSettingsRepository
import dagger.hilt.android.qualifiers.ActivityContext
import javax.inject.Inject
class SignOutUC @Inject constructor(
@ActivityContext private val context: Context,
private val tokenStorage: TokenStorage,
private val accountSettingsRepository: AccountSettingsRepository
) {
operator fun invoke() {
}
}

View File

@ -1,6 +1,60 @@
package com.isolaatti.settings.presentation
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.isolaatti.settings.data.remote.ChangePasswordResponseDto
import com.isolaatti.settings.domain.AccountSettingsRepository
import com.isolaatti.utils.Resource
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject
class ChangePasswordViewModel : ViewModel() {
@HiltViewModel
class ChangePasswordViewModel @Inject constructor(private val accountSettingsRepository: AccountSettingsRepository) : ViewModel() {
var oldPassword = ""
var newPassword = ""
set(value) {
field = value
validatePassword(value)
}
var signOut = false
var signOutCurrent = true
val newPasswordIsValid: MutableLiveData<Boolean> = MutableLiveData()
private val passwordRules = listOf(
"[a-z]",
"[A-Z]",
"[0-9]",
"[!@#\$%^&*\\(\\)_\\+\\-\\={}<>,\\.\\|\"\"'~`:;\\\\?\\/\\[\\]]"
)
private fun validatePassword(newPassword: String) {
var count = 0
for(exp in passwordRules) {
val matches = exp.toRegex().containsMatchIn(newPassword)
Log.d("ChangePasswordViewModel", "$exp matches: $matches")
if(matches) {
count++
}
}
newPasswordIsValid.value = count > 3 && newPassword.length >= 8
}
val passwordChangeResource: MutableLiveData<Resource<ChangePasswordResponseDto>> = MutableLiveData()
fun changePassword() {
viewModelScope.launch {
accountSettingsRepository.changePassword(oldPassword, newPassword, signOut, signOutCurrent).onEach {
passwordChangeResource.postValue(it)
}.flowOn(Dispatchers.IO).launchIn(this)
}
}
}

View File

@ -4,14 +4,22 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.isolaatti.R
import com.isolaatti.auth.domain.SignOutUC
import com.isolaatti.databinding.FragmentSettingsChangePasswordBinding
import com.isolaatti.settings.presentation.ChangePasswordViewModel
import com.isolaatti.utils.Resource
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
class ChangePasswordFragment : Fragment() {
@AndroidEntryPoint
class ChangePasswordFragment @Inject constructor(private val signOutUC: SignOutUC) : Fragment() {
lateinit var viewBinding: FragmentSettingsChangePasswordBinding
private val viewModel: ChangePasswordViewModel by viewModels()
@ -38,6 +46,7 @@ class ChangePasswordFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
setupListeners()
setupObservers()
viewBinding.continueCurrentPassword.isEnabled = !viewBinding.currentPasswordTextInput.editText?.text.isNullOrBlank()
}
@ -50,16 +59,76 @@ class ChangePasswordFragment : Fragment() {
viewBinding.prevNewPasswordButton.setOnClickListener(clickListener)
viewBinding.currentPasswordTextInput.editText?.doOnTextChanged { text, start, before, count ->
viewModel.oldPassword = text.toString()
viewBinding.continueCurrentPassword.isEnabled = !text.isNullOrBlank()
}
viewBinding.newPasswordInputText.editText?.doOnTextChanged { text, start, before, count ->
viewModel.newPassword = text.toString()
}
viewBinding.newPasswordInputTextConfirm.editText?.doOnTextChanged { text, start, before, count ->
viewBinding.signOutAll.setOnCheckedChangeListener { buttonView, isChecked ->
viewBinding.signOutCurrent.isEnabled = isChecked
viewModel.signOutCurrent = isChecked
if(!isChecked){
viewBinding.signOutCurrent.isChecked = false
}
}
viewBinding.signOutCurrent.setOnCheckedChangeListener { buttonView, isChecked ->
viewModel.signOutCurrent = isChecked
}
viewBinding.continueNewPasswordButton.setOnClickListener {
viewModel.changePassword()
}
}
private fun lockControls(lock: Boolean) {
viewBinding.prevNewPasswordButton.isEnabled = !lock
viewBinding.continueNewPasswordButton.isEnabled = !lock
viewBinding.newPasswordInputText.isEnabled = !lock
}
private var loadingDialog: AlertDialog? = null
private fun showLoadingDialog() {
loadingDialog = MaterialAlertDialogBuilder(requireContext()).setMessage(R.string.changing_password).setCancelable(false).show()
}
private fun signOut() {
signOutUC()
}
private fun setupObservers() {
viewModel.newPasswordIsValid.observe(viewLifecycleOwner) { valid ->
viewBinding.continueNewPasswordButton.isEnabled = valid
viewBinding.newPasswordInputText.error = if(valid) null else getString(R.string.password_req)
}
viewModel.passwordChangeResource.observe(viewLifecycleOwner) {
when(it) {
is Resource.Loading -> {
lockControls(true)
showLoadingDialog()
}
is Resource.Error -> {
lockControls(false)
loadingDialog?.dismiss()
loadingDialog = null
}
is Resource.Success -> {
loadingDialog?.dismiss()
loadingDialog = null
if(viewModel.signOutCurrent) {
signOut()
} else {
findNavController().popBackStack()
}
}
}
}
}
}

View File

@ -108,45 +108,51 @@
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/new_password_input_text_confirm"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:hint="Confirm your new password"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/new_password_input_text"
app:passwordToggleEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/prev_new_password_button"
style="?attr/materialIconButtonFilledTonalStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:text="Previous"
android:layout_marginTop="16dp"
android:text="@string/previous"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/continue_new_password_button"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/new_password_input_text_confirm" />
app:layout_constraintTop_toBottomOf="@+id/sign_out_current" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sign_out_all"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/sign_out_all_sessions"
android:layout_marginTop="24dp"
android:layout_marginHorizontal="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/new_password_input_text" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/sign_out_current"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/sign_out_this_device"
android:layout_marginHorizontal="16dp"
android:enabled="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/sign_out_all" />
<com.google.android.material.button.MaterialButton
android:id="@+id/continue_new_password_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="Continue"
android:text="@string/continuar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"

View File

@ -156,4 +156,10 @@
<string name="delete_sessions">Delete sessions</string>
<string name="delete_sessions_conf_dialog_message">The selected sessions will become invalid, sign out those devices.</string>
<string name="current">Current</string>
<string name="sign_out_all_sessions">Sign out all sessions</string>
<string name="previous">Previous</string>
<string name="sign_out_this_device">Sign out this device</string>
<string name="continuar">Continue</string>
<string name="password_req">Password must contain at least 8 characters an have the following: 1-9, a-z, A-Z, special character.</string>
<string name="changing_password">Changing password...</string>
</resources>