Integrate Valere's remarks - step 3: use viewModelScope in ViewModels

This commit is contained in:
Benoit Marty 2020-05-18 10:15:25 +02:00
parent e67e472025
commit ecf3fee709
4 changed files with 152 additions and 176 deletions

View File

@ -15,6 +15,7 @@
*/ */
package im.vector.riotx.features.discovery package im.vector.riotx.features.discovery
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.Async import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.FragmentViewModelContext
@ -25,15 +26,16 @@ import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.ViewModelContext import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.identity.IdentityServiceError import im.vector.matrix.android.api.session.identity.IdentityServiceError
import im.vector.matrix.android.api.session.identity.IdentityServiceListener import im.vector.matrix.android.api.session.identity.IdentityServiceListener
import im.vector.matrix.android.api.session.identity.SharedState import im.vector.matrix.android.api.session.identity.SharedState
import im.vector.matrix.android.api.session.identity.ThreePid import im.vector.matrix.android.api.session.identity.ThreePid
import im.vector.matrix.android.internal.util.awaitCallback
import im.vector.matrix.rx.rx import im.vector.matrix.rx.rx
import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.extensions.exhaustive
import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.platform.VectorViewModel
import kotlinx.coroutines.launch
class DiscoverySettingsViewModel @AssistedInject constructor( class DiscoverySettingsViewModel @AssistedInject constructor(
@Assisted initialState: DiscoverySettingsState, @Assisted initialState: DiscoverySettingsState,
@ -104,72 +106,47 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
} }
private fun disconnectIdentityServer() { private fun disconnectIdentityServer() {
setState { setState { copy(identityServer = Loading()) }
copy(
identityServer = Loading()
)
}
session.identityService().disconnect(object : MatrixCallback<Unit> { viewModelScope.launch {
override fun onSuccess(data: Unit) { try {
setState { awaitCallback<Unit> { session.identityService().disconnect(it) }
copy( setState { copy(identityServer = Success(null)) }
identityServer = Success(null) } catch (failure: Throwable) {
) setState { copy(identityServer = Fail(failure)) }
} }
} }
override fun onFailure(failure: Throwable) {
setState {
copy(
identityServer = Fail(failure)
)
}
}
})
} }
private fun changeIdentityServer(action: DiscoverySettingsAction.ChangeIdentityServer) { private fun changeIdentityServer(action: DiscoverySettingsAction.ChangeIdentityServer) {
setState { setState { copy(identityServer = Loading()) }
copy(
identityServer = Loading()
)
}
session.identityService().setNewIdentityServer(action.url, object : MatrixCallback<String?> { viewModelScope.launch {
override fun onSuccess(data: String?) { try {
setState { val data = awaitCallback<String?> {
copy( session.identityService().setNewIdentityServer(action.url, it)
identityServer = Success(data)
)
} }
setState { copy(identityServer = Success(data)) }
retrieveBinding() retrieveBinding()
} } catch (failure: Throwable) {
setState { copy(identityServer = Fail(failure)) }
override fun onFailure(failure: Throwable) {
setState {
copy(
identityServer = Fail(failure)
)
} }
} }
})
} }
private fun shareThreePid(action: DiscoverySettingsAction.ShareThreePid) = withState { state -> private fun shareThreePid(action: DiscoverySettingsAction.ShareThreePid) = withState { state ->
if (state.identityServer() == null) return@withState if (state.identityServer() == null) return@withState
changeThreePidState(action.threePid, Loading()) changeThreePidState(action.threePid, Loading())
identityService.startBindThreePid(action.threePid, object : MatrixCallback<Unit> { viewModelScope.launch {
override fun onSuccess(data: Unit) { try {
awaitCallback<Unit> { identityService.startBindThreePid(action.threePid, it) }
changeThreePidState(action.threePid, Success(SharedState.BINDING_IN_PROGRESS)) changeThreePidState(action.threePid, Success(SharedState.BINDING_IN_PROGRESS))
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
_viewEvents.post(DiscoverySettingsViewEvents.Failure(failure)) _viewEvents.post(DiscoverySettingsViewEvents.Failure(failure))
changeThreePidState(action.threePid, Fail(failure)) changeThreePidState(action.threePid, Fail(failure))
} }
}) }
} }
private fun changeThreePidState(threePid: ThreePid, state: Async<SharedState>) { private fun changeThreePidState(threePid: ThreePid, state: Async<SharedState>) {
@ -238,16 +215,15 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
if (state.emailList() == null) return@withState if (state.emailList() == null) return@withState
changeThreePidState(threePid, Loading()) changeThreePidState(threePid, Loading())
identityService.unbindThreePid(threePid, object : MatrixCallback<Unit> { viewModelScope.launch {
override fun onSuccess(data: Unit) { try {
awaitCallback<Unit> { identityService.unbindThreePid(threePid, it) }
changeThreePidState(threePid, Success(SharedState.NOT_SHARED)) changeThreePidState(threePid, Success(SharedState.NOT_SHARED))
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
_viewEvents.post(DiscoverySettingsViewEvents.Failure(failure)) _viewEvents.post(DiscoverySettingsViewEvents.Failure(failure))
changeThreePidState(threePid, Fail(failure)) changeThreePidState(threePid, Fail(failure))
} }
}) }
} }
private fun revokeMsisdn(threePid: ThreePid.Msisdn) = withState { state -> private fun revokeMsisdn(threePid: ThreePid.Msisdn) = withState { state ->
@ -255,29 +231,27 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
if (state.phoneNumbersList() == null) return@withState if (state.phoneNumbersList() == null) return@withState
changeThreePidState(threePid, Loading()) changeThreePidState(threePid, Loading())
identityService.unbindThreePid(threePid, object : MatrixCallback<Unit> { viewModelScope.launch {
override fun onSuccess(data: Unit) { try {
awaitCallback<Unit> { identityService.unbindThreePid(threePid, it) }
changeThreePidState(threePid, Success(SharedState.NOT_SHARED)) changeThreePidState(threePid, Success(SharedState.NOT_SHARED))
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
_viewEvents.post(DiscoverySettingsViewEvents.Failure(failure)) _viewEvents.post(DiscoverySettingsViewEvents.Failure(failure))
changeThreePidState(threePid, Fail(failure)) changeThreePidState(threePid, Fail(failure))
} }
}) }
} }
private fun cancelBinding(action: DiscoverySettingsAction.CancelBinding) { private fun cancelBinding(action: DiscoverySettingsAction.CancelBinding) {
identityService.cancelBindThreePid(action.threePid, object : MatrixCallback<Unit> { viewModelScope.launch {
override fun onSuccess(data: Unit) { try {
awaitCallback<Unit> { identityService.cancelBindThreePid(action.threePid, it) }
changeThreePidState(action.threePid, Success(SharedState.NOT_SHARED)) changeThreePidState(action.threePid, Success(SharedState.NOT_SHARED))
changeThreePidSubmitState(action.threePid, Uninitialized) changeThreePidSubmitState(action.threePid, Uninitialized)
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
// This could never fail // This could never fail
} }
}) }
} }
private fun startListenToIdentityManager() { private fun startListenToIdentityManager() {
@ -305,9 +279,11 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
) )
} }
identityService.getShareStatus(threePids, viewModelScope.launch {
object : MatrixCallback<Map<ThreePid, SharedState>> { try {
override fun onSuccess(data: Map<ThreePid, SharedState>) { val data = awaitCallback<Map<ThreePid, SharedState>> {
identityService.getShareStatus(threePids, it)
}
setState { setState {
copy( copy(
emailList = Success(data.filter { it.key is ThreePid.Email }.toPidInfoList()), emailList = Success(data.filter { it.key is ThreePid.Email }.toPidInfoList()),
@ -315,9 +291,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
termsNotSigned = false termsNotSigned = false
) )
} }
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
if (failure !is IdentityServiceError.TermsNotSignedException) { if (failure !is IdentityServiceError.TermsNotSignedException) {
_viewEvents.post(DiscoverySettingsViewEvents.Failure(failure)) _viewEvents.post(DiscoverySettingsViewEvents.Failure(failure))
} }
@ -330,7 +304,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
) )
} }
} }
}) }
} }
private fun Map<ThreePid, SharedState>.toPidInfoList(): List<PidInfo> { private fun Map<ThreePid, SharedState>.toPidInfoList(): List<PidInfo> {
@ -347,19 +321,17 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
changeThreePidSubmitState(action.threePid, Loading()) changeThreePidSubmitState(action.threePid, Loading())
identityService.submitValidationToken(action.threePid, viewModelScope.launch {
action.code, try {
object : MatrixCallback<Unit> { awaitCallback<Unit> {
override fun onSuccess(data: Unit) { identityService.submitValidationToken(action.threePid, action.code, it)
}
changeThreePidSubmitState(action.threePid, Uninitialized) changeThreePidSubmitState(action.threePid, Uninitialized)
finalizeBind3pid(DiscoverySettingsAction.FinalizeBind3pid(action.threePid), true) finalizeBind3pid(DiscoverySettingsAction.FinalizeBind3pid(action.threePid), true)
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
changeThreePidSubmitState(action.threePid, Fail(failure)) changeThreePidSubmitState(action.threePid, Fail(failure))
} }
} }
)
} }
private fun finalizeBind3pid(action: DiscoverySettingsAction.FinalizeBind3pid, fromUser: Boolean) = withState { state -> private fun finalizeBind3pid(action: DiscoverySettingsAction.FinalizeBind3pid, fromUser: Boolean) = withState { state ->
@ -374,13 +346,12 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
changeThreePidSubmitState(action.threePid, Loading()) changeThreePidSubmitState(action.threePid, Loading())
identityService.finalizeBindThreePid(threePid, object : MatrixCallback<Unit> { viewModelScope.launch {
override fun onSuccess(data: Unit) { try {
awaitCallback<Unit> { identityService.finalizeBindThreePid(threePid, it) }
changeThreePidSubmitState(action.threePid, Uninitialized) changeThreePidSubmitState(action.threePid, Uninitialized)
changeThreePidState(action.threePid, Success(SharedState.SHARED)) changeThreePidState(action.threePid, Success(SharedState.SHARED))
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
// If this is not from user (user did not click to "Continue", but this is a refresh when Fragment is resumed), do no display the error // If this is not from user (user did not click to "Continue", but this is a refresh when Fragment is resumed), do no display the error
if (fromUser) { if (fromUser) {
changeThreePidSubmitState(action.threePid, Fail(failure)) changeThreePidSubmitState(action.threePid, Fail(failure))
@ -388,7 +359,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
changeThreePidSubmitState(action.threePid, Uninitialized) changeThreePidSubmitState(action.threePid, Uninitialized)
} }
} }
}) }
} }
private fun refreshPendingEmailBindings() = withState { state -> private fun refreshPendingEmailBindings() = withState { state ->

View File

@ -15,23 +15,25 @@
*/ */
package im.vector.riotx.features.discovery.change package im.vector.riotx.features.discovery.change
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.ViewModelContext import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.identity.IdentityServiceError import im.vector.matrix.android.api.session.identity.IdentityServiceError
import im.vector.matrix.android.api.session.terms.GetTermsResponse import im.vector.matrix.android.api.session.terms.GetTermsResponse
import im.vector.matrix.android.api.session.terms.TermsService import im.vector.matrix.android.api.session.terms.TermsService
import im.vector.matrix.android.internal.util.awaitCallback
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.HasScreenInjector import im.vector.riotx.core.di.HasScreenInjector
import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.extensions.exhaustive
import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.platform.VectorViewModel
import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.StringProvider
import im.vector.riotx.core.utils.ensureProtocol import im.vector.riotx.core.utils.ensureProtocol
import kotlinx.coroutines.launch
class SetIdentityServerViewModel @AssistedInject constructor( class SetIdentityServerViewModel @AssistedInject constructor(
@Assisted initialState: SetIdentityServerState, @Assisted initialState: SetIdentityServerState,
@ -91,14 +93,15 @@ class SetIdentityServerViewModel @AssistedInject constructor(
_viewEvents.post(SetIdentityServerViewEvents.Loading()) _viewEvents.post(SetIdentityServerViewEvents.Loading())
viewModelScope.launch {
try {
// First ping the identity server v2 API // First ping the identity server v2 API
mxSession.identityService().isValidIdentityServer(baseUrl, object : MatrixCallback<Unit> { awaitCallback<Unit> {
override fun onSuccess(data: Unit) { mxSession.identityService().isValidIdentityServer(baseUrl, it)
}
// Ok, next step // Ok, next step
checkTerms(baseUrl) checkTerms(baseUrl)
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
if (failure is IdentityServiceError.OutdatedIdentityServer) { if (failure is IdentityServiceError.OutdatedIdentityServer) {
_viewEvents.post(SetIdentityServerViewEvents.Failure(R.string.identity_server_error_outdated_identity_server)) _viewEvents.post(SetIdentityServerViewEvents.Failure(R.string.identity_server_error_outdated_identity_server))
} else { } else {
@ -106,14 +109,15 @@ class SetIdentityServerViewModel @AssistedInject constructor(
_viewEvents.post(SetIdentityServerViewEvents.OtherFailure(failure)) _viewEvents.post(SetIdentityServerViewEvents.OtherFailure(failure))
} }
} }
}) }
}
private suspend fun checkTerms(baseUrl: String) {
try {
val data = awaitCallback<GetTermsResponse> {
mxSession.getTerms(TermsService.ServiceType.IdentityService, baseUrl, it)
} }
private fun checkTerms(baseUrl: String) {
mxSession.getTerms(TermsService.ServiceType.IdentityService,
baseUrl,
object : MatrixCallback<GetTermsResponse> {
override fun onSuccess(data: GetTermsResponse) {
// has all been accepted? // has all been accepted?
val resp = data.serverResponse val resp = data.serverResponse
val tos = resp.getLocalizedTerms(userLanguage) val tos = resp.getLocalizedTerms(userLanguage)
@ -128,9 +132,7 @@ class SetIdentityServerViewModel @AssistedInject constructor(
_viewEvents.post(SetIdentityServerViewEvents.TermsAccepted) _viewEvents.post(SetIdentityServerViewEvents.TermsAccepted)
} }
} }
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
if (failure is Failure.OtherServerError && failure.httpCode == 404) { if (failure is Failure.OtherServerError && failure.httpCode == 404) {
// 404: Same as NoTerms // 404: Same as NoTerms
_viewEvents.post(SetIdentityServerViewEvents.NoTerms) _viewEvents.post(SetIdentityServerViewEvents.NoTerms)
@ -139,6 +141,5 @@ class SetIdentityServerViewModel @AssistedInject constructor(
_viewEvents.post(SetIdentityServerViewEvents.OtherFailure(failure)) _viewEvents.post(SetIdentityServerViewEvents.OtherFailure(failure))
} }
} }
})
} }
} }

