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)
}
fun getProfileInfo(userId: String): Single<JsonDict> = singleBuilder {
session.getProfile(userId, it)
fun getProfileInfo(userId: String): Single<JsonDict> = rxSingle {
session.getProfile(userId)
}
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 androidx.lifecycle.LiveData
import org.matrix.android.sdk.api.MatrixCallback
import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor
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.Optional
@ -41,14 +39,14 @@ interface ProfileService {
* @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
* @param userId the userId to update the display name of
* @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
@ -56,14 +54,14 @@ interface ProfileService {
* @param newAvatarUri the new avatar uri of the user
* @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.
* @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.
@ -71,7 +69,7 @@ interface ProfileService {
* @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
@ -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.
*/
fun addThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun addThreePid(threePid: ThreePid)
/**
* 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
*/
fun finalizeAddingThreePid(threePid: ThreePid,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor,
matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun finalizeAddingThreePid(threePid: ThreePid,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor)
/**
* Cancel adding a threepid. It will remove locally stored data about this ThreePid
*/
fun cancelAddingThreePid(threePid: ThreePid,
matrixCallback: MatrixCallback<Unit>): Cancelable
suspend fun cancelAddingThreePid(threePid: ThreePid)
/**
* 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 com.zhuinden.monarchy.Monarchy
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.session.identity.ThreePid
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.MimeTypes
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.task.TaskExecutor
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 javax.inject.Inject
@ -55,64 +53,38 @@ internal class DefaultProfileService @Inject constructor(private val taskExecuto
private val userStore: UserStore,
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)
return getProfileInfoTask
.configureWith(params) {
this.callback = object : MatrixCallback<JsonDict> {
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)
val data = getProfileInfoTask.execute(params)
val displayName = data[ProfileService.DISPLAY_NAME_KEY] as? String
return Optional.from(displayName)
}
override fun setDisplayName(userId: String, newDisplayName: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.io, matrixCallback) {
override suspend fun setDisplayName(userId: String, newDisplayName: String) {
withContext(coroutineDispatchers.io) {
setDisplayNameTask.execute(SetDisplayNameTask.Params(userId = userId, newDisplayName = newDisplayName))
userStore.updateDisplayName(userId, newDisplayName)
}
}
override fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
return taskExecutor.executorScope.launchToCallback(coroutineDispatchers.main, matrixCallback) {
override suspend fun updateAvatar(userId: String, newAvatarUri: Uri, fileName: String) {
withContext(coroutineDispatchers.main) {
val response = fileUploader.uploadFromUri(newAvatarUri, fileName, MimeTypes.Jpeg)
setAvatarUrlTask.execute(SetAvatarUrlTask.Params(userId = userId, newAvatarUrl = 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)
return getProfileInfoTask
.configureWith(params) {
this.callback = object : MatrixCallback<JsonDict> {
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)
val data = getProfileInfoTask.execute(params)
val avatarUrl = data[ProfileService.AVATAR_URL_KEY] as? String
return Optional.from(avatarUrl)
}
override fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable {
override suspend fun getProfile(userId: String): JsonDict {
val params = GetProfileInfoTask.Params(userId)
return getProfileInfoTask
.configureWith(params) {
this.callback = matrixCallback
}
.executeBy(taskExecutor)
return getProfileInfoTask.execute(params)
}
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 {
return addThreePidTask
.configureWith(AddThreePidTask.Params(threePid)) {
callback = matrixCallback
}
.executeBy(taskExecutor)
override suspend fun addThreePid(threePid: ThreePid) {
addThreePidTask.execute(AddThreePidTask.Params(threePid))
}
override fun submitSmsCode(threePid: ThreePid.Msisdn, code: String, matrixCallback: MatrixCallback<Unit>): Cancelable {
return validateSmsCodeTask
.configureWith(ValidateSmsCodeTask.Params(threePid, code)) {
callback = matrixCallback
}
.executeBy(taskExecutor)
override suspend fun submitSmsCode(threePid: ThreePid.Msisdn, code: String) {
validateSmsCodeTask.execute(ValidateSmsCodeTask.Params(threePid, code))
}
override fun finalizeAddingThreePid(threePid: ThreePid,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor,
matrixCallback: MatrixCallback<Unit>): Cancelable {
return finalizeAddingThreePidTask
.configureWith(FinalizeAddingThreePidTask.Params(
override suspend fun finalizeAddingThreePid(threePid: ThreePid,
userInteractiveAuthInterceptor: UserInteractiveAuthInterceptor) {
finalizeAddingThreePidTask
.execute(FinalizeAddingThreePidTask.Params(
threePid = threePid,
userInteractiveAuthInterceptor = userInteractiveAuthInterceptor,
userWantsToCancel = false
)) {
callback = alsoRefresh(matrixCallback)
}
.executeBy(taskExecutor)
))
refreshThreePids()
}
override fun cancelAddingThreePid(threePid: ThreePid, matrixCallback: MatrixCallback<Unit>): Cancelable {
return finalizeAddingThreePidTask
.configureWith(FinalizeAddingThreePidTask.Params(
override suspend fun cancelAddingThreePid(threePid: ThreePid) {
finalizeAddingThreePidTask
.execute(FinalizeAddingThreePidTask.Params(
threePid = threePid,
userInteractiveAuthInterceptor = null,
userWantsToCancel = true
)) {
callback = alsoRefresh(matrixCallback)
}
.executeBy(taskExecutor)
))
refreshThreePids()
}
/**
* Wrap the callback to fetch 3Pids from the server in case of success
*/
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)
override suspend fun deleteThreePid(threePid: ThreePid) {
deleteThreePidTask.execute(DeleteThreePidTask.Params(threePid))
refreshThreePids()
}
}

View file

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

View file

@ -55,7 +55,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
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.session.integrationmanager.IntegrationManagerConfig
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
@ -305,17 +304,13 @@ class VectorSettingsGeneralFragment @Inject constructor(
private fun uploadAvatar(uri: Uri) {
displayLoadingView()
session.updateAvatar(session.myUserId, uri, getFilenameFromUri(context, uri) ?: UUID.randomUUID().toString(), object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
if (!isAdded) return
onCommonDone(null)
lifecycleScope.launch {
val result = runCatching {
session.updateAvatar(session.myUserId, uri, getFilenameFromUri(context, uri) ?: UUID.randomUUID().toString())
}
override fun onFailure(failure: Throwable) {
if (!isAdded) return
onCommonDone(failure.localizedMessage)
}
})
if (!isAdded) return@launch
onCommonDone(result.fold({ null }, { it.localizedMessage }))
}
}
// ==============================================================================================================
@ -477,20 +472,21 @@ class VectorSettingsGeneralFragment @Inject constructor(
if (currentDisplayName != value) {
displayLoadingView()
session.setDisplayName(session.myUserId, value, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
if (!isAdded) return
// refresh the settings value
mDisplayNamePreference.summary = value
mDisplayNamePreference.text = value
onCommonDone(null)
}
override fun onFailure(failure: Throwable) {
if (!isAdded) return
onCommonDone(failure.localizedMessage)
}
})
lifecycleScope.launch {
val result = runCatching { session.setDisplayName(session.myUserId, value) }
if (!isAdded) return@launch
result.fold(
{
// refresh the settings value
mDisplayNamePreference.summary = value
mDisplayNamePreference.text = value
onCommonDone(null)
},
{
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.features.auth.ReAuthActivity
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.registration.RegistrationFlowResponse
import org.matrix.android.sdk.api.session.Session
@ -58,16 +57,18 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
private var pendingThreePid: ThreePid? = null
// private var pendingSession: String? = null
private val loadingCallback: MatrixCallback<Unit> = object : MatrixCallback<Unit> {
override fun onFailure(failure: Throwable) {
isLoading(false)
_viewEvents.post(ThreePidsSettingsViewEvents.Failure(failure))
}
override fun onSuccess(data: Unit) {
pendingThreePid = null
isLoading(false)
}
private suspend fun loadingSuspendable(block: suspend () -> Unit) {
runCatching { block() }
.fold(
{
pendingThreePid = null
isLoading(false)
},
{
isLoading(false)
_viewEvents.post(ThreePidsSettingsViewEvents.Failure(it))
}
)
}
private fun isLoading(isLoading: Boolean) {
@ -186,24 +187,23 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
viewModelScope.launch {
// First submit the code
session.submitSmsCode(action.threePid, action.code, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
// then finalize
pendingThreePid = action.threePid
session.finalizeAddingThreePid(action.threePid, uiaInterceptor, loadingCallback)
try {
session.submitSmsCode(action.threePid, action.code)
} catch (failure: Throwable) {
isLoading(false)
setState {
copy(
msisdnValidationRequests = msisdnValidationRequests.toMutableMap().apply {
put(action.threePid.value, Fail(failure))
}
)
}
return@launch
}
override fun onFailure(failure: Throwable) {
isLoading(false)
setState {
copy(
msisdnValidationRequests = msisdnValidationRequests.toMutableMap().apply {
put(action.threePid.value, Fail(failure))
}
)
}
}
})
// then finalize
pendingThreePid = action.threePid
loadingSuspendable { session.finalizeAddingThreePid(action.threePid, uiaInterceptor) }
}
}
@ -230,21 +230,15 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
))))
} else {
viewModelScope.launch {
session.addThreePid(action.threePid, object : MatrixCallback<Unit> {
override fun onSuccess(data: Unit) {
// Also reset the state
setState {
copy(
uiState = ThreePidsSettingsUiState.Idle
)
}
loadingCallback.onSuccess(data)
loadingSuspendable {
session.addThreePid(action.threePid)
// Also reset the state
setState {
copy(
uiState = ThreePidsSettingsUiState.Idle
)
}
override fun onFailure(failure: Throwable) {
loadingCallback.onFailure(failure)
}
})
}
}
}
}
@ -254,14 +248,14 @@ class ThreePidsSettingsViewModel @AssistedInject constructor(
isLoading(true)
pendingThreePid = action.threePid
viewModelScope.launch {
session.finalizeAddingThreePid(action.threePid, uiaInterceptor, loadingCallback)
loadingSuspendable { session.finalizeAddingThreePid(action.threePid, uiaInterceptor) }
}
}
private fun handleCancelThreePid(action: ThreePidsSettingsAction.CancelThreePid) {
isLoading(true)
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) {
isLoading(true)
viewModelScope.launch {
session.deleteThreePid(action.threePid, loadingCallback)
loadingSuspendable { session.deleteThreePid(action.threePid) }
}
}
}