2022-01-11 19:55:17 +01:00
|
|
|
package com.keylesspalace.tusky.components.account
|
2018-06-18 13:26:18 +02:00
|
|
|
|
2019-06-11 15:56:27 +02:00
|
|
|
import android.util.Log
|
2018-12-17 15:25:35 +01:00
|
|
|
import androidx.lifecycle.MutableLiveData
|
2022-12-28 19:06:31 +01:00
|
|
|
import androidx.lifecycle.viewModelScope
|
2021-06-28 21:13:24 +02:00
|
|
|
import com.keylesspalace.tusky.appstore.BlockEvent
|
|
|
|
import com.keylesspalace.tusky.appstore.DomainMuteEvent
|
|
|
|
import com.keylesspalace.tusky.appstore.EventHub
|
|
|
|
import com.keylesspalace.tusky.appstore.MuteEvent
|
|
|
|
import com.keylesspalace.tusky.appstore.ProfileEditedEvent
|
|
|
|
import com.keylesspalace.tusky.appstore.UnfollowEvent
|
2019-05-15 12:43:16 +02:00
|
|
|
import com.keylesspalace.tusky.db.AccountManager
|
2018-06-18 13:26:18 +02:00
|
|
|
import com.keylesspalace.tusky.entity.Account
|
|
|
|
import com.keylesspalace.tusky.entity.Relationship
|
|
|
|
import com.keylesspalace.tusky.network.MastodonApi
|
2021-06-28 21:13:24 +02:00
|
|
|
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
|
2021-05-16 19:53:27 +02:00
|
|
|
import io.reactivex.rxjava3.core.Single
|
|
|
|
import io.reactivex.rxjava3.disposables.Disposable
|
2022-12-28 19:06:31 +01:00
|
|
|
import kotlinx.coroutines.launch
|
2018-06-18 13:26:18 +02:00
|
|
|
import retrofit2.Call
|
|
|
|
import retrofit2.Callback
|
|
|
|
import retrofit2.Response
|
2020-11-17 20:10:54 +01:00
|
|
|
import java.util.concurrent.TimeUnit
|
2018-06-18 13:26:18 +02:00
|
|
|
import javax.inject.Inject
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
class AccountViewModel @Inject constructor(
|
2021-06-28 21:13:24 +02:00
|
|
|
private val mastodonApi: MastodonApi,
|
|
|
|
private val eventHub: EventHub,
|
|
|
|
private val accountManager: AccountManager
|
2020-11-17 20:10:54 +01:00
|
|
|
) : RxAwareViewModel() {
|
2018-06-18 13:26:18 +02:00
|
|
|
|
|
|
|
val accountData = MutableLiveData<Resource<Account>>()
|
|
|
|
val relationshipData = MutableLiveData<Resource<Relationship>>()
|
|
|
|
|
2020-11-17 20:10:54 +01:00
|
|
|
val noteSaved = MutableLiveData<Boolean>()
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
val isRefreshing = MutableLiveData<Boolean>().apply { value = false }
|
|
|
|
private var isDataLoading = false
|
2018-06-18 13:26:18 +02:00
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
lateinit var accountId: String
|
|
|
|
var isSelf = false
|
2018-06-18 13:26:18 +02:00
|
|
|
|
2020-11-17 20:10:54 +01:00
|
|
|
private var noteDisposable: Disposable? = null
|
|
|
|
|
|
|
|
init {
|
|
|
|
eventHub.events
|
2021-06-28 21:13:24 +02:00
|
|
|
.subscribe { event ->
|
|
|
|
if (event is ProfileEditedEvent && event.newProfileData.id == accountData.value?.data?.id) {
|
|
|
|
accountData.postValue(Success(event.newProfileData))
|
|
|
|
}
|
|
|
|
}.autoDispose()
|
2020-11-17 20:10:54 +01:00
|
|
|
}
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
private fun obtainAccount(reload: Boolean = false) {
|
|
|
|
if (accountData.value == null || reload) {
|
|
|
|
isDataLoading = true
|
2018-06-18 13:26:18 +02:00
|
|
|
accountData.postValue(Loading())
|
|
|
|
|
2020-11-17 20:10:54 +01:00
|
|
|
mastodonApi.account(accountId)
|
2021-06-28 21:13:24 +02:00
|
|
|
.subscribe(
|
|
|
|
{ account ->
|
2020-11-17 20:10:54 +01:00
|
|
|
accountData.postValue(Success(account))
|
|
|
|
isDataLoading = false
|
|
|
|
isRefreshing.postValue(false)
|
2021-06-28 21:13:24 +02:00
|
|
|
},
|
|
|
|
{ t ->
|
2020-11-17 20:10:54 +01:00
|
|
|
Log.w(TAG, "failed obtaining account", t)
|
2018-06-18 13:26:18 +02:00
|
|
|
accountData.postValue(Error())
|
2020-11-17 20:10:54 +01:00
|
|
|
isDataLoading = false
|
|
|
|
isRefreshing.postValue(false)
|
2021-06-28 21:13:24 +02:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.autoDispose()
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
private fun obtainRelationship(reload: Boolean = false) {
|
|
|
|
if (relationshipData.value == null || reload) {
|
2018-06-18 13:26:18 +02:00
|
|
|
|
|
|
|
relationshipData.postValue(Loading())
|
|
|
|
|
2020-11-17 20:10:54 +01:00
|
|
|
mastodonApi.relationships(listOf(accountId))
|
2021-06-28 21:13:24 +02:00
|
|
|
.subscribe(
|
|
|
|
{ relationships ->
|
2020-11-17 20:10:54 +01:00
|
|
|
relationshipData.postValue(Success(relationships[0]))
|
2021-06-28 21:13:24 +02:00
|
|
|
},
|
|
|
|
{ t ->
|
2020-11-17 20:10:54 +01:00
|
|
|
Log.w(TAG, "failed obtaining relationships", t)
|
2018-06-18 13:26:18 +02:00
|
|
|
relationshipData.postValue(Error())
|
2021-06-28 21:13:24 +02:00
|
|
|
}
|
|
|
|
)
|
|
|
|
.autoDispose()
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
fun changeFollowState() {
|
2018-07-22 14:34:55 +02:00
|
|
|
val relationship = relationshipData.value?.data
|
|
|
|
if (relationship?.following == true || relationship?.requested == true) {
|
2019-05-15 12:43:16 +02:00
|
|
|
changeRelationship(RelationShipAction.UNFOLLOW)
|
2018-06-18 13:26:18 +02:00
|
|
|
} else {
|
2019-05-15 12:43:16 +02:00
|
|
|
changeRelationship(RelationShipAction.FOLLOW)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
fun changeBlockState() {
|
2018-06-18 13:26:18 +02:00
|
|
|
if (relationshipData.value?.data?.blocking == true) {
|
2019-05-15 12:43:16 +02:00
|
|
|
changeRelationship(RelationShipAction.UNBLOCK)
|
2018-06-18 13:26:18 +02:00
|
|
|
} else {
|
2019-05-15 12:43:16 +02:00
|
|
|
changeRelationship(RelationShipAction.BLOCK)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-09 18:37:41 +02:00
|
|
|
fun muteAccount(notifications: Boolean, duration: Int?) {
|
2021-01-15 21:05:36 +01:00
|
|
|
changeRelationship(RelationShipAction.MUTE, notifications, duration)
|
2020-07-27 10:28:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun unmuteAccount() {
|
|
|
|
changeRelationship(RelationShipAction.UNMUTE)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
2021-06-28 21:13:24 +02:00
|
|
|
|
2020-12-23 12:52:39 +01:00
|
|
|
fun changeSubscribingState() {
|
|
|
|
val relationship = relationshipData.value?.data
|
2021-06-28 21:13:24 +02:00
|
|
|
if (relationship?.notifying == true || /* Mastodon 3.3.0rc1 */
|
|
|
|
relationship?.subscribing == true /* Pleroma */
|
|
|
|
) {
|
2020-12-23 12:52:39 +01:00
|
|
|
changeRelationship(RelationShipAction.UNSUBSCRIBE)
|
|
|
|
} else {
|
|
|
|
changeRelationship(RelationShipAction.SUBSCRIBE)
|
|
|
|
}
|
|
|
|
}
|
2018-06-18 13:26:18 +02:00
|
|
|
|
2020-06-23 19:59:49 +02:00
|
|
|
fun blockDomain(instance: String) {
|
2021-06-28 21:13:24 +02:00
|
|
|
mastodonApi.blockDomain(instance).enqueue(object : Callback<Any> {
|
2019-06-11 15:56:27 +02:00
|
|
|
override fun onResponse(call: Call<Any>, response: Response<Any>) {
|
|
|
|
if (response.isSuccessful) {
|
|
|
|
eventHub.dispatch(DomainMuteEvent(instance))
|
2020-06-23 19:59:49 +02:00
|
|
|
val relation = relationshipData.value?.data
|
2021-06-28 21:13:24 +02:00
|
|
|
if (relation != null) {
|
2020-06-23 19:59:49 +02:00
|
|
|
relationshipData.postValue(Success(relation.copy(blockingDomain = true)))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Log.e(TAG, "Error muting %s".format(instance))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onFailure(call: Call<Any>, t: Throwable) {
|
|
|
|
Log.e(TAG, "Error muting %s".format(instance), t)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fun unblockDomain(instance: String) {
|
2021-06-28 21:13:24 +02:00
|
|
|
mastodonApi.unblockDomain(instance).enqueue(object : Callback<Any> {
|
2020-06-23 19:59:49 +02:00
|
|
|
override fun onResponse(call: Call<Any>, response: Response<Any>) {
|
|
|
|
if (response.isSuccessful) {
|
|
|
|
val relation = relationshipData.value?.data
|
2021-06-28 21:13:24 +02:00
|
|
|
if (relation != null) {
|
2020-06-23 19:59:49 +02:00
|
|
|
relationshipData.postValue(Success(relation.copy(blockingDomain = false)))
|
|
|
|
}
|
2019-06-11 15:56:27 +02:00
|
|
|
} else {
|
2020-06-23 19:59:49 +02:00
|
|
|
Log.e(TAG, "Error unmuting %s".format(instance))
|
2019-06-11 15:56:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onFailure(call: Call<Any>, t: Throwable) {
|
2020-06-23 19:59:49 +02:00
|
|
|
Log.e(TAG, "Error unmuting %s".format(instance), t)
|
2019-06-11 15:56:27 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
fun changeShowReblogsState() {
|
2018-06-18 13:26:18 +02:00
|
|
|
if (relationshipData.value?.data?.showingReblogs == true) {
|
2019-05-15 12:43:16 +02:00
|
|
|
changeRelationship(RelationShipAction.FOLLOW, false)
|
2018-06-18 13:26:18 +02:00
|
|
|
} else {
|
2019-05-15 12:43:16 +02:00
|
|
|
changeRelationship(RelationShipAction.FOLLOW, true)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-27 10:28:59 +02:00
|
|
|
/**
|
|
|
|
* @param parameter showReblogs if RelationShipAction.FOLLOW, notifications if MUTE
|
|
|
|
*/
|
2022-12-28 19:06:31 +01:00
|
|
|
private fun changeRelationship(
|
|
|
|
relationshipAction: RelationShipAction,
|
|
|
|
parameter: Boolean? = null,
|
|
|
|
duration: Int? = null
|
|
|
|
) = viewModelScope.launch {
|
2018-06-18 13:26:18 +02:00
|
|
|
val relation = relationshipData.value?.data
|
|
|
|
val account = accountData.value?.data
|
2020-12-23 12:52:39 +01:00
|
|
|
val isMastodon = relationshipData.value?.data?.notifying != null
|
2018-06-18 13:26:18 +02:00
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
if (relation != null && account != null) {
|
2018-06-18 13:26:18 +02:00
|
|
|
// optimistically post new state for faster response
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
val newRelation = when (relationshipAction) {
|
2018-06-18 13:26:18 +02:00
|
|
|
RelationShipAction.FOLLOW -> {
|
|
|
|
if (account.locked) {
|
|
|
|
relation.copy(requested = true)
|
|
|
|
} else {
|
|
|
|
relation.copy(following = true)
|
|
|
|
}
|
|
|
|
}
|
2019-05-15 12:43:16 +02:00
|
|
|
RelationShipAction.UNFOLLOW -> relation.copy(following = false)
|
|
|
|
RelationShipAction.BLOCK -> relation.copy(blocking = true)
|
|
|
|
RelationShipAction.UNBLOCK -> relation.copy(blocking = false)
|
|
|
|
RelationShipAction.MUTE -> relation.copy(muting = true)
|
|
|
|
RelationShipAction.UNMUTE -> relation.copy(muting = false)
|
2020-12-23 12:52:39 +01:00
|
|
|
RelationShipAction.SUBSCRIBE -> {
|
2021-06-28 21:13:24 +02:00
|
|
|
if (isMastodon)
|
2020-12-23 12:52:39 +01:00
|
|
|
relation.copy(notifying = true)
|
|
|
|
else relation.copy(subscribing = true)
|
|
|
|
}
|
|
|
|
RelationShipAction.UNSUBSCRIBE -> {
|
2021-06-28 21:13:24 +02:00
|
|
|
if (isMastodon)
|
2020-12-23 12:52:39 +01:00
|
|
|
relation.copy(notifying = false)
|
|
|
|
else relation.copy(subscribing = false)
|
|
|
|
}
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
relationshipData.postValue(Loading(newRelation))
|
|
|
|
}
|
|
|
|
|
2022-12-28 19:06:31 +01:00
|
|
|
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)
|
|
|
|
}
|
2020-12-23 12:52:39 +01:00
|
|
|
}
|
2021-06-28 21:13:24 +02:00
|
|
|
|
2022-12-28 19:06:31 +01:00
|
|
|
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 -> {
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
2021-06-28 21:13:24 +02:00
|
|
|
}
|
2022-12-28 19:06:31 +01:00
|
|
|
} catch (_: Throwable) {
|
|
|
|
relationshipData.postValue(Error(relation))
|
|
|
|
}
|
2020-11-17 20:10:54 +01:00
|
|
|
}
|
2018-06-18 13:26:18 +02:00
|
|
|
|
2020-11-17 20:10:54 +01:00
|
|
|
fun noteChanged(newNote: String) {
|
|
|
|
noteSaved.postValue(false)
|
|
|
|
noteDisposable?.dispose()
|
|
|
|
noteDisposable = Single.timer(1500, TimeUnit.MILLISECONDS)
|
2021-06-28 21:13:24 +02:00
|
|
|
.flatMap {
|
|
|
|
mastodonApi.updateAccountNote(accountId, newNote)
|
|
|
|
}
|
|
|
|
.doOnSuccess {
|
|
|
|
noteSaved.postValue(true)
|
|
|
|
}
|
|
|
|
.delay(4, TimeUnit.SECONDS)
|
|
|
|
.subscribe(
|
|
|
|
{
|
2020-11-17 20:10:54 +01:00
|
|
|
noteSaved.postValue(false)
|
2021-06-28 21:13:24 +02:00
|
|
|
},
|
|
|
|
{
|
2020-11-17 20:10:54 +01:00
|
|
|
Log.e(TAG, "Error updating note", it)
|
2021-06-28 21:13:24 +02:00
|
|
|
}
|
|
|
|
)
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCleared() {
|
2020-11-17 20:10:54 +01:00
|
|
|
super.onCleared()
|
|
|
|
noteDisposable?.dispose()
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
|
2019-05-15 12:43:16 +02:00
|
|
|
fun refresh() {
|
|
|
|
reload(true)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun reload(isReload: Boolean = false) {
|
|
|
|
if (isDataLoading)
|
|
|
|
return
|
|
|
|
accountId.let {
|
|
|
|
obtainAccount(isReload)
|
|
|
|
if (!isSelf)
|
|
|
|
obtainRelationship(isReload)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fun setAccountInfo(accountId: String) {
|
|
|
|
this.accountId = accountId
|
|
|
|
this.isSelf = accountManager.activeAccount?.accountId == accountId
|
|
|
|
reload(false)
|
|
|
|
}
|
|
|
|
|
2018-06-18 13:26:18 +02:00
|
|
|
enum class RelationShipAction {
|
2020-12-23 12:52:39 +01:00
|
|
|
FOLLOW, UNFOLLOW, BLOCK, UNBLOCK, MUTE, UNMUTE, SUBSCRIBE, UNSUBSCRIBE
|
2018-06-18 13:26:18 +02:00
|
|
|
}
|
|
|
|
|
2019-06-11 15:56:27 +02:00
|
|
|
companion object {
|
|
|
|
const val TAG = "AccountViewModel"
|
|
|
|
}
|
2020-12-23 12:52:39 +01:00
|
|
|
}
|