refactor: Convert account relationship API calls to use ApiResult (#1109)

This commit is contained in:
Nik Clayton 2024-11-18 17:34:52 +01:00 committed by GitHub
parent 88561afcca
commit 654a81a136
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 120 additions and 118 deletions

View File

@ -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)
}
}
}

View File

@ -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<String>) {
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)
}
}
}

View File

@ -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)
}
}
}
}

View File

@ -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()
}

View File

@ -381,7 +381,7 @@ interface MastodonApi {
@GET("api/v1/accounts/{id}")
suspend fun account(
@Path("id") accountId: String,
): NetworkResult<Account>
): ApiResult<Account>
/**
* 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<Relationship>
): ApiResult<Relationship>
@POST("api/v1/accounts/{id}/unfollow")
suspend fun unfollowAccount(
@Path("id") accountId: String,
): NetworkResult<Relationship>
): ApiResult<Relationship>
@POST("api/v1/accounts/{id}/block")
suspend fun blockAccount(
@Path("id") accountId: String,
): NetworkResult<Relationship>
): ApiResult<Relationship>
@POST("api/v1/accounts/{id}/unblock")
suspend fun unblockAccount(
@Path("id") accountId: String,
): NetworkResult<Relationship>
): ApiResult<Relationship>
@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<Relationship>
): ApiResult<Relationship>
@POST("api/v1/accounts/{id}/unmute")
suspend fun unmuteAccount(
@Path("id") accountId: String,
): NetworkResult<Relationship>
): ApiResult<Relationship>
@GET("api/v1/accounts/relationships")
suspend fun relationships(
@Query("id[]") accountIds: List<String>,
): NetworkResult<List<Relationship>>
): ApiResult<List<Relationship>>
@POST("api/v1/pleroma/accounts/{id}/subscribe")
suspend fun subscribeAccount(
@Path("id") accountId: String,
): NetworkResult<Relationship>
): ApiResult<Relationship>
@POST("api/v1/pleroma/accounts/{id}/unsubscribe")
suspend fun unsubscribeAccount(
@Path("id") accountId: String,
): NetworkResult<Relationship>
): ApiResult<Relationship>
@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<Unit>
): ApiResult<Unit>
@FormUrlEncoded
// @DELETE doesn't support fields
@HTTP(method = "DELETE", path = "api/v1/domain_blocks", hasBody = true)
suspend fun unblockDomain(@Field("domain") domain: String): NetworkResult<Unit>
suspend fun unblockDomain(@Field("domain") domain: String): ApiResult<Unit>
@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<Relationship>
): ApiResult<Relationship>
@FormUrlEncoded
@POST("api/v1/push/subscription")