From 654a81a136cc0ec28dc5ccacba6e521a231bf6c8 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Mon, 18 Nov 2024 17:34:52 +0100 Subject: [PATCH] refactor: Convert account relationship API calls to use ApiResult (#1109) --- .../components/account/AccountViewModel.kt | 118 +++++++++--------- .../accountlist/AccountListFragment.kt | 15 +-- .../fragment/InstanceListFragment.kt | 33 ++--- .../components/report/ReportViewModel.kt | 46 +++---- .../core/network/retrofit/MastodonApi.kt | 26 ++-- 5 files changed, 120 insertions(+), 118 deletions(-) diff --git a/app/src/main/java/app/pachli/components/account/AccountViewModel.kt b/app/src/main/java/app/pachli/components/account/AccountViewModel.kt index 9f58ff1bb..1a4f7f51b 100644 --- a/app/src/main/java/app/pachli/components/account/AccountViewModel.kt +++ b/app/src/main/java/app/pachli/components/account/AccountViewModel.kt @@ -18,7 +18,8 @@ import app.pachli.util.Error import app.pachli.util.Loading import app.pachli.util.Resource import app.pachli.util.Success -import at.connyduck.calladapter.networkresult.fold +import com.github.michaelbull.result.onFailure +import com.github.michaelbull.result.onSuccess import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject import kotlinx.coroutines.Job @@ -71,22 +72,21 @@ class AccountViewModel @Inject constructor( viewModelScope.launch { mastodonApi.account(accountId) - .fold( - { account -> - domain = getDomain(account.url) - accountData.postValue(Success(account)) - isDataLoading = false - isRefreshing.postValue(false) + .onSuccess { result -> + val account = result.body + domain = getDomain(account.url) + accountData.postValue(Success(account)) + isDataLoading = false + isRefreshing.postValue(false) - isFromOwnDomain = domain == activeAccount.domain - }, - { t -> - Timber.w(t, "failed obtaining account") - accountData.postValue(Error(cause = t)) - isDataLoading = false - isRefreshing.postValue(false) - }, - ) + isFromOwnDomain = domain == activeAccount.domain + } + .onFailure { t -> + Timber.w("failed obtaining account: %s", t) + accountData.postValue(Error(cause = t.throwable)) + isDataLoading = false + isRefreshing.postValue(false) + } } } } @@ -97,15 +97,14 @@ class AccountViewModel @Inject constructor( viewModelScope.launch { mastodonApi.relationships(listOf(accountId)) - .fold( - { relationships -> - relationshipData.postValue(if (relationships.isNotEmpty()) Success(relationships[0]) else Error()) - }, - { t -> - Timber.w(t, "failed obtaining relationships") - relationshipData.postValue(Error(cause = t)) - }, - ) + .onSuccess { response -> + val relationships = response.body + relationshipData.postValue(if (relationships.isNotEmpty()) Success(relationships[0]) else Error()) + } + .onFailure { t -> + Timber.w("failed obtaining relationships: %s", t) + relationshipData.postValue(Error(cause = t.throwable)) + } } } } @@ -149,28 +148,32 @@ class AccountViewModel @Inject constructor( fun blockDomain(instance: String) { viewModelScope.launch { - mastodonApi.blockDomain(instance).fold({ - eventHub.dispatch(DomainMuteEvent(instance)) - val relation = relationshipData.value?.data - if (relation != null) { - relationshipData.postValue(Success(relation.copy(blockingDomain = true))) + mastodonApi.blockDomain(instance) + .onSuccess { + eventHub.dispatch(DomainMuteEvent(instance)) + val relation = relationshipData.value?.data + if (relation != null) { + relationshipData.postValue(Success(relation.copy(blockingDomain = true))) + } + } + .onFailure { e -> + Timber.e("Error muting %s: %s", instance, e) } - }, { e -> - Timber.e(e, "Error muting %s", instance) - }) } } fun unblockDomain(instance: String) { viewModelScope.launch { - mastodonApi.unblockDomain(instance).fold({ - val relation = relationshipData.value?.data - if (relation != null) { - relationshipData.postValue(Success(relation.copy(blockingDomain = false))) + mastodonApi.unblockDomain(instance) + .onSuccess { + val relation = relationshipData.value?.data + if (relation != null) { + relationshipData.postValue(Success(relation.copy(blockingDomain = false))) + } + } + .onFailure { e -> + Timber.e("Error unmuting %s: %s", instance, e) } - }, { e -> - Timber.e(e, "Error unmuting %s", instance) - }) } } @@ -258,9 +261,9 @@ class AccountViewModel @Inject constructor( } } - relationshipCall.fold( - { relationship -> - relationshipData.postValue(Success(relationship)) + relationshipCall + .onSuccess { response -> + relationshipData.postValue(Success(response.body)) when (relationshipAction) { RelationShipAction.UNFOLLOW -> eventHub.dispatch(UnfollowEvent(accountId)) @@ -268,12 +271,11 @@ class AccountViewModel @Inject constructor( RelationShipAction.MUTE -> eventHub.dispatch(MuteEvent(accountId)) else -> { } } - }, - { t -> - Timber.w(t, "failed loading relationship") - relationshipData.postValue(Error(relation, cause = t)) - }, - ) + } + .onFailure { e -> + Timber.w("failed loading relationship: %s", e) + relationshipData.postValue(Error(relation, cause = e.throwable)) + } } fun noteChanged(newNote: String) { @@ -282,16 +284,14 @@ class AccountViewModel @Inject constructor( noteUpdateJob = viewModelScope.launch { delay(1500) mastodonApi.updateAccountNote(accountId, newNote) - .fold( - { - noteSaved.postValue(true) - delay(4000) - noteSaved.postValue(false) - }, - { t -> - Timber.w(t, "Error updating note") - }, - ) + .onSuccess { + noteSaved.postValue(true) + delay(4000) + noteSaved.postValue(false) + } + .onFailure { e -> + Timber.w("Error updating note: %s", e) + } } } diff --git a/app/src/main/java/app/pachli/components/accountlist/AccountListFragment.kt b/app/src/main/java/app/pachli/components/accountlist/AccountListFragment.kt index 15be7a590..31337a475 100644 --- a/app/src/main/java/app/pachli/components/accountlist/AccountListFragment.kt +++ b/app/src/main/java/app/pachli/components/accountlist/AccountListFragment.kt @@ -63,6 +63,8 @@ import app.pachli.interfaces.AppBarLayoutHost import app.pachli.view.EndlessOnScrollListener import at.connyduck.calladapter.networkresult.fold import com.github.michaelbull.result.getOrElse +import com.github.michaelbull.result.onFailure +import com.github.michaelbull.result.onSuccess import com.google.android.material.color.MaterialColors import com.google.android.material.divider.MaterialDividerItemDecoration import com.google.android.material.snackbar.Snackbar @@ -229,11 +231,9 @@ class AccountListFragment : api.blockAccount(id) } else { api.unblockAccount(id) - }.fold({ - onBlockSuccess(block, id, position) - }, { - onBlockFailure(block, id, it) - }) + } + .onSuccess { onBlockSuccess(block, id, position) } + .onFailure { onBlockFailure(block, id, it.throwable) } } } @@ -379,8 +379,9 @@ class AccountListFragment : private fun fetchRelationships(ids: List) { lifecycleScope.launch { api.relationships(ids) - .fold(::onFetchRelationshipsSuccess) { throwable -> - Timber.e(throwable, "Fetch failure for relationships of accounts: %s", ids) + .onSuccess { onFetchRelationshipsSuccess(it.body) } + .onFailure { throwable -> + Timber.e("Fetch failure for relationships of accounts: %s: %s", ids, throwable) } } } diff --git a/app/src/main/java/app/pachli/components/instancemute/fragment/InstanceListFragment.kt b/app/src/main/java/app/pachli/components/instancemute/fragment/InstanceListFragment.kt index 6916d80ff..0a2411cd9 100644 --- a/app/src/main/java/app/pachli/components/instancemute/fragment/InstanceListFragment.kt +++ b/app/src/main/java/app/pachli/components/instancemute/fragment/InstanceListFragment.kt @@ -17,7 +17,8 @@ import app.pachli.core.network.retrofit.MastodonApi import app.pachli.core.ui.BackgroundMessage import app.pachli.databinding.FragmentInstanceListBinding import app.pachli.view.EndlessOnScrollListener -import at.connyduck.calladapter.networkresult.fold +import com.github.michaelbull.result.onFailure +import com.github.michaelbull.result.onSuccess import com.google.android.material.divider.MaterialDividerItemDecoration import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint @@ -68,22 +69,22 @@ class InstanceListFragment : override fun mute(mute: Boolean, instance: String, position: Int) { viewLifecycleOwner.lifecycleScope.launch { if (mute) { - api.blockDomain(instance).fold({ - adapter.addItem(instance) - }, { e -> - Timber.e(e, "Error muting domain %s", instance) - }) + api.blockDomain(instance) + .onSuccess { adapter.addItem(instance) } + .onFailure { Timber.e(it.throwable, "Error muting domain %s", instance) } } else { - api.unblockDomain(instance).fold({ - adapter.removeItem(position) - Snackbar.make(binding.recyclerView, getString(R.string.confirmation_domain_unmuted, instance), Snackbar.LENGTH_LONG) - .setAction(R.string.action_undo) { - mute(true, instance, position) - } - .show() - }, { e -> - Timber.e(e, "Error unmuting domain %s", instance) - }) + api.unblockDomain(instance) + .onSuccess { + adapter.removeItem(position) + Snackbar.make(binding.recyclerView, getString(R.string.confirmation_domain_unmuted, instance), Snackbar.LENGTH_LONG) + .setAction(R.string.action_undo) { + mute(true, instance, position) + } + .show() + } + .onFailure { e -> + Timber.e(e.throwable, "Error unmuting domain %s", instance) + } } } } diff --git a/app/src/main/java/app/pachli/components/report/ReportViewModel.kt b/app/src/main/java/app/pachli/components/report/ReportViewModel.kt index 4621370a7..50bfd9e91 100644 --- a/app/src/main/java/app/pachli/components/report/ReportViewModel.kt +++ b/app/src/main/java/app/pachli/components/report/ReportViewModel.kt @@ -39,6 +39,8 @@ import app.pachli.util.Resource import app.pachli.util.Success import app.pachli.viewdata.StatusViewData import at.connyduck.calladapter.networkresult.fold +import com.github.michaelbull.result.onFailure +import com.github.michaelbull.result.onSuccess import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject import kotlinx.coroutines.channels.BufferOverflow @@ -135,14 +137,9 @@ class ReportViewModel @Inject constructor( muteStateMutable.value = Loading() blockStateMutable.value = Loading() viewModelScope.launch { - mastodonApi.relationships(ids).fold( - { data -> - updateRelationship(data.getOrNull(0)) - }, - { - updateRelationship(null) - }, - ) + mastodonApi.relationships(ids) + .onSuccess { updateRelationship(it.body.firstOrNull()) } + .onFailure { updateRelationship(null) } } } @@ -163,18 +160,18 @@ class ReportViewModel @Inject constructor( mastodonApi.unmuteAccount(accountId) } else { mastodonApi.muteAccount(accountId) - }.fold( - { relationship -> + } + .onSuccess { response -> + val relationship = response.body val muting = relationship.muting muteStateMutable.value = Success(muting) if (muting) { eventHub.dispatch(MuteEvent(accountId)) } - }, - { t -> - muteStateMutable.value = Error(false, t.message) - }, - ) + } + .onFailure { t -> + muteStateMutable.value = Error(false, t.throwable.message) + } } muteStateMutable.value = Loading() @@ -187,15 +184,18 @@ class ReportViewModel @Inject constructor( mastodonApi.unblockAccount(accountId) } else { mastodonApi.blockAccount(accountId) - }.fold({ relationship -> - val blocking = relationship.blocking - blockStateMutable.value = Success(blocking) - if (blocking) { - eventHub.dispatch(BlockEvent(accountId)) + } + .onSuccess { response -> + val relationship = response.body + val blocking = relationship.blocking + blockStateMutable.value = Success(blocking) + if (blocking) { + eventHub.dispatch(BlockEvent(accountId)) + } + } + .onFailure { t -> + blockStateMutable.value = Error(false, t.throwable.message) } - }, { t -> - blockStateMutable.value = Error(false, t.message) - }) } blockStateMutable.value = Loading() } diff --git a/core/network/src/main/kotlin/app/pachli/core/network/retrofit/MastodonApi.kt b/core/network/src/main/kotlin/app/pachli/core/network/retrofit/MastodonApi.kt index bfb6edceb..43c2d9520 100644 --- a/core/network/src/main/kotlin/app/pachli/core/network/retrofit/MastodonApi.kt +++ b/core/network/src/main/kotlin/app/pachli/core/network/retrofit/MastodonApi.kt @@ -381,7 +381,7 @@ interface MastodonApi { @GET("api/v1/accounts/{id}") suspend fun account( @Path("id") accountId: String, - ): NetworkResult + ): ApiResult /** * Method to fetch statuses for the specified account. @@ -425,22 +425,22 @@ interface MastodonApi { @Path("id") accountId: String, @Field("reblogs") showReblogs: Boolean? = null, @Field("notify") notify: Boolean? = null, - ): NetworkResult + ): ApiResult @POST("api/v1/accounts/{id}/unfollow") suspend fun unfollowAccount( @Path("id") accountId: String, - ): NetworkResult + ): ApiResult @POST("api/v1/accounts/{id}/block") suspend fun blockAccount( @Path("id") accountId: String, - ): NetworkResult + ): ApiResult @POST("api/v1/accounts/{id}/unblock") suspend fun unblockAccount( @Path("id") accountId: String, - ): NetworkResult + ): ApiResult @FormUrlEncoded @POST("api/v1/accounts/{id}/mute") @@ -448,27 +448,27 @@ interface MastodonApi { @Path("id") accountId: String, @Field("notifications") notifications: Boolean? = null, @Field("duration") duration: Int? = null, - ): NetworkResult + ): ApiResult @POST("api/v1/accounts/{id}/unmute") suspend fun unmuteAccount( @Path("id") accountId: String, - ): NetworkResult + ): ApiResult @GET("api/v1/accounts/relationships") suspend fun relationships( @Query("id[]") accountIds: List, - ): NetworkResult> + ): ApiResult> @POST("api/v1/pleroma/accounts/{id}/subscribe") suspend fun subscribeAccount( @Path("id") accountId: String, - ): NetworkResult + ): ApiResult @POST("api/v1/pleroma/accounts/{id}/unsubscribe") suspend fun unsubscribeAccount( @Path("id") accountId: String, - ): NetworkResult + ): ApiResult @GET("api/v1/blocks") suspend fun blocks( @@ -491,12 +491,12 @@ interface MastodonApi { @POST("api/v1/domain_blocks") suspend fun blockDomain( @Field("domain") domain: String, - ): NetworkResult + ): ApiResult @FormUrlEncoded // @DELETE doesn't support fields @HTTP(method = "DELETE", path = "api/v1/domain_blocks", hasBody = true) - suspend fun unblockDomain(@Field("domain") domain: String): NetworkResult + suspend fun unblockDomain(@Field("domain") domain: String): ApiResult @GET("api/v1/favourites") suspend fun favourites( @@ -744,7 +744,7 @@ interface MastodonApi { suspend fun updateAccountNote( @Path("id") accountId: String, @Field("comment") note: String, - ): NetworkResult + ): ApiResult @FormUrlEncoded @POST("api/v1/push/subscription")