Merge pull request #3074 from Dominaezzz/suspend_functions_5

Convert ProfileService to suspend functions
This commit is contained in:
Benoit Marty 2021-03-30 09:54:29 +02:00 committed by GitHub
commit a53fecc9ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 181 deletions

View file

@ -145,8 +145,8 @@ class RxSession(private val session: Session) {
session.getRoomIdByAlias(roomAlias, searchOnServer, it) session.getRoomIdByAlias(roomAlias, searchOnServer, it)
} }
fun getProfileInfo(userId: String): Single<JsonDict> = singleBuilder { fun getProfileInfo(userId: String): Single<JsonDict> = rxSingle {
session.getProfile(userId, it) session.getProfile(userId)
} }
fun liveUserCryptoDevices(userId: String): Observable<List<CryptoDeviceInfo>> { fun liveUserCryptoDevices(userId: String): Observable<List<CryptoDeviceInfo>> {

View file

@ -19,10 +19,8 @@ package org.matrix.android.sdk.api.session.profile
import android.net.Uri import android.net.Uri
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
@ -41,14 +39,14 @@ interface ProfileService {
* @param userId the userId param to look for * @param userId the userId param to look for
* *
*/ */
fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable suspend fun getDisplayName(userId: String): Optional<String>
/** /**
* Update the display name for this user * Update the display name for this user
* @param userId the userId to update the display name of * @param userId the userId to update the display name of
* @param newDisplayName the new display name of the user * @param newDisplayName the new display name of the user
*/ */
fun setDisplayName(userId: String, newDisplayName: String, matrixCallback: MatrixCallback<Unit>): Cancelable suspend fun setDisplayName(userId: String, newDisplayName: String)
/** /**
* Update the avatar for this user * Update the avatar for this user
@ -56,14 +54,14 @@ interface ProfileService {
* @param newAvatarUri the new avatar uri of the user * @param newAvatarUri the new avatar uri of the user
* @param fileName the fileName of selected image * @param fileName the fileName of selected image
*/ */
fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String, matrixCallback: MatrixCallback<Unit>): Cancelable suspend fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String)
/** /**
* Return the current avatarUrl for this user. * Return the current avatarUrl for this user.
* @param userId the userId param to look for * @param userId the userId param to look for
* *
*/ */
fun getAvatarUrl(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable suspend fun getAvatarUrl(userId: String): Optional<String>
/** /**
* Get the combined profile information for this user. * Get the combined profile information for this user.
@ -71,7 +69,7 @@ interface ProfileService {
* @param userId the userId param to look for * @param userId the userId param to look for
* *
*/ */
fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable suspend fun getProfile(userId: String): JsonDict
/** /**
* Get the current user 3Pids * Get the current user 3Pids
@ -97,28 +95,26 @@ interface ProfileService {
/** /**
* Add a 3Pids. This is the first step to add a ThreePid to an account. Then the threePid will be added to the pending threePid list. * Add a 3Pids. This is the first step to add a ThreePid to an account. Then the threePid will be added to the pending threePid list.
*/ */
fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable suspend fun addThreePid(threePid: ThreePid)
/** /**
* Validate a code received by text message * Validate a code received by text message
*/ */
fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback<Unit>): Cancelable suspend fun submitSmsCode(threePid: ThreePid.Msisdn, code: String)
/** /**
* Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid * Finalize adding a 3Pids. Call this method once the user has validated that he owns the ThreePid
*/ */
fun finalizeAddingThreePid(threePid: ThreePid, suspend fun finalizeAddingThreePid(threePid: ThreePid,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor, userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor)
matrixCallback: MatrixCallback<Unit>): Cancelable
/** /**
* Cancel adding a threepid. It will remove locally stored data about this ThreePid * Cancel adding a threepid. It will remove locally stored data about this ThreePid
*/ */
fun cancelAddingThreePid(threePid: ThreePid, suspend fun cancelAddingThreePid(threePid: ThreePid)
matrixCallback: MatrixCallback<Unit>): Cancelable
/** /**
* Remove a 3Pid from the Matrix account. * Remove a 3Pid from the Matrix account.
*/ */
fun deleteThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable suspend fun deleteThreePid(threePid: ThreePid)
} }

View file

