remove Rx from AccountViewModel and ReportViewModel (#3463)
This commit is contained in:
parent
8c519af611
commit
787f88b801
5 changed files with 146 additions and 174 deletions
|
@ -2,6 +2,7 @@ package com.keylesspalace.tusky.components.account
|
|||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import at.connyduck.calladapter.networkresult.fold
|
||||
import com.keylesspalace.tusky.appstore.BlockEvent
|
||||
|
@ -17,19 +18,17 @@ import com.keylesspalace.tusky.network.MastodonApi
|
|||
import com.keylesspalace.tusky.util.Error
|
||||
import com.keylesspalace.tusky.util.Loading
|
||||
import com.keylesspalace.tusky.util.Resource
|
||||
import com.keylesspalace.tusky.util.RxAwareViewModel
|
||||
import com.keylesspalace.tusky.util.Success
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class AccountViewModel @Inject constructor(
|
||||
private val mastodonApi: MastodonApi,
|
||||
private val eventHub: EventHub,
|
||||
private val accountManager: AccountManager
|
||||
) : RxAwareViewModel() {
|
||||
) : ViewModel() {
|
||||
|
||||
val accountData = MutableLiveData<Resource<Account>>()
|
||||
val relationshipData = MutableLiveData<Resource<Relationship>>()
|
||||
|
@ -42,7 +41,7 @@ class AccountViewModel @Inject constructor(
|
|||
lateinit var accountId: String
|
||||
var isSelf = false
|
||||
|
||||
private var noteDisposable: Disposable? = null
|
||||
private var noteUpdateJob: Job? = null
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
|
@ -59,21 +58,22 @@ class AccountViewModel @Inject constructor(
|
|||
isDataLoading = true
|
||||
accountData.postValue(Loading())
|
||||
|
||||
mastodonApi.account(accountId)
|
||||
.subscribe(
|
||||
{ account ->
|
||||
accountData.postValue(Success(account))
|
||||
isDataLoading = false
|
||||
isRefreshing.postValue(false)
|
||||
},
|
||||
{ t ->
|
||||
Log.w(TAG, "failed obtaining account", t)
|
||||
accountData.postValue(Error())
|
||||
isDataLoading = false
|
||||
isRefreshing.postValue(false)
|
||||
}
|
||||
)
|
||||
.autoDispose()
|
||||
viewModelScope.launch {
|
||||
mastodonApi.account(accountId)
|
||||
.fold(
|
||||
{ account ->
|
||||
accountData.postValue(Success(account))
|
||||
isDataLoading = false
|
||||
isRefreshing.postValue(false)
|
||||
},
|
||||
{ t ->
|
||||
Log.w(TAG, "failed obtaining account", t)
|
||||
accountData.postValue(Error(cause = t))
|
||||
isDataLoading = false
|
||||
isRefreshing.postValue(false)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,17 +81,18 @@ class AccountViewModel @Inject constructor(
|
|||
if (relationshipData.value == null || reload) {
|
||||
relationshipData.postValue(Loading())
|
||||
|
||||
mastodonApi.relationships(listOf(accountId))
|
||||
.subscribe(
|
||||
{ relationships ->
|
||||
relationshipData.postValue(Success(relationships[0]))
|
||||
},
|
||||
{ t ->
|
||||
Log.w(TAG, "failed obtaining relationships", t)
|
||||
relationshipData.postValue(Error())
|
||||
}
|
||||
)
|
||||
.autoDispose()
|
||||
viewModelScope.launch {
|
||||
mastodonApi.relationships(listOf(accountId))
|
||||
.fold(
|
||||
{ relationships ->
|
||||
relationshipData.postValue(Success(relationships[0]))
|
||||
},
|
||||
{ t ->
|
||||
Log.w(TAG, "failed obtaining relationships", t)
|
||||
relationshipData.postValue(Error(cause = t))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,75 +213,71 @@ class AccountViewModel @Inject constructor(
|
|||
relationshipData.postValue(Loading(newRelation))
|
||||
}
|
||||
|
||||
try {
|
||||
val relationship = when (relationshipAction) {
|
||||
RelationShipAction.FOLLOW -> mastodonApi.followAccount(
|
||||
accountId,
|
||||
showReblogs = parameter ?: true
|
||||
)
|
||||
RelationShipAction.UNFOLLOW -> mastodonApi.unfollowAccount(accountId)
|
||||
RelationShipAction.BLOCK -> mastodonApi.blockAccount(accountId)
|
||||
RelationShipAction.UNBLOCK -> mastodonApi.unblockAccount(accountId)
|
||||
RelationShipAction.MUTE -> mastodonApi.muteAccount(
|
||||
accountId,
|
||||
parameter ?: true,
|
||||
duration
|
||||
)
|
||||
RelationShipAction.UNMUTE -> mastodonApi.unmuteAccount(accountId)
|
||||
RelationShipAction.SUBSCRIBE -> {
|
||||
if (isMastodon) {
|
||||
mastodonApi.followAccount(accountId, notify = true)
|
||||
} else {
|
||||
mastodonApi.subscribeAccount(accountId)
|
||||
}
|
||||
}
|
||||
RelationShipAction.UNSUBSCRIBE -> {
|
||||
if (isMastodon) {
|
||||
mastodonApi.followAccount(accountId, notify = false)
|
||||
} else {
|
||||
mastodonApi.unsubscribeAccount(accountId)
|
||||
}
|
||||
val relationshipCall = when (relationshipAction) {
|
||||
RelationShipAction.FOLLOW -> mastodonApi.followAccount(
|
||||
accountId,
|
||||
showReblogs = parameter ?: true
|
||||
)
|
||||
RelationShipAction.UNFOLLOW -> mastodonApi.unfollowAccount(accountId)
|
||||
RelationShipAction.BLOCK -> mastodonApi.blockAccount(accountId)
|
||||
RelationShipAction.UNBLOCK -> mastodonApi.unblockAccount(accountId)
|
||||
RelationShipAction.MUTE -> mastodonApi.muteAccount(
|
||||
accountId,
|
||||
parameter ?: true,
|
||||
duration
|
||||
)
|
||||
RelationShipAction.UNMUTE -> mastodonApi.unmuteAccount(accountId)
|
||||
RelationShipAction.SUBSCRIBE -> {
|
||||
if (isMastodon) {
|
||||
mastodonApi.followAccount(accountId, notify = true)
|
||||
} else {
|
||||
mastodonApi.subscribeAccount(accountId)
|
||||
}
|
||||
}
|
||||
|
||||
relationshipData.postValue(Success(relationship))
|
||||
|
||||
when (relationshipAction) {
|
||||
RelationShipAction.UNFOLLOW -> eventHub.dispatch(UnfollowEvent(accountId))
|
||||
RelationShipAction.BLOCK -> eventHub.dispatch(BlockEvent(accountId))
|
||||
RelationShipAction.MUTE -> eventHub.dispatch(MuteEvent(accountId))
|
||||
else -> {
|
||||
RelationShipAction.UNSUBSCRIBE -> {
|
||||
if (isMastodon) {
|
||||
mastodonApi.followAccount(accountId, notify = false)
|
||||
} else {
|
||||
mastodonApi.unsubscribeAccount(accountId)
|
||||
}
|
||||
}
|
||||
} catch (_: Throwable) {
|
||||
relationshipData.postValue(Error(relation))
|
||||
}
|
||||
|
||||
relationshipCall.fold(
|
||||
{ relationship ->
|
||||
relationshipData.postValue(Success(relationship))
|
||||
|
||||
when (relationshipAction) {
|
||||
RelationShipAction.UNFOLLOW -> eventHub.dispatch(UnfollowEvent(accountId))
|
||||
RelationShipAction.BLOCK -> eventHub.dispatch(BlockEvent(accountId))
|
||||
RelationShipAction.MUTE -> eventHub.dispatch(MuteEvent(accountId))
|
||||
else -> { }
|
||||
}
|
||||
},
|
||||
{ t ->
|
||||
Log.w(TAG, "failed loading relationship", t)
|
||||
relationshipData.postValue(Error(relation, cause = t))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun noteChanged(newNote: String) {
|
||||
noteSaved.postValue(false)
|
||||
noteDisposable?.dispose()
|
||||
noteDisposable = Single.timer(1500, TimeUnit.MILLISECONDS)
|
||||
.flatMap {
|
||||
mastodonApi.updateAccountNote(accountId, newNote)
|
||||
}
|
||||
.doOnSuccess {
|
||||
noteSaved.postValue(true)
|
||||
}
|
||||
.delay(4, TimeUnit.SECONDS)
|
||||
.subscribe(
|
||||
{
|
||||
noteSaved.postValue(false)
|
||||
},
|
||||
{
|
||||
Log.e(TAG, "Error updating note", it)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
noteDisposable?.dispose()
|
||||
noteUpdateJob?.cancel()
|
||||
noteUpdateJob = viewModelScope.launch {
|
||||
delay(1500)
|
||||
mastodonApi.updateAccountNote(accountId, newNote)
|
||||
.fold(
|
||||
{
|
||||
noteSaved.postValue(true)
|
||||
delay(4000)
|
||||
noteSaved.postValue(false)
|
||||
},
|
||||
{ t ->
|
||||
Log.w(TAG, "Error updating note", t)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
|
|
|
@ -27,6 +27,7 @@ import androidx.recyclerview.widget.DividerItemDecoration
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||
import at.connyduck.calladapter.networkresult.fold
|
||||
import autodispose2.androidx.lifecycle.AndroidLifecycleScopeProvider.from
|
||||
import autodispose2.autoDispose
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
@ -348,12 +349,12 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct
|
|||
}
|
||||
|
||||
private fun fetchRelationships(ids: List<String>) {
|
||||
api.relationships(ids)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.autoDispose(from(this))
|
||||
.subscribe(::onFetchRelationshipsSuccess) { throwable ->
|
||||
Log.e(TAG, "Fetch failure for relationships of accounts: $ids", throwable)
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
api.relationships(ids)
|
||||
.fold(::onFetchRelationshipsSuccess) { throwable ->
|
||||
Log.e(TAG, "Fetch failure for relationships of accounts: $ids", throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onFetchRelationshipsSuccess(relationships: List<Relationship>) {
|
||||
|
|
|
@ -17,11 +17,13 @@ package com.keylesspalace.tusky.components.report
|
|||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.cachedIn
|
||||
import androidx.paging.map
|
||||
import at.connyduck.calladapter.networkresult.fold
|
||||
import com.keylesspalace.tusky.appstore.BlockEvent
|
||||
import com.keylesspalace.tusky.appstore.EventHub
|
||||
import com.keylesspalace.tusky.appstore.MuteEvent
|
||||
|
@ -33,11 +35,8 @@ import com.keylesspalace.tusky.network.MastodonApi
|
|||
import com.keylesspalace.tusky.util.Error
|
||||
import com.keylesspalace.tusky.util.Loading
|
||||
import com.keylesspalace.tusky.util.Resource
|
||||
import com.keylesspalace.tusky.util.RxAwareViewModel
|
||||
import com.keylesspalace.tusky.util.Success
|
||||
import com.keylesspalace.tusky.util.toViewData
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
|
@ -48,7 +47,7 @@ import javax.inject.Inject
|
|||
class ReportViewModel @Inject constructor(
|
||||
private val mastodonApi: MastodonApi,
|
||||
private val eventHub: EventHub
|
||||
) : RxAwareViewModel() {
|
||||
) : ViewModel() {
|
||||
|
||||
private val navigationMutable = MutableLiveData<Screen?>()
|
||||
val navigation: LiveData<Screen?> = navigationMutable
|
||||
|
@ -128,10 +127,8 @@ class ReportViewModel @Inject constructor(
|
|||
val ids = listOf(accountId)
|
||||
muteStateMutable.value = Loading()
|
||||
blockStateMutable.value = Loading()
|
||||
mastodonApi.relationships(ids)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
viewModelScope.launch {
|
||||
mastodonApi.relationships(ids).fold(
|
||||
{ data ->
|
||||
updateRelationship(data.getOrNull(0))
|
||||
},
|
||||
|
@ -139,7 +136,7 @@ class ReportViewModel @Inject constructor(
|
|||
updateRelationship(null)
|
||||
}
|
||||
)
|
||||
.autoDispose()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateRelationship(relationship: Relationship?) {
|
||||
|
@ -155,21 +152,22 @@ class ReportViewModel @Inject constructor(
|
|||
fun toggleMute() {
|
||||
val alreadyMuted = muteStateMutable.value?.data == true
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val relationship = if (alreadyMuted) {
|
||||
mastodonApi.unmuteAccount(accountId)
|
||||
} else {
|
||||
mastodonApi.muteAccount(accountId)
|
||||
if (alreadyMuted) {
|
||||
mastodonApi.unmuteAccount(accountId)
|
||||
} else {
|
||||
mastodonApi.muteAccount(accountId)
|
||||
}.fold(
|
||||
{ relationship ->
|
||||
val muting = relationship.muting
|
||||
muteStateMutable.value = Success(muting)
|
||||
if (muting) {
|
||||
eventHub.dispatch(MuteEvent(accountId))
|
||||
}
|
||||
},
|
||||
{ t ->
|
||||
muteStateMutable.value = Error(false, t.message)
|
||||
}
|
||||
|
||||
val muting = relationship.muting
|
||||
muteStateMutable.value = Success(muting)
|
||||
if (muting) {
|
||||
eventHub.dispatch(MuteEvent(accountId))
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
muteStateMutable.value = Error(false, t.message)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
muteStateMutable.value = Loading()
|
||||
|
@ -178,39 +176,33 @@ class ReportViewModel @Inject constructor(
|
|||
fun toggleBlock() {
|
||||
val alreadyBlocked = blockStateMutable.value?.data == true
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val relationship = if (alreadyBlocked) {
|
||||
mastodonApi.unblockAccount(accountId)
|
||||
} else {
|
||||
mastodonApi.blockAccount(accountId)
|
||||
}
|
||||
|
||||
if (alreadyBlocked) {
|
||||
mastodonApi.unblockAccount(accountId)
|
||||
} else {
|
||||
mastodonApi.blockAccount(accountId)
|
||||
}.fold({ relationship ->
|
||||
val blocking = relationship.blocking
|
||||
blockStateMutable.value = Success(blocking)
|
||||
if (blocking) {
|
||||
eventHub.dispatch(BlockEvent(accountId))
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
}, { t ->
|
||||
blockStateMutable.value = Error(false, t.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
blockStateMutable.value = Loading()
|
||||
}
|
||||
|
||||
fun doReport() {
|
||||
reportingStateMutable.value = Loading()
|
||||
mastodonApi.reportObservable(accountId, selectedIds.toList(), reportNote, if (isRemoteAccount) isRemoteNotify else null)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
viewModelScope.launch {
|
||||
mastodonApi.report(accountId, selectedIds.toList(), reportNote, if (isRemoteAccount) isRemoteNotify else null)
|
||||
.fold({
|
||||
reportingStateMutable.value = Success(true)
|
||||
},
|
||||
{ error ->
|
||||
}, { error ->
|
||||
reportingStateMutable.value = Error(cause = error)
|
||||
}
|
||||
)
|
||||
.autoDispose()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun checkClickedUrl(url: String?) {
|
||||
|
|
|
@ -344,9 +344,9 @@ interface MastodonApi {
|
|||
): NetworkResult<List<TimelineAccount>>
|
||||
|
||||
@GET("api/v1/accounts/{id}")
|
||||
fun account(
|
||||
suspend fun account(
|
||||
@Path("id") accountId: String
|
||||
): Single<Account>
|
||||
): NetworkResult<Account>
|
||||
|
||||
/**
|
||||
* Method to fetch statuses for the specified account.
|
||||
|
@ -386,22 +386,22 @@ interface MastodonApi {
|
|||
@Path("id") accountId: String,
|
||||
@Field("reblogs") showReblogs: Boolean? = null,
|
||||
@Field("notify") notify: Boolean? = null
|
||||
): Relationship
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@POST("api/v1/accounts/{id}/unfollow")
|
||||
suspend fun unfollowAccount(
|
||||
@Path("id") accountId: String
|
||||
): Relationship
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@POST("api/v1/accounts/{id}/block")
|
||||
suspend fun blockAccount(
|
||||
@Path("id") accountId: String
|
||||
): Relationship
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@POST("api/v1/accounts/{id}/unblock")
|
||||
suspend fun unblockAccount(
|
||||
@Path("id") accountId: String
|
||||
): Relationship
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/accounts/{id}/mute")
|
||||
|
@ -409,27 +409,27 @@ interface MastodonApi {
|
|||
@Path("id") accountId: String,
|
||||
@Field("notifications") notifications: Boolean? = null,
|
||||
@Field("duration") duration: Int? = null
|
||||
): Relationship
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@POST("api/v1/accounts/{id}/unmute")
|
||||
suspend fun unmuteAccount(
|
||||
@Path("id") accountId: String
|
||||
): Relationship
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@GET("api/v1/accounts/relationships")
|
||||
fun relationships(
|
||||
suspend fun relationships(
|
||||
@Query("id[]") accountIds: List<String>
|
||||
): Single<List<Relationship>>
|
||||
): NetworkResult<List<Relationship>>
|
||||
|
||||
@POST("api/v1/pleroma/accounts/{id}/subscribe")
|
||||
suspend fun subscribeAccount(
|
||||
@Path("id") accountId: String
|
||||
): Relationship
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@POST("api/v1/pleroma/accounts/{id}/unsubscribe")
|
||||
suspend fun unsubscribeAccount(
|
||||
@Path("id") accountId: String
|
||||
): Relationship
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@GET("api/v1/blocks")
|
||||
suspend fun blocks(
|
||||
|
@ -677,12 +677,12 @@ interface MastodonApi {
|
|||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/reports")
|
||||
fun reportObservable(
|
||||
fun report(
|
||||
@Field("account_id") accountId: String,
|
||||
@Field("status_ids[]") statusIds: List<String>,
|
||||
@Field("comment") comment: String,
|
||||
@Field("forward") isNotifyRemote: Boolean?
|
||||
): Single<ResponseBody>
|
||||
): NetworkResult<Unit>
|
||||
|
||||
@GET("api/v1/accounts/{id}/statuses")
|
||||
fun accountStatusesObservable(
|
||||
|
@ -721,10 +721,10 @@ interface MastodonApi {
|
|||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/accounts/{id}/note")
|
||||
fun updateAccountNote(
|
||||
suspend fun updateAccountNote(
|
||||
@Path("id") accountId: String,
|
||||
@Field("comment") note: String
|
||||
): Single<Relationship>
|
||||
): NetworkResult<Relationship>
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("api/v1/push/subscription")
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package com.keylesspalace.tusky.util
|
||||
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.lifecycle.ViewModel
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
|
||||
open class RxAwareViewModel : ViewModel() {
|
||||
private val disposables = CompositeDisposable()
|
||||
|
||||
fun Disposable.autoDispose() = disposables.add(this)
|
||||
|
||||
@CallSuper
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
disposables.clear()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue