WIP: cambiar password
This commit is contained in:
parent
4bb6c57c38
commit
1be245cfa7
17
app/src/main/java/com/isolaatti/auth/domain/SignOutUC.kt
Normal file
17
app/src/main/java/com/isolaatti/auth/domain/SignOutUC.kt
Normal 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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,60 @@
|
|||||||
package com.isolaatti.settings.presentation
|
package com.isolaatti.settings.presentation
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -4,14 +4,22 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.widget.doOnTextChanged
|
import androidx.core.widget.doOnTextChanged
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.navigation.fragment.findNavController
|
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.databinding.FragmentSettingsChangePasswordBinding
|
||||||
import com.isolaatti.settings.presentation.ChangePasswordViewModel
|
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
|
lateinit var viewBinding: FragmentSettingsChangePasswordBinding
|
||||||
|
|
||||||
private val viewModel: ChangePasswordViewModel by viewModels()
|
private val viewModel: ChangePasswordViewModel by viewModels()
|
||||||
@ -38,6 +46,7 @@ class ChangePasswordFragment : Fragment() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
setupListeners()
|
setupListeners()
|
||||||
|
setupObservers()
|
||||||
|
|
||||||
viewBinding.continueCurrentPassword.isEnabled = !viewBinding.currentPasswordTextInput.editText?.text.isNullOrBlank()
|
viewBinding.continueCurrentPassword.isEnabled = !viewBinding.currentPasswordTextInput.editText?.text.isNullOrBlank()
|
||||||
}
|
}
|
||||||
@ -50,16 +59,76 @@ class ChangePasswordFragment : Fragment() {
|
|||||||
viewBinding.prevNewPasswordButton.setOnClickListener(clickListener)
|
viewBinding.prevNewPasswordButton.setOnClickListener(clickListener)
|
||||||
|
|
||||||
viewBinding.currentPasswordTextInput.editText?.doOnTextChanged { text, start, before, count ->
|
viewBinding.currentPasswordTextInput.editText?.doOnTextChanged { text, start, before, count ->
|
||||||
|
viewModel.oldPassword = text.toString()
|
||||||
viewBinding.continueCurrentPassword.isEnabled = !text.isNullOrBlank()
|
viewBinding.continueCurrentPassword.isEnabled = !text.isNullOrBlank()
|
||||||
}
|
}
|
||||||
|
|
||||||
viewBinding.newPasswordInputText.editText?.doOnTextChanged { text, start, before, count ->
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -108,45 +108,51 @@
|
|||||||
android:inputType="textPassword" />
|
android:inputType="textPassword" />
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</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
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/prev_new_password_button"
|
android:id="@+id/prev_new_password_button"
|
||||||
style="?attr/materialIconButtonFilledTonalStyle"
|
style="?attr/materialIconButtonFilledTonalStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:text="Previous"
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/previous"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/continue_new_password_button"
|
app:layout_constraintEnd_toStartOf="@+id/continue_new_password_button"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
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
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/continue_new_password_button"
|
android:id="@+id/continue_new_password_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:text="Continue"
|
android:text="@string/continuar"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintHorizontal_bias="0.5"
|
app:layout_constraintHorizontal_bias="0.5"
|
||||||
|
|||||||
@ -156,4 +156,10 @@
|
|||||||
<string name="delete_sessions">Delete sessions</string>
|
<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="delete_sessions_conf_dialog_message">The selected sessions will become invalid, sign out those devices.</string>
|
||||||
<string name="current">Current</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>
|
</resources>
|
||||||
Loading…
x
Reference in New Issue
Block a user