@ -21,11 +21,10 @@ import android.net.Uri
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import io.realm.kotlin.where import io.realm.kotlin.where
import org.matrix.android.sdk.api.MatrixCallback import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.profile.ProfileService import org.matrix.android.sdk.api.session.profile.ProfileService
import org.matrix.android.sdk.api.util.Cancelable
import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.api.util.JsonDict
import org.matrix.android.sdk.api.util.MimeTypes import org.matrix.android.sdk.api.util.MimeTypes
import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.Optional
@ -36,7 +35,6 @@ import org.matrix.android.sdk.internal.session.content.FileUploader
import org.matrix.android.sdk.internal.session.user.UserStore import org.matrix.android.sdk.internal.session.user.UserStore
import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.TaskExecutor
import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.task.configureWith
import org.matrix.android.sdk.internal.task.launchToCallback
import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers import org.matrix.android.sdk.internal.util.MatrixCoroutineDispatchers
import javax.inject.Inject import javax.inject.Inject
@ -55,64 +53,38 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
private val userStore: UserStore, private val userStore: UserStore,
private val fileUploader: FileUploader) : ProfileService { private val fileUploader: FileUploader) : ProfileService {
override fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable { override suspend fun getDisplayName(userId: String): Optional<String> {
val params = GetProfileInfoTask.Params(userId) val params = GetProfileInfoTask.Params(userId)
return getProfileInfoTask val data = getProfileInfoTask.execute(params)
.configureWith(params) { val displayName = data[ProfileService.DISPLAY_NAME_KEY] as? String
this.callback = object : MatrixCallback<JsonDict> { return Optional.from(displayName)
override fun onSuccess(data: JsonDict) {
val displayName = data[ProfileService.DISPLAY_NAME_KEY] as? String
matrixCallback.onSuccess(Optional.from(displayName))
}
override fun onFailure(failure: Throwable) {
matrixCallback.onFailure(failure)
}
}
}
.executeBy(taskExecutor)
} }
override fun setDisplayName(userId: String, newDisplayName: String, matrixCallback: MatrixCallback<Unit>): Cancelable { override suspend fun setDisplayName(userId: String, newDisplayName: String) {
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.io, matrixCallback) { withContext(coroutineDispatchers.io) {
setDisplayNameTask.execute(SetDisplayNameTask.Params(userId = userId, newDisplayName = newDisplayName)) setDisplayNameTask.execute(SetDisplayNameTask.Params(userId = userId, newDisplayName = newDisplayName))
userStore.updateDisplayName(userId, newDisplayName) userStore.updateDisplayName(userId, newDisplayName)
} }
} }
override fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String, matrixCallback: MatrixCallback<Unit>): Cancelable { override suspend fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String) {
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, matrixCallback) { withContext(coroutineDispatchers.main) {
val response = fileUploader.uploadFromUri(newAvatarUri, fileName, MimeTypes.Jpeg) val response = fileUploader.uploadFromUri(newAvatarUri, fileName, MimeTypes.Jpeg)
setAvatarUrlTask.execute(SetAvatarUrlTask.Params(userId = userId, newAvatarUrl = response.contentUri)) setAvatarUrlTask.execute(SetAvatarUrlTask.Params(userId = userId, newAvatarUrl = response.contentUri))
userStore.updateAvatar(userId, response.contentUri) userStore.updateAvatar(userId, response.contentUri)
} }
} }
override fun getAvatarUrl(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable { override suspend fun getAvatarUrl(userId: String): Optional<String> {
val params = GetProfileInfoTask.Params(userId) val params = GetProfileInfoTask.Params(userId)
return getProfileInfoTask val data = getProfileInfoTask.execute(params)
.configureWith(params) { val avatarUrl = data[ProfileService.AVATAR_URL_KEY] as? String
this.callback = object : MatrixCallback<JsonDict> { return Optional.from(avatarUrl)
override fun onSuccess(data: JsonDict) {
val avatarUrl = data[ProfileService.AVATAR_URL_KEY] as? String
matrixCallback.onSuccess(Optional.from(avatarUrl))
}
override fun onFailure(failure: Throwable) {
matrixCallback.onFailure(failure)
}
}
}
.executeBy(taskExecutor)
} }
override fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable { override suspend fun getProfile(userId: String): JsonDict {
val params = GetProfileInfoTask.Params(userId) val params = GetProfileInfoTask.Params(userId)
return getProfileInfoTask return getProfileInfoTask.execute(params)
.configureWith(params) {
this.callback = matrixCallback
}
.executeBy(taskExecutor)
} }
override fun getThreePids(): List<ThreePid> { override fun getThreePids(): List<ThreePid> {
@ -154,70 +126,38 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
) )
} }
override fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable { override suspend fun addThreePid(threePid: ThreePid) {
return addThreePidTask addThreePidTask.execute(AddThreePidTask.Params(threePid))
.configureWith(AddThreePidTask.Params(threePid)) {
callback = matrixCallback
}
.executeBy(taskExecutor)
} }
override fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback<Unit>): Cancelable { override suspend fun submitSmsCode(threePid: ThreePid.Msisdn, code: String) {
return validateSmsCodeTask validateSmsCodeTask.execute(ValidateSmsCodeTask.Params(threePid, code))
.configureWith(ValidateSmsCodeTask.Params(threePid, code)) {
callback = matrixCallback
}
.executeBy(taskExecutor)
} }
override fun finalizeAddingThreePid(threePid: ThreePid, override suspend fun finalizeAddingThreePid(threePid: ThreePid,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor, userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor) {
matrixCallback: MatrixCallback<Unit>): Cancelable { finalizeAddingThreePidTask
return finalizeAddingThreePidTask .execute(FinalizeAddingThreePidTask.Params(
.configureWith(FinalizeAddingThreePidTask.Params(
threePid = threePid, threePid = threePid,
userInteractiveAuthInterceptor = userInteractiveAuthInterceptor, userInteractiveAuthInterceptor = userInteractiveAuthInterceptor,
userWantsToCancel = false userWantsToCancel = false
)) { ))
callback = alsoRefresh(matrixCallback) refreshThreePids()
}
.executeBy(taskExecutor)
} }
override fun cancelAddingThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable { override suspend fun cancelAddingThreePid(threePid: ThreePid) {
return finalizeAddingThreePidTask finalizeAddingThreePidTask
.configureWith(FinalizeAddingThreePidTask.Params( .execute(FinalizeAddingThreePidTask.Params(
threePid = threePid, threePid = threePid,
userInteractiveAuthInterceptor = null, userInteractiveAuthInterceptor = null,
userWantsToCancel = true userWantsToCancel = true
)) { ))
callback = alsoRefresh(matrixCallback) refreshThreePids()
}
.executeBy(taskExecutor)
} }
/** override suspend fun deleteThreePid(threePid: ThreePid) {
* Wrap the callback to fetch 3Pids from the server in case of success deleteThreePidTask.execute(DeleteThreePidTask.Params(threePid))
*/ refreshThreePids()
private fun alsoRefresh(callback: MatrixCallback<Unit>): MatrixCallback<Unit> {
return object : MatrixCallback<Unit> {
override fun onFailure(failure: Throwable) {
callback.onFailure(failure)
}
override fun onSuccess(data: Unit) {
refreshThreePids()
callback.onSuccess(data)
}
}
}
override fun deleteThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable {
return deleteThreePidTask
.configureWith(DeleteThreePidTask.Params(threePid)) {
callback = alsoRefresh(matrixCallback)
}
.executeBy(taskExecutor)
} }
} }

