Show inline password error on account reset failure

- Add showIncorrectPasswordError() in HabiticaAccountDialog to display a field-level error message
- Update resetAccount() in the fragment to dismiss the spinner on both outcomes and, on failure, keep the sheet open and call showIncorrectPasswordError("Incorrect password.") rather than closing the dialog
This commit is contained in:
Hafiz 2025-07-14 11:45:07 -05:00
parent 1411d49107
commit 6d3b2806ed
6 changed files with 42 additions and 11 deletions

View file

@ -395,7 +395,7 @@ interface ApiClient {
suspend fun reroll(): User?
suspend fun resetAccount(password: String): Void?
suspend fun resetAccount(password: String): Boolean
suspend fun deleteAccount(password: String): Void?

View file

@ -87,7 +87,7 @@ interface UserRepository : BaseRepository {
suspend fun updateLanguage(languageCode: String): User?
suspend fun resetAccount(password: String): User?
suspend fun resetAccount(password: String): Boolean?
suspend fun deleteAccount(password: String): Void?

View file

@ -97,6 +97,16 @@ class ApiClientImpl(
return null
}
private suspend fun <T> processWithIfSuccess(apiCall: suspend () -> HabitResponse<T>): Boolean {
try {
processResponse(apiCall())
return true
} catch (throwable: Throwable) {
accept(throwable)
return false
}
}
override var languageCode: String? = null
private var lastAPICallURL: String? = null
@ -994,10 +1004,10 @@ class ApiClientImpl(
override suspend fun reroll(): User? = process { apiService.reroll() }
override suspend fun resetAccount(password: String): Void? {
override suspend fun resetAccount(password: String): Boolean {
val updateObject = HashMap<String, String>()
updateObject["password"] = password
return process { apiService.resetAccount(updateObject) }
return processWithIfSuccess { apiService.resetAccount(updateObject) }
}
override suspend fun deleteAccount(password: String): Void? {

View file

@ -273,9 +273,13 @@ class UserRepositoryImpl(
return mergeWithExistingUser(user)
}
override suspend fun resetAccount(password: String): User? {
apiClient.resetAccount(password)
return retrieveUser(withTasks = true, forced = true)
override suspend fun resetAccount(password: String): Boolean {
val resetAccountSuccessful = apiClient.resetAccount(password)
if (resetAccountSuccessful) {
retrieveUser(withTasks = true, forced = true)
return true
}
return false
}
override suspend fun deleteAccount(password: String) = apiClient.deleteAccount(password)

View file

@ -52,7 +52,9 @@ import com.habitrpg.common.habitica.helpers.ExceptionHandler
import com.habitrpg.common.habitica.helpers.MainNavigationController
import com.habitrpg.common.habitica.helpers.launchCatching
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import retrofit2.HttpException
import javax.inject.Inject
@ -602,11 +604,17 @@ class AccountPreferenceFragment :
}
private fun resetAccount(confirmationString: String) {
val dialog = activity?.let { HabiticaProgressDialog.show(it, R.string.resetting_account) }
val progressDialog = activity?.let { HabiticaProgressDialog.show(it, R.string.resetting_account) }
lifecycleScope.launch(ExceptionHandler.coroutine()) {
userRepository.resetAccount(confirmationString)
dialog?.dismiss()
accountDialog.dismiss()
val resetAccountSuccess = userRepository.resetAccount(confirmationString) ?: false
progressDialog?.dismiss()
if (resetAccountSuccess) {
accountDialog.dismiss()
} else {
accountDialog.showIncorrectPasswordError(
getString(R.string.incorrect_password)
)
}
}
}

View file

@ -287,6 +287,15 @@ class HabiticaAccountDialog(private var thisContext: Context) :
}
}
fun showIncorrectPasswordError(message: String) {
if (viewBinding == null) return
binding.confirmationTextInputLayout.apply {
error = message
isErrorEnabled = true
}
}
override fun getTheme(): Int {
return R.style.HabiticaAlertDialogTheme
}