Use coroutines
This commit is contained in:
parent
178ae0b392
commit
3a91b02e55
@ -9,6 +9,7 @@ import android.os.Bundle
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.h.pixeldroid.utils.BaseActivity
|
import com.h.pixeldroid.utils.BaseActivity
|
||||||
import com.h.pixeldroid.utils.api.PixelfedAPI
|
import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||||
import com.h.pixeldroid.utils.api.objects.*
|
import com.h.pixeldroid.utils.api.objects.*
|
||||||
@ -17,24 +18,22 @@ import com.h.pixeldroid.utils.db.storeInstance
|
|||||||
import com.h.pixeldroid.utils.hasInternet
|
import com.h.pixeldroid.utils.hasInternet
|
||||||
import com.h.pixeldroid.utils.normalizeDomain
|
import com.h.pixeldroid.utils.normalizeDomain
|
||||||
import com.h.pixeldroid.utils.openUrl
|
import com.h.pixeldroid.utils.openUrl
|
||||||
import io.reactivex.Single
|
|
||||||
import io.reactivex.SingleObserver
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
|
||||||
import io.reactivex.disposables.Disposable
|
|
||||||
import io.reactivex.functions.BiFunction
|
|
||||||
import io.reactivex.schedulers.Schedulers
|
|
||||||
import kotlinx.android.synthetic.main.activity_login.*
|
import kotlinx.android.synthetic.main.activity_login.*
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Callback
|
import retrofit2.Callback
|
||||||
|
import retrofit2.HttpException
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Overview of the flow of the login process: (boxes are requests done in parallel,
|
Overview of the flow of the login process: (boxes are requests done in parallel,
|
||||||
since they do not depend on each other)
|
since they do not depend on each other)
|
||||||
|
|
||||||
_________________________________
|
_________________________________
|
||||||
|[PixelfedAPI.registerApplication]|
|
|[PixelfedAPI.registerApplicationAsync]|
|
||||||
|[PixelfedAPI.wellKnownNodeInfo] |
|
|[PixelfedAPI.wellKnownNodeInfo] |
|
||||||
̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅ +----> [PixelfedAPI.nodeInfoSchema]
|
̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅̅ +----> [PixelfedAPI.nodeInfoSchema]
|
||||||
+----> [promptOAuth]
|
+----> [promptOAuth]
|
||||||
@ -131,56 +130,52 @@ class LoginActivity : BaseActivity() {
|
|||||||
|
|
||||||
pixelfedAPI = PixelfedAPI.createFromUrl(normalizedDomain)
|
pixelfedAPI = PixelfedAPI.createFromUrl(normalizedDomain)
|
||||||
|
|
||||||
Single.zip(
|
lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
val credentialsDeferred = async {
|
||||||
pixelfedAPI.registerApplication(
|
pixelfedAPI.registerApplication(
|
||||||
appName, "$oauthScheme://$PACKAGE_ID", SCOPE
|
appName, "$oauthScheme://$PACKAGE_ID", SCOPE
|
||||||
),
|
)
|
||||||
pixelfedAPI.wellKnownNodeInfo(),
|
}
|
||||||
{ application, nodeInfoJRD ->
|
|
||||||
// we get here when both results have come in:
|
val nodeInfoJRD = pixelfedAPI.wellKnownNodeInfo()
|
||||||
Pair(application, nodeInfoJRD)
|
|
||||||
})
|
val credentials = credentialsDeferred.await()
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
val clientId = credentials.client_id ?: return@launch failedRegistration()
|
||||||
.subscribe(object : SingleObserver<Pair<Application, NodeInfoJRD>> {
|
|
||||||
override fun onSuccess(pair: Pair<Application, NodeInfoJRD>) {
|
|
||||||
val (credentials, nodeInfoJRD) = pair
|
|
||||||
val clientId = credentials.client_id ?: return failedRegistration()
|
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
.putString("domain", normalizedDomain)
|
.putString("domain", normalizedDomain)
|
||||||
.putString("clientID", clientId)
|
.putString("clientID", clientId)
|
||||||
.putString("clientSecret", credentials.client_secret)
|
.putString("clientSecret", credentials.client_secret)
|
||||||
.apply()
|
.apply()
|
||||||
|
|
||||||
|
|
||||||
// c.f. https://nodeinfo.diaspora.software/protocol.html for more info
|
// c.f. https://nodeinfo.diaspora.software/protocol.html for more info
|
||||||
val nodeInfoSchemaUrl = nodeInfoJRD.links.firstOrNull {
|
val nodeInfoSchemaUrl = nodeInfoJRD.links.firstOrNull {
|
||||||
it.rel == "http://nodeinfo.diaspora.software/ns/schema/2.0"
|
it.rel == "http://nodeinfo.diaspora.software/ns/schema/2.0"
|
||||||
}?.href ?: return failedRegistration(getString(R.string.instance_error))
|
}?.href ?: return@launch failedRegistration(getString(R.string.instance_error))
|
||||||
|
|
||||||
nodeInfoSchema(normalizedDomain, clientId, nodeInfoSchemaUrl)
|
nodeInfoSchema(normalizedDomain, clientId, nodeInfoSchemaUrl)
|
||||||
|
} catch (exception: IOException) {
|
||||||
|
return@launch failedRegistration()
|
||||||
|
} catch (exception: HttpException) {
|
||||||
|
return@launch failedRegistration()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
private suspend fun nodeInfoSchema(
|
||||||
//Error in any of the two requests will get to this
|
|
||||||
Log.e("registerAppToServer", e.message.toString())
|
|
||||||
failedRegistration()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun nodeInfoSchema(
|
|
||||||
normalizedDomain: String,
|
normalizedDomain: String,
|
||||||
clientId: String,
|
clientId: String,
|
||||||
nodeInfoSchemaUrl: String
|
nodeInfoSchemaUrl: String
|
||||||
) {
|
) {
|
||||||
pixelfedAPI.nodeInfoSchema(nodeInfoSchemaUrl).enqueue(object : Callback<NodeInfo> {
|
val nodeInfo = try {
|
||||||
override fun onResponse(call: Call<NodeInfo>, response: Response<NodeInfo>) {
|
pixelfedAPI.nodeInfoSchema(nodeInfoSchemaUrl)
|
||||||
if (response.body() == null || !response.isSuccessful) {
|
} catch (exception: IOException) {
|
||||||
|
return failedRegistration(getString(R.string.instance_error))
|
||||||
|
} catch (exception: HttpException) {
|
||||||
return failedRegistration(getString(R.string.instance_error))
|
return failedRegistration(getString(R.string.instance_error))
|
||||||
}
|
}
|
||||||
val nodeInfo = response.body() as NodeInfo
|
|
||||||
|
|
||||||
if (!nodeInfo.software?.name.orEmpty().contains("pixelfed")) {
|
if (!nodeInfo.software?.name.orEmpty().contains("pixelfed")) {
|
||||||
val builder = AlertDialog.Builder(this@LoginActivity)
|
val builder = AlertDialog.Builder(this@LoginActivity)
|
||||||
@ -196,15 +191,10 @@ class LoginActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
// Create the AlertDialog
|
// Create the AlertDialog
|
||||||
builder.show()
|
builder.show()
|
||||||
return
|
|
||||||
} else {
|
} else {
|
||||||
promptOAuth(normalizedDomain, clientId)
|
promptOAuth(normalizedDomain, clientId)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
override fun onFailure(call: Call<NodeInfo>, t: Throwable) {
|
|
||||||
failedRegistration(getString(R.string.instance_error))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -233,43 +223,41 @@ class LoginActivity : BaseActivity() {
|
|||||||
//Successful authorization
|
//Successful authorization
|
||||||
pixelfedAPI = PixelfedAPI.createFromUrl(domain)
|
pixelfedAPI = PixelfedAPI.createFromUrl(domain)
|
||||||
|
|
||||||
//TODO check why we can't do onErrorReturn { null } which would make more sense ¯\_(ツ)_/¯
|
lifecycleScope.launch {
|
||||||
//Also, maybe find a nicer way to do this, this feels hacky (although it can work fine)
|
try {
|
||||||
val nullInstance = Instance(null, null, null, null, null, null, null, null)
|
val instanceDeferred = async {
|
||||||
val nullToken = Token(null, null, null, null, null)
|
pixelfedAPI.instance()
|
||||||
|
}
|
||||||
Single.zip(
|
val token = pixelfedAPI.obtainToken(
|
||||||
pixelfedAPI.instance().onErrorReturn { nullInstance },
|
|
||||||
pixelfedAPI.obtainToken(
|
|
||||||
clientId, clientSecret, "$oauthScheme://$PACKAGE_ID", SCOPE, code,
|
clientId, clientSecret, "$oauthScheme://$PACKAGE_ID", SCOPE, code,
|
||||||
"authorization_code"
|
"authorization_code"
|
||||||
).onErrorReturn { nullToken },
|
)
|
||||||
{ instance, token ->
|
if (token.access_token == null) {
|
||||||
// we get here when all results have come in:
|
return@launch failedRegistration(getString(R.string.token_error))
|
||||||
Pair(instance, token)
|
}
|
||||||
})
|
|
||||||
.subscribeOn(Schedulers.io())
|
val instance = instanceDeferred.await()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(object : SingleObserver<Pair<Instance, Token>> {
|
if (instance.uri == null) {
|
||||||
override fun onSuccess(triple: Pair<Instance, Token>) {
|
return@launch failedRegistration(getString(R.string.instance_error))
|
||||||
val (instance, token) = triple
|
|
||||||
if(token == nullToken || token.access_token == null){
|
|
||||||
return failedRegistration(getString(R.string.token_error))
|
|
||||||
} else if(instance == nullInstance || instance.uri == null){
|
|
||||||
return failedRegistration(getString(R.string.instance_error))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
storeInstance(db, instance)
|
storeInstance(db, instance)
|
||||||
storeUser(token.access_token, token.refresh_token, clientId, clientSecret, instance.uri)
|
storeUser(
|
||||||
|
token.access_token,
|
||||||
|
token.refresh_token,
|
||||||
|
clientId,
|
||||||
|
clientSecret,
|
||||||
|
instance.uri
|
||||||
|
)
|
||||||
wipeSharedSettings()
|
wipeSharedSettings()
|
||||||
}
|
} catch (exception: IOException) {
|
||||||
|
return@launch failedRegistration(getString(R.string.token_error))
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
} catch (exception: HttpException) {
|
||||||
Log.e("saveUserAndInstance", e.message.toString())
|
return@launch failedRegistration(getString(R.string.token_error))
|
||||||
failedRegistration(getString(R.string.token_error))
|
}
|
||||||
}
|
}
|
||||||
override fun onSubscribe(d: Disposable) {}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun failedRegistration(message: String = getString(R.string.registration_failed)) {
|
private fun failedRegistration(message: String = getString(R.string.registration_failed)) {
|
||||||
@ -294,13 +282,10 @@ class LoginActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun storeUser(accessToken: String, refreshToken: String?, clientId: String, clientSecret: String, instance: String) {
|
private suspend fun storeUser(accessToken: String, refreshToken: String?, clientId: String, clientSecret: String, instance: String) {
|
||||||
pixelfedAPI.verifyCredentials("Bearer $accessToken")
|
try {
|
||||||
.enqueue(object : Callback<Account> {
|
val user = pixelfedAPI.verifyCredentials("Bearer $accessToken")
|
||||||
override fun onResponse(call: Call<Account>, response: Response<Account>) {
|
|
||||||
if (response.body() != null && response.isSuccessful) {
|
|
||||||
db.userDao().deActivateActiveUsers()
|
db.userDao().deActivateActiveUsers()
|
||||||
val user = response.body() as Account
|
|
||||||
addUser(
|
addUser(
|
||||||
db,
|
db,
|
||||||
user,
|
user,
|
||||||
@ -315,11 +300,11 @@ class LoginActivity : BaseActivity() {
|
|||||||
val intent = Intent(this@LoginActivity, MainActivity::class.java)
|
val intent = Intent(this@LoginActivity, MainActivity::class.java)
|
||||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
} catch (exception: IOException) {
|
||||||
|
return failedRegistration(getString(R.string.verify_credentials))
|
||||||
|
} catch (exception: HttpException) {
|
||||||
|
return failedRegistration(getString(R.string.verify_credentials))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun onFailure(call: Call<Account>, t: Throwable) {
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.paging.ExperimentalPagingApi
|
import androidx.paging.ExperimentalPagingApi
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
@ -42,7 +43,9 @@ import kotlinx.android.synthetic.main.activity_main.*
|
|||||||
import org.ligi.tracedroid.sending.TraceDroidEmailSender
|
import org.ligi.tracedroid.sending.TraceDroidEmailSender
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Callback
|
import retrofit2.Callback
|
||||||
|
import retrofit2.HttpException
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
class MainActivity : BaseActivity() {
|
class MainActivity : BaseActivity() {
|
||||||
|
|
||||||
@ -188,23 +191,18 @@ class MainActivity : BaseActivity() {
|
|||||||
val clientId = user?.clientId.orEmpty()
|
val clientId = user?.clientId.orEmpty()
|
||||||
val clientSecret = user?.clientSecret.orEmpty()
|
val clientSecret = user?.clientSecret.orEmpty()
|
||||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||||
api.verifyCredentials("Bearer $accessToken")
|
|
||||||
.enqueue(object : Callback<Account> {
|
lifecycleScope.launchWhenCreated {
|
||||||
override fun onResponse(
|
try {
|
||||||
call: Call<Account>,
|
val account = api.verifyCredentials("Bearer $accessToken")
|
||||||
response: Response<Account>
|
|
||||||
) {
|
|
||||||
if (response.body() != null && response.isSuccessful) {
|
|
||||||
val account = response.body() as Account
|
|
||||||
addUser(db, account, domain, accessToken = accessToken, refreshToken = refreshToken, clientId = clientId, clientSecret = clientSecret)
|
addUser(db, account, domain, accessToken = accessToken, refreshToken = refreshToken, clientId = clientId, clientSecret = clientSecret)
|
||||||
fillDrawerAccountInfo(account.id!!)
|
fillDrawerAccountInfo(account.id!!)
|
||||||
|
} catch (exception: IOException) {
|
||||||
|
Log.e("ACCOUNT UPDATE:", exception.toString())
|
||||||
|
} catch (exception: HttpException) {
|
||||||
|
Log.e("ACCOUNT UPDATE:", exception.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<Account>, t: Throwable) {
|
|
||||||
Log.e("DRAWER ACCOUNT:", t.toString())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class PostFragment : BaseFragment() {
|
|||||||
|
|
||||||
val user = db.userDao().getActiveUser()!!
|
val user = db.userDao().getActiveUser()!!
|
||||||
|
|
||||||
val api = apiHolder.api ?: apiHolder.setDomain(user)
|
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||||
|
|
||||||
val holder = StatusViewHolder(root)
|
val holder = StatusViewHolder(root)
|
||||||
|
|
||||||
|
@ -89,8 +89,7 @@ class PostFeedFragment<T: FeedContentDatabase>: CachedFeedFragment<T>() {
|
|||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
val uiModel = getItem(position) as Status
|
val uiModel = getItem(position) as Status
|
||||||
uiModel.let {
|
uiModel.let {
|
||||||
val user = db.userDao().getActiveUser()!!
|
(holder as StatusViewHolder).bind(it, apiHolder.setDomainToCurrentUser(db), db, lifecycleScope)
|
||||||
(holder as StatusViewHolder).bind(it, apiHolder.setDomain(user), db, lifecycleScope)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,8 +79,7 @@ class SearchPostsFragment : UncachedFeedFragment<Status>() {
|
|||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
val uiModel = getItem(position) as Status
|
val uiModel = getItem(position) as Status
|
||||||
uiModel.let {
|
uiModel.let {
|
||||||
val user = db.userDao().getActiveUser()!!
|
(holder as StatusViewHolder).bind(it, apiHolder.setDomainToCurrentUser(db), db, lifecycleScope)
|
||||||
(holder as StatusViewHolder).bind(it, apiHolder.setDomain(user), db, lifecycleScope)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import android.widget.*
|
|||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
@ -22,9 +23,12 @@ import com.h.pixeldroid.posts.parseHTMLText
|
|||||||
import com.h.pixeldroid.utils.BaseActivity
|
import com.h.pixeldroid.utils.BaseActivity
|
||||||
import com.h.pixeldroid.utils.ImageConverter
|
import com.h.pixeldroid.utils.ImageConverter
|
||||||
import com.h.pixeldroid.utils.openUrl
|
import com.h.pixeldroid.utils.openUrl
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Callback
|
import retrofit2.Callback
|
||||||
|
import retrofit2.HttpException
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
class ProfileActivity : BaseActivity() {
|
class ProfileActivity : BaseActivity() {
|
||||||
private lateinit var pixelfedAPI : PixelfedAPI
|
private lateinit var pixelfedAPI : PixelfedAPI
|
||||||
@ -75,27 +79,21 @@ class ProfileActivity : BaseActivity() {
|
|||||||
setViews(account)
|
setViews(account)
|
||||||
setPosts(account)
|
setPosts(account)
|
||||||
} else {
|
} else {
|
||||||
|
lifecycleScope.launchWhenResumed {
|
||||||
|
val myAccount: Account = try {
|
||||||
pixelfedAPI.verifyCredentials("Bearer $accessToken")
|
pixelfedAPI.verifyCredentials("Bearer $accessToken")
|
||||||
.enqueue(object : Callback<Account> {
|
} catch (exception: IOException) {
|
||||||
override fun onResponse(call: Call<Account>, response: Response<Account>) {
|
Log.e("ProfileActivity:", exception.toString())
|
||||||
if (response.code() == 200) {
|
return@launchWhenResumed showError()
|
||||||
val myAccount = response.body()!!
|
} catch (exception: HttpException) {
|
||||||
|
return@launchWhenResumed showError()
|
||||||
|
}
|
||||||
setViews(myAccount)
|
setViews(myAccount)
|
||||||
// Populate profile page with user's posts
|
// Populate profile page with user's posts
|
||||||
setPosts(myAccount)
|
setPosts(myAccount)
|
||||||
} else {
|
|
||||||
showError()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(call: Call<Account>, t: Throwable) {
|
|
||||||
Log.e("ProfileActivity:", t.toString())
|
|
||||||
showError()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//if we aren't viewing our own account, activate follow button
|
//if we aren't viewing our own account, activate follow button
|
||||||
if(account != null && account.id != user?.user_id) activateFollow(account)
|
if(account != null && account.id != user?.user_id) activateFollow(account)
|
||||||
//if we *are* viewing our own account, activate the edit button
|
//if we *are* viewing our own account, activate the edit button
|
||||||
@ -244,40 +242,35 @@ class ProfileActivity : BaseActivity() {
|
|||||||
*/
|
*/
|
||||||
private fun activateFollow(account: Account) {
|
private fun activateFollow(account: Account) {
|
||||||
// Get relationship between the two users (credential and this) and set followButton accordingly
|
// Get relationship between the two users (credential and this) and set followButton accordingly
|
||||||
pixelfedAPI.checkRelationships("Bearer $accessToken", listOf(account.id.orEmpty()))
|
lifecycleScope.launch {
|
||||||
.enqueue(object : Callback<List<Relationship>> {
|
try {
|
||||||
|
val relationship = pixelfedAPI.checkRelationships(
|
||||||
|
"Bearer $accessToken", listOf(account.id.orEmpty())
|
||||||
|
).firstOrNull()
|
||||||
|
|
||||||
override fun onFailure(call: Call<List<Relationship>>, t: Throwable) {
|
if(relationship != null){
|
||||||
Log.e("FOLLOW ERROR", t.toString())
|
|
||||||
Toast.makeText(
|
|
||||||
applicationContext, getString(R.string.follow_status_failed),
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResponse(
|
|
||||||
call: Call<List<Relationship>>,
|
|
||||||
response: Response<List<Relationship>>
|
|
||||||
) {
|
|
||||||
if (response.code() == 200) {
|
|
||||||
if (response.body()!!.isNotEmpty()) {
|
|
||||||
val followButton = findViewById<Button>(R.id.followButton)
|
val followButton = findViewById<Button>(R.id.followButton)
|
||||||
|
|
||||||
if (response.body()!![0].following) {
|
if (relationship.following) {
|
||||||
setOnClickUnfollow(account)
|
setOnClickUnfollow(account)
|
||||||
} else {
|
} else {
|
||||||
setOnClickFollow(account)
|
setOnClickFollow(account)
|
||||||
}
|
}
|
||||||
followButton.visibility = View.VISIBLE
|
followButton.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
} else {
|
} catch (exception: IOException) {
|
||||||
|
Log.e("FOLLOW ERROR", exception.toString())
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext, getString(R.string.follow_status_failed),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
} catch (exception: HttpException) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext, getString(R.string.follow_button_failed),
|
applicationContext, getString(R.string.follow_button_failed),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setOnClickFollow(account: Account) {
|
private fun setOnClickFollow(account: Account) {
|
||||||
@ -286,32 +279,24 @@ class ProfileActivity : BaseActivity() {
|
|||||||
followButton.setText(R.string.follow)
|
followButton.setText(R.string.follow)
|
||||||
|
|
||||||
followButton.setOnClickListener {
|
followButton.setOnClickListener {
|
||||||
|
lifecycleScope.launchWhenResumed {
|
||||||
|
try {
|
||||||
pixelfedAPI.follow(account.id.orEmpty(), "Bearer $accessToken")
|
pixelfedAPI.follow(account.id.orEmpty(), "Bearer $accessToken")
|
||||||
.enqueue(object : Callback<Relationship> {
|
setOnClickUnfollow(account)
|
||||||
|
} catch (exception: IOException) {
|
||||||
override fun onFailure(call: Call<Relationship>, t: Throwable) {
|
Log.e("FOLLOW ERROR", exception.toString())
|
||||||
Log.e("FOLLOW ERROR", t.toString())
|
Toast.makeText(
|
||||||
|
applicationContext, getString(R.string.follow_error),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
} catch (exception: HttpException) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext, getString(R.string.follow_error),
|
applicationContext, getString(R.string.follow_error),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(
|
|
||||||
call: Call<Relationship>,
|
|
||||||
response: Response<Relationship>
|
|
||||||
) {
|
|
||||||
if (response.code() == 200) {
|
|
||||||
setOnClickUnfollow(account)
|
|
||||||
} else if (response.code() == 403) {
|
|
||||||
Toast.makeText(
|
|
||||||
applicationContext, getString(R.string.action_not_allowed),
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setOnClickUnfollow(account: Account) {
|
private fun setOnClickUnfollow(account: Account) {
|
||||||
@ -320,31 +305,24 @@ class ProfileActivity : BaseActivity() {
|
|||||||
followButton.setText(R.string.unfollow)
|
followButton.setText(R.string.unfollow)
|
||||||
|
|
||||||
followButton.setOnClickListener {
|
followButton.setOnClickListener {
|
||||||
pixelfedAPI.unfollow(account.id.orEmpty(), "Bearer $accessToken")
|
|
||||||
.enqueue(object : Callback<Relationship> {
|
|
||||||
|
|
||||||
override fun onFailure(call: Call<Relationship>, t: Throwable) {
|
lifecycleScope.launchWhenResumed {
|
||||||
Log.e("UNFOLLOW ERROR", t.toString())
|
try {
|
||||||
|
pixelfedAPI.unfollow(account.id.orEmpty(), "Bearer $accessToken")
|
||||||
|
setOnClickFollow(account)
|
||||||
|
} catch (exception: IOException) {
|
||||||
|
Log.e("FOLLOW ERROR", exception.toString())
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext, getString(R.string.unfollow_error),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
} catch (exception: HttpException) {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
applicationContext, getString(R.string.unfollow_error),
|
applicationContext, getString(R.string.unfollow_error),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
override fun onResponse(
|
|
||||||
call: Call<Relationship>,
|
|
||||||
response: Response<Relationship>
|
|
||||||
) {
|
|
||||||
if (response.code() == 200) {
|
|
||||||
setOnClickFollow(account)
|
|
||||||
} else if (response.code() == 401) {
|
|
||||||
Toast.makeText(
|
|
||||||
applicationContext, getString(R.string.access_token_invalid),
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package com.h.pixeldroid.utils.api
|
|||||||
import com.h.pixeldroid.utils.api.objects.*
|
import com.h.pixeldroid.utils.api.objects.*
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
import okhttp3.MultipartBody
|
import okhttp3.MultipartBody
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Response
|
import retrofit2.Response
|
||||||
@ -35,17 +36,17 @@ interface PixelfedAPI {
|
|||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST("/api/v1/apps")
|
@POST("/api/v1/apps")
|
||||||
fun registerApplication(
|
suspend fun registerApplication(
|
||||||
@Field("client_name") client_name: String,
|
@Field("client_name") client_name: String,
|
||||||
@Field("redirect_uris") redirect_uris: String,
|
@Field("redirect_uris") redirect_uris: String,
|
||||||
@Field("scopes") scopes: String? = null,
|
@Field("scopes") scopes: String? = null,
|
||||||
@Field("website") website: String? = null
|
@Field("website") website: String? = null
|
||||||
): Single<Application>
|
): Application
|
||||||
|
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST("/oauth/token")
|
@POST("/oauth/token")
|
||||||
fun obtainToken(
|
suspend fun obtainToken(
|
||||||
@Field("client_id") client_id: String,
|
@Field("client_id") client_id: String,
|
||||||
@Field("client_secret") client_secret: String,
|
@Field("client_secret") client_secret: String,
|
||||||
@Field("redirect_uri") redirect_uri: String? = null,
|
@Field("redirect_uri") redirect_uri: String? = null,
|
||||||
@ -53,41 +54,41 @@ interface PixelfedAPI {
|
|||||||
@Field("code") code: String? = null,
|
@Field("code") code: String? = null,
|
||||||
@Field("grant_type") grant_type: String? = null,
|
@Field("grant_type") grant_type: String? = null,
|
||||||
@Field("refresh_token") refresh_token: String? = null
|
@Field("refresh_token") refresh_token: String? = null
|
||||||
): Single<Token>
|
): Token
|
||||||
|
|
||||||
// get instance configuration
|
// get instance configuration
|
||||||
@GET("/api/v1/instance")
|
@GET("/api/v1/instance")
|
||||||
fun instance() : Single<Instance>
|
suspend fun instance() : Instance
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance info from the Nodeinfo .well_known (https://nodeinfo.diaspora.software/protocol.html) endpoint
|
* Instance info from the Nodeinfo .well_known (https://nodeinfo.diaspora.software/protocol.html) endpoint
|
||||||
*/
|
*/
|
||||||
@GET("/.well-known/nodeinfo")
|
@GET("/.well-known/nodeinfo")
|
||||||
fun wellKnownNodeInfo() : Single<NodeInfoJRD>
|
suspend fun wellKnownNodeInfo() : NodeInfoJRD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance info from [NodeInfo] (https://nodeinfo.diaspora.software/schema.html) endpoint
|
* Instance info from [NodeInfo] (https://nodeinfo.diaspora.software/schema.html) endpoint
|
||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
fun nodeInfoSchema(
|
suspend fun nodeInfoSchema(
|
||||||
@Url nodeInfo_schema_url: String
|
@Url nodeInfo_schema_url: String
|
||||||
) : Call<NodeInfo>
|
) : NodeInfo
|
||||||
|
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST("/api/v1/accounts/{id}/follow")
|
@POST("/api/v1/accounts/{id}/follow")
|
||||||
fun follow(
|
suspend fun follow(
|
||||||
//The authorization header needs to be of the form "Bearer <token>"
|
//The authorization header needs to be of the form "Bearer <token>"
|
||||||
@Path("id") statusId: String,
|
@Path("id") statusId: String,
|
||||||
@Header("Authorization") authorization: String,
|
@Header("Authorization") authorization: String,
|
||||||
@Field("reblogs") reblogs : Boolean = true
|
@Field("reblogs") reblogs : Boolean = true
|
||||||
) : Call<Relationship>
|
) : Relationship
|
||||||
|
|
||||||
@POST("/api/v1/accounts/{id}/unfollow")
|
@POST("/api/v1/accounts/{id}/unfollow")
|
||||||
fun unfollow(
|
suspend fun unfollow(
|
||||||
//The authorization header needs to be of the form "Bearer <token>"
|
//The authorization header needs to be of the form "Bearer <token>"
|
||||||
@Path("id") statusId: String,
|
@Path("id") statusId: String,
|
||||||
@Header("Authorization") authorization: String
|
@Header("Authorization") authorization: String
|
||||||
) : Call<Relationship>
|
) : Relationship
|
||||||
|
|
||||||
@POST("api/v1/statuses/{id}/favourite")
|
@POST("api/v1/statuses/{id}/favourite")
|
||||||
fun likePost(
|
fun likePost(
|
||||||
@ -205,10 +206,11 @@ interface PixelfedAPI {
|
|||||||
): List<Notification>
|
): List<Notification>
|
||||||
|
|
||||||
@GET("/api/v1/accounts/verify_credentials")
|
@GET("/api/v1/accounts/verify_credentials")
|
||||||
fun verifyCredentials(
|
suspend fun verifyCredentials(
|
||||||
//The authorization header needs to be of the form "Bearer <token>"
|
//The authorization header needs to be of the form "Bearer <token>"
|
||||||
@Header("Authorization") authorization: String
|
@Header("Authorization") authorization: String
|
||||||
): Call<Account>
|
): Account
|
||||||
|
|
||||||
|
|
||||||
@GET("/api/v1/accounts/{id}/statuses")
|
@GET("/api/v1/accounts/{id}/statuses")
|
||||||
fun accountPosts(
|
fun accountPosts(
|
||||||
@ -217,10 +219,10 @@ interface PixelfedAPI {
|
|||||||
): Call<List<Status>>
|
): Call<List<Status>>
|
||||||
|
|
||||||
@GET("/api/v1/accounts/relationships")
|
@GET("/api/v1/accounts/relationships")
|
||||||
fun checkRelationships(
|
suspend fun checkRelationships(
|
||||||
@Header("Authorization") authorization : String,
|
@Header("Authorization") authorization : String,
|
||||||
@Query("id[]") account_ids : List<String>
|
@Query("id[]") account_ids : List<String>
|
||||||
) : Call<List<Relationship>>
|
) : List<Relationship>
|
||||||
|
|
||||||
@GET("/api/v1/accounts/{id}/followers")
|
@GET("/api/v1/accounts/{id}/followers")
|
||||||
suspend fun followers(
|
suspend fun followers(
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package com.h.pixeldroid.utils.db.dao
|
package com.h.pixeldroid.utils.db.dao
|
||||||
|
|
||||||
import androidx.room.Dao
|
import androidx.room.*
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.OnConflictStrategy
|
|
||||||
import androidx.room.Query
|
|
||||||
import com.h.pixeldroid.utils.db.entities.UserDatabaseEntity
|
import com.h.pixeldroid.utils.db.entities.UserDatabaseEntity
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@ -11,6 +8,9 @@ interface UserDao {
|
|||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insertUser(user: UserDatabaseEntity)
|
fun insertUser(user: UserDatabaseEntity)
|
||||||
|
|
||||||
|
@Query("UPDATE users SET accessToken = :accessToken WHERE user_id = :id and instance_uri = :instance_uri")
|
||||||
|
fun updateAccessToken(accessToken: String, id: String, instance_uri: String)
|
||||||
|
|
||||||
@Query("SELECT * FROM users")
|
@Query("SELECT * FROM users")
|
||||||
fun getAll(): List<UserDatabaseEntity>
|
fun getAll(): List<UserDatabaseEntity>
|
||||||
|
|
||||||
|
@ -2,9 +2,11 @@ package com.h.pixeldroid.utils.di
|
|||||||
|
|
||||||
import com.h.pixeldroid.utils.api.PixelfedAPI
|
import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||||
import com.h.pixeldroid.utils.db.AppDatabase
|
import com.h.pixeldroid.utils.db.AppDatabase
|
||||||
|
import com.h.pixeldroid.utils.db.addUser
|
||||||
import com.h.pixeldroid.utils.db.entities.UserDatabaseEntity
|
import com.h.pixeldroid.utils.db.entities.UserDatabaseEntity
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||||
@ -18,11 +20,11 @@ class APIModule{
|
|||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun providesAPIHolder(db: AppDatabase): PixelfedAPIHolder {
|
fun providesAPIHolder(db: AppDatabase): PixelfedAPIHolder {
|
||||||
return PixelfedAPIHolder(db.userDao().getActiveUser())
|
return PixelfedAPIHolder(db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TokenAuthenticator(val user: UserDatabaseEntity) : Authenticator {
|
class TokenAuthenticator(val user: UserDatabaseEntity, val db: AppDatabase) : Authenticator {
|
||||||
|
|
||||||
private val pixelfedAPI = PixelfedAPI.createFromUrl(user.instance_uri)
|
private val pixelfedAPI = PixelfedAPI.createFromUrl(user.instance_uri)
|
||||||
|
|
||||||
@ -32,36 +34,47 @@ class TokenAuthenticator(val user: UserDatabaseEntity) : Authenticator {
|
|||||||
return null // Give up, we've already failed to authenticate.
|
return null // Give up, we've already failed to authenticate.
|
||||||
}
|
}
|
||||||
// Refresh the access_token using a synchronous api request
|
// Refresh the access_token using a synchronous api request
|
||||||
val newAccessToken: String = try {
|
val newAccessToken: String? = try {
|
||||||
|
runBlocking {
|
||||||
pixelfedAPI.obtainToken(
|
pixelfedAPI.obtainToken(
|
||||||
scope = "", grant_type = "refresh_token",
|
scope = "",
|
||||||
refresh_token = user.refreshToken, client_id = user.clientId, client_secret = user.clientSecret
|
grant_type = "refresh_token",
|
||||||
).blockingGet().access_token
|
refresh_token = user.refreshToken,
|
||||||
|
client_id = user.clientId,
|
||||||
|
client_secret = user.clientSecret
|
||||||
|
).access_token
|
||||||
|
}
|
||||||
}catch (e: Exception){
|
}catch (e: Exception){
|
||||||
null
|
null
|
||||||
}.orEmpty()
|
}
|
||||||
|
|
||||||
|
if (newAccessToken != null) {
|
||||||
|
db.userDao().updateAccessToken(newAccessToken, user.user_id, user.instance_uri)
|
||||||
|
}
|
||||||
|
|
||||||
// Add new header to rejected request and retry it
|
// Add new header to rejected request and retry it
|
||||||
return response.request.newBuilder()
|
return response.request.newBuilder()
|
||||||
.header("Authorization", "Bearer $newAccessToken")
|
.header("Authorization", "Bearer ${newAccessToken.orEmpty()}")
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PixelfedAPIHolder(user: UserDatabaseEntity?){
|
class PixelfedAPIHolder(db: AppDatabase?){
|
||||||
private val intermediate: Retrofit.Builder = Retrofit.Builder()
|
private val intermediate: Retrofit.Builder = Retrofit.Builder()
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||||
var api: PixelfedAPI? = if (user != null) setDomain(user) else null
|
var api: PixelfedAPI? =
|
||||||
|
db?.userDao()?.getActiveUser()?.let {
|
||||||
fun setDomainToCurrentUser(db: AppDatabase): PixelfedAPI {
|
setDomainToCurrentUser(db, it)
|
||||||
return setDomain(db.userDao().getActiveUser()!!)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDomain(user: UserDatabaseEntity): PixelfedAPI {
|
fun setDomainToCurrentUser(
|
||||||
|
db: AppDatabase,
|
||||||
|
user: UserDatabaseEntity = db.userDao().getActiveUser()!!
|
||||||
|
): PixelfedAPI {
|
||||||
val newAPI = intermediate
|
val newAPI = intermediate
|
||||||
.baseUrl(user.instance_uri)
|
.baseUrl(user.instance_uri)
|
||||||
.client(OkHttpClient().newBuilder().authenticator(TokenAuthenticator(user)).build())
|
.client(OkHttpClient().newBuilder().authenticator(TokenAuthenticator(user, db)).build())
|
||||||
.build().create(PixelfedAPI::class.java)
|
.build().create(PixelfedAPI::class.java)
|
||||||
api = newAPI
|
api = newAPI
|
||||||
return newAPI
|
return newAPI
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<string name="registration_failed">"Could not register the application with this server"</string>
|
<string name="registration_failed">"Could not register the application with this server"</string>
|
||||||
<string name="browser_launch_failed">"Could not launch a browser, do you have one?"</string>
|
<string name="browser_launch_failed">"Could not launch a browser, do you have one?"</string>
|
||||||
<string name="auth_failed">"Could not authenticate"</string>
|
<string name="auth_failed">"Could not authenticate"</string>
|
||||||
|
<string name="verify_credentials">"Could not get user information"</string>
|
||||||
<string name="token_error">"Error getting token"</string>
|
<string name="token_error">"Error getting token"</string>
|
||||||
<string name="instance_error">"Could not get instance information"</string>
|
<string name="instance_error">"Could not get instance information"</string>
|
||||||
<string name="instance_not_pixelfed_warning">"This doesn't seem to be a Pixelfed instance, so the app could break in unexpected ways."</string>
|
<string name="instance_not_pixelfed_warning">"This doesn't seem to be a Pixelfed instance, so the app could break in unexpected ways."</string>
|
||||||
|
@ -112,10 +112,11 @@ class APIUnitTest {
|
|||||||
.withHeader("Content-Type", "application/json")
|
.withHeader("Content-Type", "application/json")
|
||||||
.withBody(""" {"id":3197,"name":"Pixeldroid","website":null,"redirect_uri":"urn:ietf:wg:oauth:2.0:oob","client_id":3197,"client_secret":"hhRwLupqUJPghKsZzpZtxNV67g5DBdPYCqW6XE3m","vapid_key":null}"""
|
.withBody(""" {"id":3197,"name":"Pixeldroid","website":null,"redirect_uri":"urn:ietf:wg:oauth:2.0:oob","client_id":3197,"client_secret":"hhRwLupqUJPghKsZzpZtxNV67g5DBdPYCqW6XE3m","vapid_key":null}"""
|
||||||
)))
|
)))
|
||||||
val call: Single<Application> = PixelfedAPI.createFromUrl("http://localhost:8089")
|
val application: Application = runBlocking {
|
||||||
|
PixelfedAPI.createFromUrl("http://localhost:8089")
|
||||||
.registerApplication("Pixeldroid", "urn:ietf:wg:oauth:2.0:oob", "read write follow")
|
.registerApplication("Pixeldroid", "urn:ietf:wg:oauth:2.0:oob", "read write follow")
|
||||||
|
}
|
||||||
|
|
||||||
val application: Application = call.toFuture().get()
|
|
||||||
assertEquals("3197", application.client_id)
|
assertEquals("3197", application.client_id)
|
||||||
assertEquals("hhRwLupqUJPghKsZzpZtxNV67g5DBdPYCqW6XE3m", application.client_secret)
|
assertEquals("hhRwLupqUJPghKsZzpZtxNV67g5DBdPYCqW6XE3m", application.client_secret)
|
||||||
assertEquals("Pixeldroid", application.name)
|
assertEquals("Pixeldroid", application.name)
|
||||||
@ -141,10 +142,14 @@ class APIUnitTest {
|
|||||||
val OAUTH_SCHEME = "oauth2redirect"
|
val OAUTH_SCHEME = "oauth2redirect"
|
||||||
val SCOPE = "read write follow"
|
val SCOPE = "read write follow"
|
||||||
val PACKAGE_ID = "com.h.pixeldroid"
|
val PACKAGE_ID = "com.h.pixeldroid"
|
||||||
val call: Single<Token> = PixelfedAPI.createFromUrl("http://localhost:8089")
|
|
||||||
.obtainToken("123", "ssqdfqsdfqds", "$OAUTH_SCHEME://$PACKAGE_ID", SCOPE, "abc",
|
val token: Token = runBlocking {
|
||||||
"authorization_code")
|
PixelfedAPI.createFromUrl("http://localhost:8089")
|
||||||
val token: Token = call.toFuture().get()
|
.obtainToken(
|
||||||
|
"123", "ssqdfqsdfqds", "$OAUTH_SCHEME://$PACKAGE_ID", SCOPE, "abc",
|
||||||
|
"authorization_code"
|
||||||
|
)
|
||||||
|
}
|
||||||
assertEquals("ZA-Yj3aBD8U8Cm7lKUp-lm9O9BmDgdhHzDeqsY8tlL0", token.access_token)
|
assertEquals("ZA-Yj3aBD8U8Cm7lKUp-lm9O9BmDgdhHzDeqsY8tlL0", token.access_token)
|
||||||
assertEquals("Bearer", token.token_type)
|
assertEquals("Bearer", token.token_type)
|
||||||
assertEquals("read write follow push", token.scope)
|
assertEquals("read write follow push", token.scope)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user