View file

@ -964,8 +964,8 @@ class RoomDetailViewModel @AssistedInject constructor(
} }
private fun handleChangeDisplayNameSlashCommand(changeDisplayName: ParsedCommand.ChangeDisplayName) { private fun handleChangeDisplayNameSlashCommand(changeDisplayName: ParsedCommand.ChangeDisplayName) {
launchSlashCommandFlow { launchSlashCommandFlowSuspendable {
session.setDisplayName(session.myUserId, changeDisplayName.displayName, it) session.setDisplayName(session.myUserId, changeDisplayName.displayName)
} }
} }

View file

@ -55,7 +55,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.failure.isInvalidPassword import org.matrix.android.sdk.api.failure.isInvalidPassword
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerConfig
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
@ -305,17 +304,13 @@ class VectorSettingsGeneralFragment @Inject constructor(
private fun uploadAvatar(uri: Uri) { private fun uploadAvatar(uri: Uri) {
displayLoadingView() displayLoadingView()
session.updateAvatar(session.myUserId, uri, getFilenameFromUri(context, uri) ?: UUID.randomUUID().toString(), object : MatrixCallback<Unit> { lifecycleScope.launch {
override fun onSuccess(data: Unit) { val result = runCatching {
if (!isAdded) return session.updateAvatar(session.myUserId, uri, getFilenameFromUri(context, uri) ?: UUID.randomUUID().toString())
onCommonDone(null)
} }
if (!isAdded) return@launch
override fun onFailure(failure: Throwable) { onCommonDone(result.fold({ null }, { it.localizedMessage }))
if (!isAdded) return }
onCommonDone(failure.localizedMessage)
}
})
} }
// ============================================================================================================== // ==============================================================================================================
@ -477,20 +472,21 @@ class VectorSettingsGeneralFragment @Inject constructor(
if (currentDisplayName != value) { if (currentDisplayName != value) {
displayLoadingView() displayLoadingView()
session.setDisplayName(session.myUserId, value, object : MatrixCallback<Unit> { lifecycleScope.launch {
override fun onSuccess(data: Unit) { val result = runCatching { session.setDisplayName(session.myUserId, value) }
if (!isAdded) return if (!isAdded) return@launch
// refresh the settings value result.fold(
mDisplayNamePreference.summary = value {
mDisplayNamePreference.text = value // refresh the settings value
onCommonDone(null) mDisplayNamePreference.summary = value
} mDisplayNamePreference.text = value
onCommonDone(null)
override fun onFailure(failure: Throwable) { },
if (!isAdded) return {
onCommonDone(failure.localizedMessage) onCommonDone(it.localizedMessage)
} }
}) )
}
} }
} }
} }

