diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt index ec5477f976..6ae72aeb3a 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/ChangePasswordTest.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.account +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.failure.isInvalidPassword import org.matrix.android.sdk.common.CommonTestHelper @@ -43,8 +45,8 @@ class ChangePasswordTest : InstrumentedTest { val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false)) // Change password - commonTestHelper.doSync { - session.changePassword(TestConstants.PASSWORD, NEW_PASSWORD, it) + commonTestHelper.runBlockingTest { + session.changePassword(TestConstants.PASSWORD, NEW_PASSWORD) } // Try to login with the previous password, it will fail diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt index a6fbfd9b7a..9996eef0a8 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/account/DeactivateAccountTest.kt @@ -43,8 +43,8 @@ class DeactivateAccountTest : InstrumentedTest { val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false)) // Deactivate the account - commonTestHelper.doSync { - session.deactivateAccount(TestConstants.PASSWORD, false, it) + commonTestHelper.runBlockingTest { + session.deactivateAccount(TestConstants.PASSWORD, false) } // Try to login on the previous account, it will fail (M_USER_DEACTIVATED) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt index cbe4cca8a3..660a3cc5e3 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CommonTestHelper.kt @@ -40,6 +40,7 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue @@ -343,6 +344,15 @@ class CommonTestHelper(context: Context) { await(latch, timeout) } + // Transform a method with a MatrixCallback to a synchronous method + fun runBlockingTest(timeout: Long = TestConstants.timeOutMillis, block: suspend () -> T): T { + return runBlocking { + withTimeout(timeout) { + block() + } + } + } + // Transform a method with a MatrixCallback to a synchronous method inline fun doSync(timeout: Long? = TestConstants.timeOutMillis, block: (MatrixCallback) -> Unit): T { val lock = CountDownLatch(1) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/account/AccountService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/account/AccountService.kt index b05f0036b2..1913da7c78 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/account/AccountService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/account/AccountService.kt @@ -16,8 +16,6 @@ package org.matrix.android.sdk.api.session.account -import org.matrix.android.sdk.api.MatrixCallback -import org.matrix.android.sdk.api.util.Cancelable /** * This interface defines methods to manage the account. It's implemented at the session level. @@ -28,7 +26,7 @@ interface AccountService { * @param password Current password. * @param newPassword New password */ - fun changePassword(password: String, newPassword: String, callback: MatrixCallback): Cancelable + suspend fun changePassword(password: String, newPassword: String) /** * Deactivate the account. @@ -46,5 +44,5 @@ interface AccountService { * @param eraseAllData set to true to forget all messages that have been sent. Warning: this will cause future users to see * an incomplete view of conversations */ - fun deactivateAccount(password: String, eraseAllData: Boolean, callback: MatrixCallback): Cancelable + suspend fun deactivateAccount(password: String, eraseAllData: Boolean) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DefaultAccountService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DefaultAccountService.kt index 31a39d45e5..1165d2116b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DefaultAccountService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/account/DefaultAccountService.kt @@ -16,30 +16,17 @@ package org.matrix.android.sdk.internal.session.account -import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.account.AccountService -import org.matrix.android.sdk.api.util.Cancelable -import org.matrix.android.sdk.internal.task.TaskExecutor -import org.matrix.android.sdk.internal.task.configureWith import javax.inject.Inject internal class DefaultAccountService @Inject constructor(private val changePasswordTask: ChangePasswordTask, - private val deactivateAccountTask: DeactivateAccountTask, - private val taskExecutor: TaskExecutor) : AccountService { + private val deactivateAccountTask: DeactivateAccountTask) : AccountService { - override fun changePassword(password: String, newPassword: String, callback: MatrixCallback): Cancelable { - return changePasswordTask - .configureWith(ChangePasswordTask.Params(password, newPassword)) { - this.callback = callback - } - .executeBy(taskExecutor) + override suspend fun changePassword(password: String, newPassword: String) { + changePasswordTask.execute(ChangePasswordTask.Params(password, newPassword)) } - override fun deactivateAccount(password: String, eraseAllData: Boolean, callback: MatrixCallback): Cancelable { - return deactivateAccountTask - .configureWith(DeactivateAccountTask.Params(password, eraseAllData)) { - this.callback = callback - } - .executeBy(taskExecutor) + override suspend fun deactivateAccount(password: String, eraseAllData: Boolean) { + deactivateAccountTask.execute(DeactivateAccountTask.Params(password, eraseAllData)) } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt index d8171bd30d..b1ccabfb76 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt @@ -27,6 +27,7 @@ import android.widget.ImageView import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.core.view.isVisible +import androidx.lifecycle.lifecycleScope import androidx.preference.EditTextPreference import androidx.preference.Preference import androidx.preference.PreferenceCategory @@ -451,28 +452,25 @@ class VectorSettingsGeneralFragment @Inject constructor( val newPwd = newPasswordText.text.toString() showPasswordLoadingView(true) - session.changePassword(oldPwd, newPwd, object : MatrixCallback { - override fun onSuccess(data: Unit) { - if (!isAdded) { - return - } - showPasswordLoadingView(false) + lifecycleScope.launch { + val result = runCatching { + session.changePassword(oldPwd, newPwd) + } + if (!isAdded) { + return@launch + } + showPasswordLoadingView(false) + result.fold({ dialog.dismiss() activity.toast(R.string.settings_password_updated) - } - - override fun onFailure(failure: Throwable) { - if (!isAdded) { - return - } - showPasswordLoadingView(false) + }, { failure -> if (failure.isInvalidPassword()) { oldPasswordTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password) } else { oldPasswordTil.error = getString(R.string.settings_fail_to_update_password) } - } - }) + }) + } } } dialog.show() diff --git a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt index e08147d54f..f264f430ad 100644 --- a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt @@ -15,6 +15,7 @@ */ package im.vector.app.features.settings.account.deactivation +import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxState import com.airbnb.mvrx.MvRxViewModelFactory @@ -24,9 +25,12 @@ import com.squareup.inject.assisted.AssistedInject import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModelAction +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.failure.isInvalidPassword import org.matrix.android.sdk.api.session.Session +import java.lang.Exception data class DeactivateAccountViewState( val passwordShown: Boolean = false @@ -67,19 +71,22 @@ class DeactivateAccountViewModel @AssistedInject constructor(@Assisted private v _viewEvents.post(DeactivateAccountViewEvents.Loading()) - session.deactivateAccount(action.password, action.eraseAllData, object : MatrixCallback { - override fun onSuccess(data: Unit) { - _viewEvents.post(DeactivateAccountViewEvents.Done) - } + viewModelScope.launch { + val event = try { + session.deactivateAccount(action.password, action.eraseAllData) + DeactivateAccountViewEvents.Done + } catch (failure: Exception) { + if (failure is CancellationException) throw failure - override fun onFailure(failure: Throwable) { if (failure.isInvalidPassword()) { - _viewEvents.post(DeactivateAccountViewEvents.InvalidPassword) + DeactivateAccountViewEvents.InvalidPassword } else { - _viewEvents.post(DeactivateAccountViewEvents.OtherFailure(failure)) + DeactivateAccountViewEvents.OtherFailure(failure) } } - }) + + _viewEvents.post(event) + } } companion object : MvRxViewModelFactory {