From 40af691386b449e478c0841439e9939129fb6576 Mon Sep 17 00:00:00 2001 From: Taras Smakula <tarassmakula@gmail.com> Date: Thu, 21 Mar 2024 14:45:56 +0200 Subject: [PATCH] Implement select password on login --- .../uia/stages/password/PasswordDataSource.kt | 2 +- .../uia/stages/password/PasswordFragment.kt | 10 ++++-- .../uia/stages/password/PasswordViewModel.kt | 36 ++++++++++++++++++- .../src/main/res/layout/fragment_password.xml | 1 + .../futo/circles/core/view/LoadingButton.kt | 6 ++-- 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordDataSource.kt b/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordDataSource.kt index 9f78db94d..2e8adc523 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordDataSource.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordDataSource.kt @@ -55,7 +55,7 @@ class PasswordDataSource @Inject constructor( is Response.Error -> result } } - + private suspend fun processDirectPasswordStage(password: String): Response<Unit> { val result = createResult { MatrixInstanceProvider.matrix.authenticationService().getLoginWizard().login( diff --git a/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordFragment.kt b/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordFragment.kt index d446f5aba..33884332d 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordFragment.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordFragment.kt @@ -16,6 +16,7 @@ import org.futo.circles.auth.feature.uia.stages.password.confirmation.SetupPassw import org.futo.circles.core.base.fragment.HasLoadingState import org.futo.circles.core.base.fragment.ParentBackPressOwnerFragment import org.futo.circles.core.extensions.getText +import org.futo.circles.core.extensions.observeData import org.futo.circles.core.extensions.observeResponse import org.futo.circles.core.extensions.setIsVisible import org.futo.circles.core.extensions.showError @@ -33,6 +34,7 @@ class PasswordFragment : ParentBackPressOwnerFragment(R.layout.fragment_password super.onViewCreated(view, savedInstanceState) setupViews() setupObservers() + if (!isSignupMode()) viewModel.getCredentials(requireContext()) } override fun onResume() { @@ -73,14 +75,18 @@ class PasswordFragment : ParentBackPressOwnerFragment(R.layout.fragment_password private fun setupObservers() { viewModel.passwordResponseLiveData.observeResponse(this, error = { showError(getString(R.string.invalid_password)) }) + viewModel.passwordSelectedEventLiveData.observeData(this) { + startLoading(binding.btnLogin) + binding.etPassword.setText(it) + } } private fun onPasswordDataChanged() { val password = binding.tilPassword.getText() val repeat = binding.tilRepeatPassword.getText() binding.btnLogin.isEnabled = if (isSignupMode()) { - binding.vPasswordStrength.isPasswordStrong() && password == repeat && password.isNotEmpty() - } else password.isNotEmpty() + binding.vPasswordStrength.isPasswordStrong() && password == repeat && password.isNotEmpty() && !binding.btnLogin.isLoading + } else password.isNotEmpty() && !binding.btnLogin.isLoading } private fun showPasswordWarningIfNeeded() { diff --git a/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordViewModel.kt b/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordViewModel.kt index 015471921..febaa25ce 100644 --- a/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordViewModel.kt +++ b/auth/src/main/java/org/futo/circles/auth/feature/uia/stages/password/PasswordViewModel.kt @@ -1,10 +1,17 @@ package org.futo.circles.auth.feature.uia.stages.password +import android.content.Context +import androidx.credentials.CredentialManager +import androidx.credentials.GetCredentialRequest +import androidx.credentials.GetPasswordOption +import androidx.credentials.PasswordCredential import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import org.futo.circles.auth.feature.uia.UIADataSourceProvider import org.futo.circles.core.base.SingleEventLiveData import org.futo.circles.core.extensions.Response import org.futo.circles.core.extensions.launchBg +import org.matrix.android.sdk.api.extensions.tryOrNull import javax.inject.Inject @HiltViewModel @@ -14,13 +21,40 @@ class PasswordViewModel @Inject constructor( private var isPasswordWarningConfirmed: Boolean = false val passwordResponseLiveData = SingleEventLiveData<Response<Unit>>() + val passwordSelectedEventLiveData = SingleEventLiveData<String>() fun processPasswordStage(password: String) { + launchBg { handlePasswordRequest(password) } + } + + fun getCredentials(activityContext: Context) { launchBg { - passwordResponseLiveData.postValue(passwordDataSource.processPasswordStage(password)) + tryOrNull { + val credentialManager = CredentialManager.create(activityContext) + val userName = UIADataSourceProvider.getDataSourceOrThrow().userName + val request = GetCredentialRequest( + listOf(GetPasswordOption(allowedUserIds = setOf(userName))) + ) + + val result = credentialManager.getCredential( + context = activityContext, + request = request + ).credential + + if (result is PasswordCredential) { + val password = result.password + passwordSelectedEventLiveData.postValue(password) + handlePasswordRequest(password) + } + } } } + private suspend fun handlePasswordRequest(password: String) { + val result = passwordDataSource.processPasswordStage(password) + passwordResponseLiveData.postValue(result) + } + fun isPasswordWarningConfirmed() = isPasswordWarningConfirmed fun confirmPasswordWarning() { isPasswordWarningConfirmed = true diff --git a/auth/src/main/res/layout/fragment_password.xml b/auth/src/main/res/layout/fragment_password.xml index 638421e67..4b3e6e6c8 100644 --- a/auth/src/main/res/layout/fragment_password.xml +++ b/auth/src/main/res/layout/fragment_password.xml @@ -61,6 +61,7 @@ android:autofillHints="password" android:imeOptions="actionDone" android:inputType="textPassword" + android:isCredential="true" android:padding="8dp" /> <org.futo.circles.auth.view.PasswordStrengthView diff --git a/core/src/main/java/org/futo/circles/core/view/LoadingButton.kt b/core/src/main/java/org/futo/circles/core/view/LoadingButton.kt index 1ceec3f8b..0a9be1355 100644 --- a/core/src/main/java/org/futo/circles/core/view/LoadingButton.kt +++ b/core/src/main/java/org/futo/circles/core/view/LoadingButton.kt @@ -7,7 +7,6 @@ import android.util.TypedValue import android.view.LayoutInflater import android.view.View import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.view.doOnLayout import org.futo.circles.core.R import org.futo.circles.core.databinding.ViewLoadingButtonBinding import org.futo.circles.core.extensions.getAttributes @@ -31,7 +30,8 @@ class LoadingButton( ViewLoadingButtonBinding.inflate(LayoutInflater.from(context), this) private var buttonText: String = "" - private var isLoading: Boolean = false + var isLoading: Boolean = false + private set init { getAttributes(attrs, R.styleable.LoadingButton) { @@ -60,7 +60,7 @@ class LoadingButton( override fun onRestoreInstanceState(state: Parcelable?) { val loadingButtonState = state as? LoadingButtonState super.onRestoreInstanceState(loadingButtonState?.superSavedState ?: state) - doOnLayout { + post { setText(loadingButtonState?.text ?: "") setIsLoading(loadingButtonState?.isLoading ?: false) isEnabled = loadingButtonState?.isEnabled ?: true -- GitLab