View file

@ -33,7 +33,6 @@ import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.ReadOnceTrue import im.vector.app.core.utils.ReadOnceTrue
import im.vector.app.features.auth.ReAuthActivity import im.vector.app.features.auth.ReAuthActivity
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
@ -58,16 +57,18 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
private var pendingThreePid: ThreePid? = null private var pendingThreePid: ThreePid? = null
// private var pendingSession: String? = null // private var pendingSession: String? = null
private val loadingCallback: MatrixCallback<Unit> = object : MatrixCallback<Unit> { private suspend fun loadingSuspendable(block: suspend () -> Unit) {
override fun onFailure(failure: Throwable) { runCatching { block() }
isLoading(false) .fold(
_viewEvents.post(ThreePidsSettingsViewEvents.Failure(failure)) {
} pendingThreePid = null
isLoading(false)
override fun onSuccess(data: Unit) { },
pendingThreePid = null {
isLoading(false) isLoading(false)
} _viewEvents.post(ThreePidsSettingsViewEvents.Failure(it))
}
)
} }
private fun isLoading(isLoading: Boolean) { private fun isLoading(isLoading: Boolean) {
@ -186,24 +187,23 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
viewModelScope.launch { viewModelScope.launch {
// First submit the code // First submit the code
session.submitSmsCode(action.threePid, action.code, object : MatrixCallback<Unit> { try {
override fun onSuccess(data: Unit) { session.submitSmsCode(action.threePid, action.code)
// then finalize } catch (failure: Throwable) {
pendingThreePid = action.threePid isLoading(false)
session.finalizeAddingThreePid(action.threePid, uiaInterceptor, loadingCallback) setState {
copy(
msisdnValidationRequests = msisdnValidationRequests.toMutableMap().apply {
put(action.threePid.value, Fail(failure))
}
)
} }
return@launch
}
override fun onFailure(failure: Throwable) { // then finalize
isLoading(false) pendingThreePid = action.threePid
setState { loadingSuspendable { session.finalizeAddingThreePid(action.threePid, uiaInterceptor) }
copy(
msisdnValidationRequests = msisdnValidationRequests.toMutableMap().apply {
put(action.threePid.value, Fail(failure))
}
)
}
}
})
} }
} }
@ -230,21 +230,15 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
)))) ))))
} else { } else {
viewModelScope.launch { viewModelScope.launch {
session.addThreePid(action.threePid, object : MatrixCallback<Unit> { loadingSuspendable {
override fun onSuccess(data: Unit) { session.addThreePid(action.threePid)
// Also reset the state // Also reset the state
setState { setState {
copy( copy(
uiState = ThreePidsSettingsUiState.Idle uiState = ThreePidsSettingsUiState.Idle
) )
}
loadingCallback.onSuccess(data)
} }
}
override fun onFailure(failure: Throwable) {
loadingCallback.onFailure(failure)
}
})
} }
} }
} }
@ -254,14 +248,14 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
isLoading(true) isLoading(true)
pendingThreePid = action.threePid pendingThreePid = action.threePid
viewModelScope.launch { viewModelScope.launch {
session.finalizeAddingThreePid(action.threePid, uiaInterceptor, loadingCallback) loadingSuspendable { session.finalizeAddingThreePid(action.threePid, uiaInterceptor) }
} }
} }
private fun handleCancelThreePid(action: ThreePidsSettingsAction.CancelThreePid) { private fun handleCancelThreePid(action: ThreePidsSettingsAction.CancelThreePid) {
isLoading(true) isLoading(true)
viewModelScope.launch { viewModelScope.launch {
session.cancelAddingThreePid(action.threePid, loadingCallback) loadingSuspendable { session.cancelAddingThreePid(action.threePid) }
} }
} }
@ -277,7 +271,7 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
private fun handleDeleteThreePid(action: ThreePidsSettingsAction.DeleteThreePid) { private fun handleDeleteThreePid(action: ThreePidsSettingsAction.DeleteThreePid) {
isLoading(true) isLoading(true)
viewModelScope.launch { viewModelScope.launch {
session.deleteThreePid(action.threePid, loadingCallback) loadingSuspendable { session.deleteThreePid(action.threePid) }
} }
} }
} }