View File

@ -15,6 +15,7 @@
*/ */
package im.vector.riotx.features.terms package im.vector.riotx.features.terms
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.ActivityViewModelContext import com.airbnb.mvrx.ActivityViewModelContext
import com.airbnb.mvrx.Loading import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.MvRxViewModelFactory
@ -23,11 +24,12 @@ import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.ViewModelContext import com.airbnb.mvrx.ViewModelContext
import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.Assisted
import com.squareup.inject.assisted.AssistedInject import com.squareup.inject.assisted.AssistedInject
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.terms.GetTermsResponse import im.vector.matrix.android.api.session.terms.GetTermsResponse
import im.vector.matrix.android.internal.util.awaitCallback
import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.extensions.exhaustive
import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.platform.VectorViewModel
import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
class ReviewTermsViewModel @AssistedInject constructor( class ReviewTermsViewModel @AssistedInject constructor(
@ -94,17 +96,19 @@ class ReviewTermsViewModel @AssistedInject constructor(
val agreedUrls = acceptedTerms.map { it.url } val agreedUrls = acceptedTerms.map { it.url }
viewModelScope.launch {
try {
awaitCallback<Unit> {
session.agreeToTerms( session.agreeToTerms(
termsArgs.type, termsArgs.type,
termsArgs.baseURL, termsArgs.baseURL,
agreedUrls, agreedUrls,
termsArgs.token, termsArgs.token,
object : MatrixCallback<Unit> { it
override fun onSuccess(data: Unit) { )
_viewEvents.post(ReviewTermsViewEvents.Success)
} }
_viewEvents.post(ReviewTermsViewEvents.Success)
override fun onFailure(failure: Throwable) { } catch (failure: Throwable) {
Timber.e(failure, "Failed to agree to terms") Timber.e(failure, "Failed to agree to terms")
setState { setState {
copy( copy(
@ -114,7 +118,6 @@ class ReviewTermsViewModel @AssistedInject constructor(
_viewEvents.post(ReviewTermsViewEvents.Failure(failure, false)) _viewEvents.post(ReviewTermsViewEvents.Failure(failure, false))
} }
} }
)
} }
private fun loadTerms(action: ReviewTermsAction.LoadTerms) = withState { state -> private fun loadTerms(action: ReviewTermsAction.LoadTerms) = withState { state ->
@ -126,8 +129,11 @@ class ReviewTermsViewModel @AssistedInject constructor(
copy(termsList = Loading()) copy(termsList = Loading())
} }
session.getTerms(termsArgs.type, termsArgs.baseURL, object : MatrixCallback<GetTermsResponse> { viewModelScope.launch {
override fun onSuccess(data: GetTermsResponse) { try {
val data = awaitCallback<GetTermsResponse> {
session.getTerms(termsArgs.type, termsArgs.baseURL, it)
}
val terms = data.serverResponse.getLocalizedTerms(action.preferredLanguageCode).map { val terms = data.serverResponse.getLocalizedTerms(action.preferredLanguageCode).map {
Term(it.localizedUrl ?: "", Term(it.localizedUrl ?: "",
it.localizedName ?: "", it.localizedName ?: "",
@ -141,9 +147,7 @@ class ReviewTermsViewModel @AssistedInject constructor(
termsList = Success(terms) termsList = Success(terms)
) )
} }
} } catch (failure: Throwable) {
override fun onFailure(failure: Throwable) {
Timber.e(failure, "Failed to agree to terms") Timber.e(failure, "Failed to agree to terms")
setState { setState {
copy( copy(
@ -152,6 +156,6 @@ class ReviewTermsViewModel @AssistedInject constructor(
} }
_viewEvents.post(ReviewTermsViewEvents.Failure(failure, true)) _viewEvents.post(ReviewTermsViewEvents.Failure(failure, true))
} }
}) }
} }
} }