introduce KotlinResultCallAdapter for nice suspending network calls (#2415)
* introduce KotlinResultCallAdapter for nice suspending network calls * fix tests
This commit is contained in:
parent
d21d045eda
commit
3e8c6a318a
15 changed files with 168 additions and 179 deletions
|
@ -35,6 +35,7 @@ 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 kotlinx.coroutines.rx3.rxSingle
|
||||
import javax.inject.Inject
|
||||
|
||||
class AnnouncementsViewModel @Inject constructor(
|
||||
|
@ -56,8 +57,9 @@ class AnnouncementsViewModel @Inject constructor(
|
|||
appDatabase.instanceDao().loadMetadataForInstance(accountManager.activeAccount?.domain!!)
|
||||
.map<Either<InstanceEntity, Instance>> { Either.Left(it) }
|
||||
.onErrorResumeNext {
|
||||
mastodonApi.getInstance()
|
||||
.map { Either.Right(it) }
|
||||
rxSingle {
|
||||
mastodonApi.getInstance().getOrThrow()
|
||||
}.map { Either.Right(it) }
|
||||
}
|
||||
) { emojis, either ->
|
||||
either.asLeftOrNull()?.copy(emojiList = emojis)
|
||||
|
|
|
@ -48,6 +48,7 @@ import io.reactivex.rxjava3.core.Observable
|
|||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.rx3.rxSingle
|
||||
import java.util.Locale
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -105,7 +106,10 @@ class ComposeViewModel @Inject constructor(
|
|||
init {
|
||||
|
||||
Single.zip(
|
||||
api.getCustomEmojis(), api.getInstance()
|
||||
api.getCustomEmojis(),
|
||||
rxSingle {
|
||||
api.getInstance().getOrThrow()
|
||||
}
|
||||
) { emojis, instance ->
|
||||
InstanceEntity(
|
||||
instance = accountManager.activeAccount?.domain!!,
|
||||
|
@ -291,7 +295,7 @@ class ComposeViewModel @Inject constructor(
|
|||
): LiveData<Unit> {
|
||||
|
||||
val deletionObservable = if (isEditingScheduledToot) {
|
||||
api.deleteScheduledStatus(scheduledTootId.toString()).toObservable().map { }
|
||||
rxSingle { api.deleteScheduledStatus(scheduledTootId.toString()) }.toObservable().map { }
|
||||
} else {
|
||||
Observable.just(Unit)
|
||||
}.toLiveData()
|
||||
|
|
|
@ -33,7 +33,6 @@ import com.keylesspalace.tusky.MainActivity
|
|||
import com.keylesspalace.tusky.R
|
||||
import com.keylesspalace.tusky.databinding.ActivityLoginBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.entity.AppCredentials
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.util.getNonNullString
|
||||
import com.keylesspalace.tusky.util.rickRoll
|
||||
|
@ -166,32 +165,33 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
setLoading(true)
|
||||
|
||||
lifecycleScope.launch {
|
||||
val credentials: AppCredentials = try {
|
||||
mastodonApi.authenticateApp(
|
||||
domain, getString(R.string.app_name), oauthRedirectUri,
|
||||
OAUTH_SCOPES, getString(R.string.tusky_website)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
binding.loginButton.isEnabled = true
|
||||
binding.domainTextInputLayout.error =
|
||||
getString(R.string.error_failed_app_registration)
|
||||
setLoading(false)
|
||||
Log.e(TAG, Log.getStackTraceString(e))
|
||||
return@launch
|
||||
}
|
||||
mastodonApi.authenticateApp(
|
||||
domain, getString(R.string.app_name), oauthRedirectUri,
|
||||
OAUTH_SCOPES, getString(R.string.tusky_website)
|
||||
).fold(
|
||||
{ credentials ->
|
||||
// Before we open browser page we save the data.
|
||||
// Even if we don't open other apps user may go to password manager or somewhere else
|
||||
// and we will need to pick up the process where we left off.
|
||||
// Alternatively we could pass it all as part of the intent and receive it back
|
||||
// but it is a bit of a workaround.
|
||||
preferences.edit()
|
||||
.putString(DOMAIN, domain)
|
||||
.putString(CLIENT_ID, credentials.clientId)
|
||||
.putString(CLIENT_SECRET, credentials.clientSecret)
|
||||
.apply()
|
||||
|
||||
// Before we open browser page we save the data.
|
||||
// Even if we don't open other apps user may go to password manager or somewhere else
|
||||
// and we will need to pick up the process where we left off.
|
||||
// Alternatively we could pass it all as part of the intent and receive it back
|
||||
// but it is a bit of a workaround.
|
||||
preferences.edit()
|
||||
.putString(DOMAIN, domain)
|
||||
.putString(CLIENT_ID, credentials.clientId)
|
||||
.putString(CLIENT_SECRET, credentials.clientSecret)
|
||||
.apply()
|
||||
|
||||
redirectUserToAuthorizeAndLogin(domain, credentials.clientId)
|
||||
redirectUserToAuthorizeAndLogin(domain, credentials.clientId)
|
||||
},
|
||||
{ e ->
|
||||
binding.loginButton.isEnabled = true
|
||||
binding.domainTextInputLayout.error =
|
||||
getString(R.string.error_failed_app_registration)
|
||||
setLoading(false)
|
||||
Log.e(TAG, Log.getStackTraceString(e))
|
||||
return@launch
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,29 +224,28 @@ class LoginActivity : BaseActivity(), Injectable {
|
|||
|
||||
setLoading(true)
|
||||
|
||||
val accessToken = try {
|
||||
mastodonApi.fetchOAuthToken(
|
||||
domain, clientId, clientSecret, oauthRedirectUri, code,
|
||||
"authorization_code"
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
setLoading(false)
|
||||
binding.domainTextInputLayout.error =
|
||||
getString(R.string.error_retrieving_oauth_token)
|
||||
Log.e(
|
||||
TAG,
|
||||
"%s %s".format(getString(R.string.error_retrieving_oauth_token), e.message),
|
||||
)
|
||||
return
|
||||
}
|
||||
mastodonApi.fetchOAuthToken(
|
||||
domain, clientId, clientSecret, oauthRedirectUri, code, "authorization_code"
|
||||
).fold(
|
||||
{ accessToken ->
|
||||
accountManager.addAccount(accessToken.accessToken, domain)
|
||||
|
||||
accountManager.addAccount(accessToken.accessToken, domain)
|
||||
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
finish()
|
||||
overridePendingTransition(R.anim.explode, R.anim.explode)
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
finish()
|
||||
overridePendingTransition(R.anim.explode, R.anim.explode)
|
||||
},
|
||||
{ e ->
|
||||
setLoading(false)
|
||||
binding.domainTextInputLayout.error =
|
||||
getString(R.string.error_retrieving_oauth_token)
|
||||
Log.e(
|
||||
TAG,
|
||||
"%s %s".format(getString(R.string.error_retrieving_oauth_token), e.message),
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun setLoading(loadingState: Boolean) {
|
||||
|
|
|
@ -25,7 +25,6 @@ import com.keylesspalace.tusky.appstore.EventHub
|
|||
import com.keylesspalace.tusky.entity.ScheduledStatus
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.rx3.await
|
||||
import javax.inject.Inject
|
||||
|
||||
class ScheduledStatusViewModel @Inject constructor(
|
||||
|
@ -43,12 +42,14 @@ class ScheduledStatusViewModel @Inject constructor(
|
|||
|
||||
fun deleteScheduledStatus(status: ScheduledStatus) {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
mastodonApi.deleteScheduledStatus(status.id).await()
|
||||
pagingSourceFactory.remove(status)
|
||||
} catch (throwable: Throwable) {
|
||||
Log.w("ScheduledTootViewModel", "Error deleting scheduled status", throwable)
|
||||
}
|
||||
mastodonApi.deleteScheduledStatus(status.id).fold(
|
||||
{
|
||||
pagingSourceFactory.remove(status)
|
||||
},
|
||||
{ throwable ->
|
||||
Log.w("ScheduledTootViewModel", "Error deleting scheduled status", throwable)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue