Merge branch 'token_consistency' into 'master'
Better token refresh, refactor auth token with interceptor See merge request pixeldroid/PixelDroid!326
This commit is contained in:
commit
bccf57f918
@ -185,16 +185,17 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
private fun getUpdatedAccount() {
|
||||
if (hasInternet(applicationContext)) {
|
||||
val domain = user?.instance_uri.orEmpty()
|
||||
val accessToken = user?.accessToken.orEmpty()
|
||||
val refreshToken = user?.refreshToken
|
||||
val clientId = user?.clientId.orEmpty()
|
||||
val clientSecret = user?.clientSecret.orEmpty()
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
try {
|
||||
val account = api.verifyCredentials("Bearer $accessToken")
|
||||
val domain = user?.instance_uri.orEmpty()
|
||||
val accessToken = user?.accessToken.orEmpty()
|
||||
val refreshToken = user?.refreshToken
|
||||
val clientId = user?.clientId.orEmpty()
|
||||
val clientSecret = user?.clientSecret.orEmpty()
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
val account = api.verifyCredentials()
|
||||
addUser(db, account, domain, accessToken = accessToken, refreshToken = refreshToken, clientId = clientId, clientSecret = clientSecret)
|
||||
fillDrawerAccountInfo(account.id!!)
|
||||
} catch (exception: IOException) {
|
||||
|
@ -29,7 +29,6 @@ import com.h.pixeldroid.postCreation.carousel.CarouselItem
|
||||
import com.h.pixeldroid.postCreation.carousel.ImageCarousel
|
||||
import com.h.pixeldroid.postCreation.photoEdit.PhotoEditActivity
|
||||
import com.h.pixeldroid.utils.BaseActivity
|
||||
import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||
import com.h.pixeldroid.utils.api.objects.Attachment
|
||||
import com.h.pixeldroid.utils.db.entities.InstanceDatabaseEntity
|
||||
import com.h.pixeldroid.utils.db.entities.UserDatabaseEntity
|
||||
@ -58,8 +57,6 @@ data class PhotoData(
|
||||
|
||||
class PostCreationActivity : BaseActivity() {
|
||||
|
||||
private lateinit var accessToken: String
|
||||
|
||||
private var user: UserDatabaseEntity? = null
|
||||
private lateinit var instance: InstanceDatabaseEntity
|
||||
|
||||
@ -85,8 +82,6 @@ class PostCreationActivity : BaseActivity() {
|
||||
// get image URIs
|
||||
intent.clipData?.let { addPossibleImages(it) }
|
||||
|
||||
accessToken = user?.accessToken.orEmpty()
|
||||
|
||||
val carousel: ImageCarousel = binding.carousel
|
||||
carousel.addData(photoData.map { CarouselItem(it.imageUri) })
|
||||
carousel.layoutCarouselCallback = {
|
||||
@ -338,7 +333,7 @@ class PostCreationActivity : BaseActivity() {
|
||||
val description = data.imageDescription?.let { MultipartBody.Part.createFormData("description", it) }
|
||||
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
val inter = api.mediaUpload("Bearer $accessToken", description, requestBody.parts[0])
|
||||
val inter = api.mediaUpload(description, requestBody.parts[0])
|
||||
|
||||
postSub = inter
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -383,7 +378,6 @@ class PostCreationActivity : BaseActivity() {
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
api.postStatus(
|
||||
authorization = "Bearer $accessToken",
|
||||
statusText = description,
|
||||
media_ids = photoData.mapNotNull { it.uploadId }.toList()
|
||||
)
|
||||
|
@ -12,13 +12,13 @@ import android.view.View
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.text.toSpanned
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||
import com.h.pixeldroid.utils.api.objects.Account.Companion.openAccountFromId
|
||||
import com.h.pixeldroid.utils.api.objects.Mention
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import com.h.pixeldroid.utils.db.AppDatabase
|
||||
import com.h.pixeldroid.utils.di.PixelfedAPIHolder
|
||||
import java.net.URI
|
||||
import java.net.URISyntaxException
|
||||
import java.text.ParseException
|
||||
@ -50,12 +50,12 @@ fun getDomain(urlString: String?): String {
|
||||
}
|
||||
|
||||
fun parseHTMLText(
|
||||
text : String,
|
||||
mentions: List<Mention>?,
|
||||
api : PixelfedAPI,
|
||||
context: Context,
|
||||
credential: String,
|
||||
lifecycleScope: LifecycleCoroutineScope
|
||||
text: String,
|
||||
mentions: List<Mention>?,
|
||||
apiHolder: PixelfedAPIHolder,
|
||||
context: Context,
|
||||
lifecycleScope: LifecycleCoroutineScope,
|
||||
db: AppDatabase
|
||||
) : Spanned {
|
||||
//Convert text to spannable
|
||||
val content = fromHtml(text)
|
||||
@ -108,7 +108,8 @@ fun parseHTMLText(
|
||||
Log.e("MENTION", "CLICKED")
|
||||
//Retrieve the account for the given profile
|
||||
lifecycleScope.launchWhenCreated {
|
||||
openAccountFromId(accountId, api, context, credential)
|
||||
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
openAccountFromId(accountId, api, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import java.io.IOException
|
||||
|
||||
class PostActivity : BaseActivity() {
|
||||
lateinit var domain : String
|
||||
private lateinit var accessToken : String
|
||||
|
||||
private lateinit var binding: ActivityPostBinding
|
||||
|
||||
@ -45,17 +44,15 @@ class PostActivity : BaseActivity() {
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
domain = user?.instance_uri.orEmpty()
|
||||
accessToken = user?.accessToken.orEmpty()
|
||||
|
||||
|
||||
supportActionBar?.title = getString(R.string.post_title).format(status.account?.getDisplayName())
|
||||
|
||||
val holder = StatusViewHolder(binding.postFragmentSingle)
|
||||
|
||||
holder.bind(status, apiHolder.api!!, db, lifecycleScope, displayDimensionsInPx(), isActivity = true)
|
||||
holder.bind(status, apiHolder, db, lifecycleScope, displayDimensionsInPx(), isActivity = true)
|
||||
|
||||
val credential = "Bearer $accessToken"
|
||||
activateCommenter(credential)
|
||||
activateCommenter()
|
||||
|
||||
if(viewComments || postComment){
|
||||
//Scroll already down as much as possible (since comments are not loaded yet)
|
||||
@ -68,10 +65,10 @@ class PostActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
// also retrieve comments if we're not posting the comment
|
||||
if(!postComment) retrieveComments(apiHolder.api!!, credential)
|
||||
if(!postComment) retrieveComments(apiHolder.api!!)
|
||||
}
|
||||
binding.postFragmentSingle.viewComments.setOnClickListener {
|
||||
retrieveComments(apiHolder.api!!, credential)
|
||||
retrieveComments(apiHolder.api!!)
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +77,7 @@ class PostActivity : BaseActivity() {
|
||||
return true
|
||||
}
|
||||
|
||||
private fun activateCommenter(credential: String) {
|
||||
private fun activateCommenter() {
|
||||
//Activate commenter
|
||||
binding.submitComment.setOnClickListener {
|
||||
val textIn = binding.editComment.text
|
||||
@ -94,15 +91,14 @@ class PostActivity : BaseActivity() {
|
||||
} else {
|
||||
//Post the comment
|
||||
lifecycleScope.launchWhenCreated {
|
||||
apiHolder.api?.let { it1 -> postComment(it1, credential) }
|
||||
apiHolder.api?.let { it1 -> postComment(it1) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addComment(context: Context, commentContainer: LinearLayout,
|
||||
commentUsername: String, commentContent: String, mentions: List<Mention>,
|
||||
credential: String) {
|
||||
commentUsername: String, commentContent: String, mentions: List<Mention>) {
|
||||
|
||||
|
||||
val itemBinding = CommentBinding.inflate(
|
||||
@ -113,25 +109,29 @@ class PostActivity : BaseActivity() {
|
||||
itemBinding.commentText.text = parseHTMLText(
|
||||
commentContent,
|
||||
mentions,
|
||||
apiHolder.api!!,
|
||||
apiHolder,
|
||||
context,
|
||||
credential,
|
||||
lifecycleScope
|
||||
lifecycleScope,
|
||||
db
|
||||
)
|
||||
}
|
||||
|
||||
private fun retrieveComments(api: PixelfedAPI, credential: String) {
|
||||
private fun retrieveComments(api: PixelfedAPI) {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
status.id.let {
|
||||
try {
|
||||
val statuses = api.statusComments(it, credential).descendants
|
||||
val statuses = api.statusComments(it).descendants
|
||||
|
||||
binding.commentContainer.removeAllViews()
|
||||
|
||||
//Create the new views for each comment
|
||||
for (status in statuses) {
|
||||
addComment(binding.root.context, binding.commentContainer, status.account!!.username!!,
|
||||
status.content!!, status.mentions.orEmpty(), credential
|
||||
addComment(
|
||||
binding.root.context,
|
||||
binding.commentContainer,
|
||||
status.account!!.username!!,
|
||||
status.content!!,
|
||||
status.mentions.orEmpty()
|
||||
)
|
||||
}
|
||||
binding.commentContainer.visibility = View.VISIBLE
|
||||
@ -149,19 +149,18 @@ class PostActivity : BaseActivity() {
|
||||
|
||||
private suspend fun postComment(
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
) {
|
||||
val textIn = binding.editComment.text
|
||||
val nonNullText = textIn.toString()
|
||||
status.id.let {
|
||||
try {
|
||||
val response = api.postStatus(credential, nonNullText, it)
|
||||
val response = api.postStatus(nonNullText, it)
|
||||
binding.commentIn.visibility = View.GONE
|
||||
|
||||
//Add the comment to the comment section
|
||||
addComment(
|
||||
binding.root.context, binding.commentContainer, response.account!!.username!!,
|
||||
response.content!!, response.mentions.orEmpty(), credential
|
||||
response.content!!, response.mentions.orEmpty()
|
||||
)
|
||||
|
||||
Toast.makeText(
|
||||
|
@ -24,10 +24,6 @@ class ReportActivity : BaseActivity() {
|
||||
|
||||
val status = intent.getSerializableExtra(Status.POST_TAG) as Status?
|
||||
|
||||
//get the currently active user
|
||||
val user = db.userDao().getActiveUser()
|
||||
|
||||
|
||||
binding.reportTargetTextview.text = getString(R.string.report_target).format(status?.account?.acct)
|
||||
|
||||
|
||||
@ -37,12 +33,15 @@ class ReportActivity : BaseActivity() {
|
||||
|
||||
binding.textInputLayout.editText?.isEnabled = false
|
||||
|
||||
val accessToken = user?.accessToken.orEmpty()
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
try {
|
||||
api.report("Bearer $accessToken", status?.account?.id!!, listOf(status), binding.textInputLayout.editText?.text.toString())
|
||||
api.report(
|
||||
status?.account?.id!!,
|
||||
listOf(status),
|
||||
binding.textInputLayout.editText?.text.toString()
|
||||
)
|
||||
|
||||
reportStatus(true)
|
||||
} catch (exception: IOException) {
|
||||
|
@ -29,6 +29,7 @@ import com.h.pixeldroid.utils.api.objects.Status.Companion.POST_COMMENT_TAG
|
||||
import com.h.pixeldroid.utils.api.objects.Status.Companion.POST_TAG
|
||||
import com.h.pixeldroid.utils.api.objects.Status.Companion.VIEW_COMMENTS_TAG
|
||||
import com.h.pixeldroid.utils.db.AppDatabase
|
||||
import com.h.pixeldroid.utils.di.PixelfedAPIHolder
|
||||
import com.karumi.dexter.Dexter
|
||||
import com.karumi.dexter.listener.PermissionDeniedResponse
|
||||
import com.karumi.dexter.listener.PermissionGrantedResponse
|
||||
@ -46,7 +47,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
|
||||
private var status: Status? = null
|
||||
|
||||
fun bind(status: Status?, pixelfedAPI: PixelfedAPI, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope, displayDimensionsInPx: Pair<Int, Int>, isActivity: Boolean = false) {
|
||||
fun bind(status: Status?, pixelfedAPI: PixelfedAPIHolder, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope, displayDimensionsInPx: Pair<Int, Int>, isActivity: Boolean = false) {
|
||||
|
||||
this.itemView.visibility = View.VISIBLE
|
||||
this.status = status
|
||||
@ -177,9 +178,9 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
}
|
||||
|
||||
private fun setDescription(
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
lifecycleScope: LifecycleCoroutineScope
|
||||
apiHolder: PixelfedAPIHolder,
|
||||
lifecycleScope: LifecycleCoroutineScope,
|
||||
db: AppDatabase
|
||||
) {
|
||||
binding.description.apply {
|
||||
if (status?.content.isNullOrBlank()) {
|
||||
@ -188,10 +189,10 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
text = parseHTMLText(
|
||||
status?.content.orEmpty(),
|
||||
status?.mentions,
|
||||
api,
|
||||
apiHolder,
|
||||
binding.root.context,
|
||||
credential,
|
||||
lifecycleScope
|
||||
lifecycleScope,
|
||||
db
|
||||
)
|
||||
movementMethod = LinkMovementMethod.getInstance()
|
||||
}
|
||||
@ -199,25 +200,20 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
}
|
||||
//region buttons
|
||||
private fun activateButtons(
|
||||
api: PixelfedAPI,
|
||||
apiHolder: PixelfedAPIHolder,
|
||||
db: AppDatabase,
|
||||
lifecycleScope: LifecycleCoroutineScope,
|
||||
isActivity: Boolean
|
||||
){
|
||||
val user = db.userDao().getActiveUser()!!
|
||||
|
||||
val credential = "Bearer ${user.accessToken}"
|
||||
//Set the special HTML text
|
||||
setDescription(api, credential, lifecycleScope)
|
||||
setDescription(apiHolder, lifecycleScope, db)
|
||||
|
||||
//Activate onclickListeners
|
||||
activateLiker(
|
||||
api, credential, status?.favourited ?: false,
|
||||
lifecycleScope
|
||||
apiHolder, status?.favourited ?: false, lifecycleScope, db
|
||||
)
|
||||
activateReblogger(
|
||||
api, credential, status?.reblogged ?: false,
|
||||
lifecycleScope
|
||||
apiHolder, status?.reblogged ?: false, lifecycleScope, db
|
||||
)
|
||||
|
||||
if(isActivity){
|
||||
@ -237,14 +233,14 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
|
||||
showComments(lifecycleScope, isActivity)
|
||||
|
||||
activateMoreButton(api, db, lifecycleScope)
|
||||
activateMoreButton(apiHolder, db, lifecycleScope)
|
||||
}
|
||||
|
||||
private fun activateReblogger(
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
isReblogged: Boolean,
|
||||
lifecycleScope: LifecycleCoroutineScope
|
||||
apiHolder: PixelfedAPIHolder,
|
||||
isReblogged: Boolean,
|
||||
lifecycleScope: LifecycleCoroutineScope,
|
||||
db: AppDatabase
|
||||
) {
|
||||
binding.reblogger.apply {
|
||||
//Set initial button state
|
||||
@ -253,12 +249,13 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
//Activate the button
|
||||
setEventListener { _, buttonState ->
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
if (buttonState) {
|
||||
// Button is active
|
||||
undoReblogPost(api, credential)
|
||||
undoReblogPost(api)
|
||||
} else {
|
||||
// Button is inactive
|
||||
reblogPost(api, credential)
|
||||
reblogPost(api)
|
||||
}
|
||||
}
|
||||
//show animation or not?
|
||||
@ -267,15 +264,12 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun reblogPost(
|
||||
api: PixelfedAPI,
|
||||
credential: String
|
||||
) {
|
||||
private suspend fun reblogPost(api: PixelfedAPI) {
|
||||
//Call the api function
|
||||
status?.id?.let {
|
||||
|
||||
try {
|
||||
val resp = api.reblogStatus(credential, it)
|
||||
val resp = api.reblogStatus(it)
|
||||
|
||||
//Update shown share count
|
||||
binding.nshares.text = resp.getNShares(binding.root.context)
|
||||
@ -290,14 +284,11 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun undoReblogPost(
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
) {
|
||||
private suspend fun undoReblogPost(api: PixelfedAPI) {
|
||||
//Call the api function
|
||||
status?.id?.let {
|
||||
try {
|
||||
val resp = api.undoReblogStatus(credential, it)
|
||||
val resp = api.undoReblogStatus(it)
|
||||
|
||||
//Update shown share count
|
||||
binding.nshares.text = resp.getNShares(binding.root.context)
|
||||
@ -312,7 +303,7 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
}
|
||||
}
|
||||
|
||||
private fun activateMoreButton(api: PixelfedAPI, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope){
|
||||
private fun activateMoreButton(apiHolder: PixelfedAPIHolder, db: AppDatabase, lifecycleScope: LifecycleCoroutineScope){
|
||||
binding.statusMore.setOnClickListener {
|
||||
PopupMenu(it.context, it).apply {
|
||||
setOnMenuItemClickListener { item ->
|
||||
@ -395,7 +386,8 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
db.homePostDao().delete(id, user.user_id, user.instance_uri)
|
||||
db.publicPostDao().delete(id, user.user_id, user.instance_uri)
|
||||
try {
|
||||
api.deleteStatus("Bearer ${user.accessToken}", id)
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
api.deleteStatus(id)
|
||||
binding.root.visibility = View.GONE
|
||||
} catch (exception: HttpException) {
|
||||
Toast.makeText(
|
||||
@ -439,10 +431,10 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
}
|
||||
|
||||
private fun activateLiker(
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
isLiked: Boolean,
|
||||
lifecycleScope: LifecycleCoroutineScope
|
||||
apiHolder: PixelfedAPIHolder,
|
||||
isLiked: Boolean,
|
||||
lifecycleScope: LifecycleCoroutineScope,
|
||||
db: AppDatabase
|
||||
) {
|
||||
|
||||
binding.liker.apply {
|
||||
@ -452,12 +444,13 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
//Activate the liker
|
||||
setEventListener { _, buttonState ->
|
||||
lifecycleScope.launchWhenCreated {
|
||||
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
if (buttonState) {
|
||||
// Button is active, unlike
|
||||
unLikePostCall(api, credential)
|
||||
unLikePostCall(api)
|
||||
} else {
|
||||
// Button is inactive, like
|
||||
likePostCall(api, credential)
|
||||
likePostCall(api)
|
||||
}
|
||||
}
|
||||
//show animation or not?
|
||||
@ -473,15 +466,16 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
if(binding.sensitiveWarning.visibility == View.GONE) {
|
||||
//Check for double click
|
||||
if(clicked) {
|
||||
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
if (binding.liker.isChecked) {
|
||||
// Button is active, unlike
|
||||
binding.liker.isChecked = false
|
||||
unLikePostCall(api, credential)
|
||||
unLikePostCall(api)
|
||||
} else {
|
||||
// Button is inactive, like
|
||||
binding.liker.playAnimation()
|
||||
binding.liker.isChecked = true
|
||||
likePostCall(api, credential)
|
||||
likePostCall(api)
|
||||
}
|
||||
} else {
|
||||
clicked = true
|
||||
@ -495,15 +489,12 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun likePostCall(
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
) {
|
||||
private suspend fun likePostCall(api: PixelfedAPI) {
|
||||
//Call the api function
|
||||
status?.id?.let {
|
||||
|
||||
try {
|
||||
val resp = api.likePost(credential, it)
|
||||
val resp = api.likePost(it)
|
||||
|
||||
//Update shown like count and internal like toggle
|
||||
binding.nlikes.text = resp.getNLikes(binding.root.context)
|
||||
@ -518,15 +509,12 @@ class StatusViewHolder(val binding: PostFragmentBinding) : RecyclerView.ViewHold
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun unLikePostCall(
|
||||
api: PixelfedAPI,
|
||||
credential: String,
|
||||
) {
|
||||
private suspend fun unLikePostCall(api: PixelfedAPI) {
|
||||
//Call the api function
|
||||
status?.id?.let {
|
||||
|
||||
try {
|
||||
val resp = api.unlikePost(credential, it)
|
||||
val resp = api.unlikePost(it)
|
||||
|
||||
//Update shown like count and internal like toggle
|
||||
binding.nlikes.text = resp.getNLikes(binding.root.context)
|
||||
|
@ -27,7 +27,6 @@ import com.h.pixeldroid.posts.feeds.cachedFeeds.ViewModelFactory
|
||||
import com.h.pixeldroid.posts.parseHTMLText
|
||||
import com.h.pixeldroid.posts.setTextViewFromISO8601
|
||||
import com.h.pixeldroid.profile.ProfileActivity
|
||||
import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||
import com.h.pixeldroid.utils.api.objects.Account
|
||||
import com.h.pixeldroid.utils.api.objects.Notification
|
||||
import com.h.pixeldroid.utils.api.objects.Status
|
||||
@ -165,9 +164,9 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
|
||||
|
||||
fun bind(
|
||||
notification: Notification?,
|
||||
api: PixelfedAPI,
|
||||
accessToken: String,
|
||||
lifecycleScope: LifecycleCoroutineScope
|
||||
api: PixelfedAPIHolder,
|
||||
lifecycleScope: LifecycleCoroutineScope,
|
||||
db: AppDatabase
|
||||
) {
|
||||
|
||||
this.notification = notification
|
||||
@ -208,8 +207,8 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
|
||||
notification?.status?.mentions,
|
||||
api,
|
||||
itemView.context,
|
||||
"Bearer $accessToken",
|
||||
lifecycleScope
|
||||
lifecycleScope,
|
||||
db
|
||||
)
|
||||
}
|
||||
|
||||
@ -257,9 +256,9 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
|
||||
uiModel.let {
|
||||
(holder as NotificationViewHolder).bind(
|
||||
it,
|
||||
apiHolder.setDomainToCurrentUser(db),
|
||||
db.userDao().getActiveUser()!!.accessToken,
|
||||
lifecycleScope
|
||||
apiHolder,
|
||||
lifecycleScope,
|
||||
db
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -59,12 +59,11 @@ class NotificationsRemoteMediator @Inject constructor(
|
||||
val user = db.userDao().getActiveUser()
|
||||
?: return MediatorResult.Error(NullPointerException("No active user exists"))
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
val accessToken = user.accessToken
|
||||
|
||||
val apiResponse = api.notifications("Bearer $accessToken",
|
||||
max_id = max_id,
|
||||
min_id = min_id,
|
||||
limit = state.config.pageSize.toString(),
|
||||
val apiResponse = api.notifications(
|
||||
max_id = max_id,
|
||||
min_id = min_id,
|
||||
limit = state.config.pageSize.toString(),
|
||||
)
|
||||
|
||||
apiResponse.forEach{it.user_id = user.user_id; it.instance_uri = user.instance_uri}
|
||||
|
@ -44,11 +44,11 @@ class HomeFeedRemoteMediator @Inject constructor(
|
||||
val user = db.userDao().getActiveUser()
|
||||
?: return MediatorResult.Error(NullPointerException("No active user exists"))
|
||||
val api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
val accessToken = user.accessToken
|
||||
|
||||
val apiResponse = api.timelineHome( "Bearer $accessToken",
|
||||
max_id= max_id, min_id = min_id,
|
||||
limit = state.config.pageSize.toString())
|
||||
val apiResponse = api.timelineHome(
|
||||
max_id= max_id,
|
||||
min_id = min_id, limit = state.config.pageSize.toString()
|
||||
)
|
||||
|
||||
val dbObjects = apiResponse.map{
|
||||
HomeStatusDatabaseEntity(user.user_id, user.instance_uri, it)
|
||||
|
@ -90,7 +90,7 @@ class PostFeedFragment<T: FeedContentDatabase>: CachedFeedFragment<T>() {
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val uiModel = getItem(position) as Status
|
||||
uiModel.let {
|
||||
(holder as StatusViewHolder).bind(it, apiHolder.setDomainToCurrentUser(db), db, lifecycleScope, displayDimensionsInPx)
|
||||
(holder as StatusViewHolder).bind(it, apiHolder, db, lifecycleScope, displayDimensionsInPx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ class AccountListFragment : UncachedFeedFragment<Account>() {
|
||||
viewModel = ViewModelProvider(this, ViewModelFactory(
|
||||
FollowersContentRepository(
|
||||
apiHolder.setDomainToCurrentUser(db),
|
||||
db.userDao().getActiveUser()!!.accessToken,
|
||||
id,
|
||||
following
|
||||
)
|
||||
|
@ -14,7 +14,6 @@ import javax.inject.Inject
|
||||
class FollowersContentRepository @ExperimentalPagingApi
|
||||
@Inject constructor(
|
||||
private val api: PixelfedAPI,
|
||||
private val accessToken: String,
|
||||
private val accountId: String,
|
||||
private val following: Boolean,
|
||||
): UncachedContentRepository<Account> {
|
||||
@ -25,7 +24,7 @@ class FollowersContentRepository @ExperimentalPagingApi
|
||||
pageSize = NETWORK_PAGE_SIZE,
|
||||
enablePlaceholders = false),
|
||||
pagingSourceFactory = {
|
||||
FollowersPagingSource(api, accessToken, accountId, following)
|
||||
FollowersPagingSource(api, accountId, following)
|
||||
}
|
||||
).flow
|
||||
}
|
||||
|
@ -6,11 +6,9 @@ import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||
import com.h.pixeldroid.utils.api.objects.Account
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
import java.math.BigInteger
|
||||
|
||||
class FollowersPagingSource(
|
||||
private val api: PixelfedAPI,
|
||||
private val accessToken: String,
|
||||
private val accountId: String,
|
||||
private val following: Boolean
|
||||
) : PagingSource<String, Account>() {
|
||||
@ -22,17 +20,19 @@ class FollowersPagingSource(
|
||||
// Laravel's paging mechanism, while Mastodon uses the Link header for pagination.
|
||||
// No need to know which is which, they should ignore the non-relevant argument
|
||||
if(following) {
|
||||
api.followers(account_id = accountId,
|
||||
authorization = "Bearer $accessToken",
|
||||
api.followers(
|
||||
account_id = accountId,
|
||||
max_id = position,
|
||||
limit = params.loadSize,
|
||||
page = position,
|
||||
max_id = position)
|
||||
page = position
|
||||
)
|
||||
} else {
|
||||
api.following(account_id = accountId,
|
||||
authorization = "Bearer $accessToken",
|
||||
api.following(
|
||||
account_id = accountId,
|
||||
max_id = position,
|
||||
limit = params.loadSize,
|
||||
page = position,
|
||||
max_id = position)
|
||||
page = position
|
||||
)
|
||||
}
|
||||
|
||||
val accounts = if(response.isSuccessful){
|
||||
|
@ -13,7 +13,6 @@ import javax.inject.Inject
|
||||
class ProfileContentRepository @ExperimentalPagingApi
|
||||
@Inject constructor(
|
||||
private val api: PixelfedAPI,
|
||||
private val accessToken: String,
|
||||
private val accountId: String
|
||||
) : UncachedContentRepository<Status> {
|
||||
override fun getStream(): Flow<PagingData<Status>> {
|
||||
@ -23,7 +22,7 @@ class ProfileContentRepository @ExperimentalPagingApi
|
||||
pageSize = NETWORK_PAGE_SIZE,
|
||||
enablePlaceholders = false),
|
||||
pagingSourceFactory = {
|
||||
ProfilePagingSource(api, accessToken, accountId)
|
||||
ProfilePagingSource(api, accountId)
|
||||
}
|
||||
).flow
|
||||
}
|
||||
|
@ -9,16 +9,15 @@ import java.io.IOException
|
||||
|
||||
class ProfilePagingSource(
|
||||
private val api: PixelfedAPI,
|
||||
private val accessToken: String,
|
||||
private val accountId: String
|
||||
) : PagingSource<String, Status>() {
|
||||
override suspend fun load(params: LoadParams<String>): LoadResult<String, Status> {
|
||||
val position = params.key
|
||||
return try {
|
||||
val posts = api.accountPosts("Bearer $accessToken",
|
||||
account_id = accountId,
|
||||
max_id = position,
|
||||
limit = params.loadSize
|
||||
val posts = api.accountPosts(
|
||||
account_id = accountId,
|
||||
max_id = position,
|
||||
limit = params.loadSize
|
||||
)
|
||||
|
||||
LoadResult.Page(
|
||||
|
@ -41,7 +41,6 @@ class SearchAccountFragment : UncachedFeedFragment<Account>() {
|
||||
SearchContentRepository<Account>(
|
||||
apiHolder.setDomainToCurrentUser(db),
|
||||
Results.SearchType.accounts,
|
||||
db.userDao().getActiveUser()!!.accessToken,
|
||||
query
|
||||
)
|
||||
)
|
||||
|
@ -22,7 +22,6 @@ class SearchContentRepository<T: FeedContent> @ExperimentalPagingApi
|
||||
@Inject constructor(
|
||||
private val api: PixelfedAPI,
|
||||
private val type: Results.SearchType,
|
||||
private val accessToken: String,
|
||||
private val query: String,
|
||||
): UncachedContentRepository<T> {
|
||||
override fun getStream(): Flow<PagingData<T>> {
|
||||
@ -32,7 +31,7 @@ class SearchContentRepository<T: FeedContent> @ExperimentalPagingApi
|
||||
pageSize = NETWORK_PAGE_SIZE,
|
||||
enablePlaceholders = false),
|
||||
pagingSourceFactory = {
|
||||
SearchPagingSource<T>(api, query, type, accessToken)
|
||||
SearchPagingSource<T>(api, query, type)
|
||||
}
|
||||
).flow
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ class SearchHashtagFragment : UncachedFeedFragment<Tag>() {
|
||||
SearchContentRepository<Tag>(
|
||||
apiHolder.setDomainToCurrentUser(db),
|
||||
Results.SearchType.hashtags,
|
||||
db.userDao().getActiveUser()!!.accessToken,
|
||||
query
|
||||
)
|
||||
)
|
||||
|
@ -15,16 +15,16 @@ class SearchPagingSource<T: FeedContent>(
|
||||
private val api: PixelfedAPI,
|
||||
private val query: String,
|
||||
private val type: Results.SearchType,
|
||||
private val accessToken: String,
|
||||
) : PagingSource<Int, T>() {
|
||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, T> {
|
||||
val position = params.key
|
||||
return try {
|
||||
val response = api.search(authorization = "Bearer $accessToken",
|
||||
offset = position?.toString(),
|
||||
q = query,
|
||||
val response = api.search(
|
||||
type = type,
|
||||
limit = params.loadSize.toString())
|
||||
q = query,
|
||||
limit = params.loadSize.toString(),
|
||||
offset = position?.toString()
|
||||
)
|
||||
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -45,7 +45,6 @@ class SearchPostsFragment : UncachedFeedFragment<Status>() {
|
||||
SearchContentRepository<Status>(
|
||||
apiHolder.setDomainToCurrentUser(db),
|
||||
Results.SearchType.statuses,
|
||||
db.userDao().getActiveUser()!!.accessToken,
|
||||
query
|
||||
)
|
||||
)
|
||||
@ -80,7 +79,7 @@ class SearchPostsFragment : UncachedFeedFragment<Status>() {
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
val uiModel = getItem(position) as Status
|
||||
uiModel.let {
|
||||
(holder as StatusViewHolder).bind(it, apiHolder.setDomainToCurrentUser(db), db, lifecycleScope, displayDimensionsInPx)
|
||||
(holder as StatusViewHolder).bind(it, apiHolder, db, lifecycleScope, displayDimensionsInPx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +44,6 @@ import java.io.IOException
|
||||
|
||||
class ProfileActivity : BaseActivity() {
|
||||
|
||||
private lateinit var pixelfedAPI : PixelfedAPI
|
||||
private lateinit var accessToken : String
|
||||
private lateinit var domain : String
|
||||
private lateinit var accountId : String
|
||||
private lateinit var binding: ActivityProfileBinding
|
||||
@ -66,8 +64,6 @@ class ProfileActivity : BaseActivity() {
|
||||
user = db.userDao().getActiveUser()
|
||||
|
||||
domain = user?.instance_uri.orEmpty()
|
||||
pixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
accessToken = user?.accessToken.orEmpty()
|
||||
|
||||
// Set profile according to given account
|
||||
val account = intent.getSerializableExtra(Account.ACCOUNT_TAG) as Account?
|
||||
@ -77,9 +73,8 @@ class ProfileActivity : BaseActivity() {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
viewModel = ViewModelProvider(this, ProfileViewModelFactory(
|
||||
ProfileContentRepository(
|
||||
apiHolder.setDomainToCurrentUser(db),
|
||||
db.userDao().getActiveUser()!!.accessToken,
|
||||
accountId
|
||||
apiHolder.setDomainToCurrentUser(db),
|
||||
accountId
|
||||
)
|
||||
)
|
||||
).get(FeedViewModel::class.java) as FeedViewModel<Status>
|
||||
@ -124,8 +119,9 @@ class ProfileActivity : BaseActivity() {
|
||||
setViews(account)
|
||||
} else {
|
||||
lifecycleScope.launchWhenResumed {
|
||||
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
val myAccount: Account = try {
|
||||
pixelfedAPI.verifyCredentials("Bearer $accessToken")
|
||||
api.verifyCredentials()
|
||||
} catch (exception: IOException) {
|
||||
Log.e("ProfileActivity:", exception.toString())
|
||||
return@launchWhenResumed showError()
|
||||
@ -162,9 +158,10 @@ class ProfileActivity : BaseActivity() {
|
||||
)
|
||||
|
||||
binding.descriptionTextView.text = parseHTMLText(
|
||||
account.note ?: "", emptyList(), pixelfedAPI,
|
||||
applicationContext, "Bearer $accessToken",
|
||||
lifecycleScope
|
||||
account.note ?: "", emptyList(), apiHolder,
|
||||
applicationContext,
|
||||
lifecycleScope,
|
||||
db
|
||||
)
|
||||
|
||||
val displayName = account.getDisplayName()
|
||||
@ -235,8 +232,9 @@ class ProfileActivity : BaseActivity() {
|
||||
// Get relationship between the two users (credential and this) and set followButton accordingly
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
val relationship = pixelfedAPI.checkRelationships(
|
||||
"Bearer $accessToken", listOf(account.id.orEmpty())
|
||||
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
val relationship = api.checkRelationships(
|
||||
listOf(account.id.orEmpty())
|
||||
).firstOrNull()
|
||||
|
||||
if(relationship != null){
|
||||
@ -268,7 +266,8 @@ class ProfileActivity : BaseActivity() {
|
||||
setOnClickListener {
|
||||
lifecycleScope.launchWhenResumed {
|
||||
try {
|
||||
val rel = pixelfedAPI.follow(account.id.orEmpty(), "Bearer $accessToken")
|
||||
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
val rel = api.follow(account.id.orEmpty())
|
||||
if(rel.following == true) setOnClickUnfollow(account, rel.requested == true)
|
||||
else setOnClickFollow(account)
|
||||
} catch (exception: IOException) {
|
||||
@ -298,7 +297,8 @@ class ProfileActivity : BaseActivity() {
|
||||
fun unfollow() {
|
||||
lifecycleScope.launchWhenResumed {
|
||||
try {
|
||||
val rel = pixelfedAPI.unfollow(account.id.orEmpty(), "Bearer $accessToken")
|
||||
val api: PixelfedAPI = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
val rel = api.unfollow(account.id.orEmpty())
|
||||
if(rel.following == false && rel.requested == false) setOnClickFollow(account)
|
||||
else setOnClickUnfollow(account, rel.requested == true)
|
||||
} catch (exception: IOException) {
|
||||
|
@ -20,12 +20,6 @@ import com.h.pixeldroid.posts.PostActivity
|
||||
import com.h.pixeldroid.utils.BaseFragment
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import com.h.pixeldroid.utils.bindingLifecycleAware
|
||||
import com.mikepenz.iconics.IconicsColor
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||
import com.mikepenz.iconics.utils.color
|
||||
import com.mikepenz.iconics.utils.paddingDp
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
@ -37,7 +31,6 @@ class SearchDiscoverFragment : BaseFragment() {
|
||||
private lateinit var api: PixelfedAPI
|
||||
private lateinit var recycler : RecyclerView
|
||||
private lateinit var adapter : DiscoverRecyclerViewAdapter
|
||||
private lateinit var accessToken: String
|
||||
|
||||
var binding: FragmentSearchBinding by bindingLifecycleAware()
|
||||
|
||||
@ -68,8 +61,6 @@ class SearchDiscoverFragment : BaseFragment() {
|
||||
|
||||
api = apiHolder.api ?: apiHolder.setDomainToCurrentUser(db)
|
||||
|
||||
accessToken = db.userDao().getActiveUser()?.accessToken.orEmpty()
|
||||
|
||||
getDiscover()
|
||||
|
||||
binding.discoverRefreshLayout.setOnRefreshListener {
|
||||
@ -93,7 +84,7 @@ class SearchDiscoverFragment : BaseFragment() {
|
||||
private fun getDiscover() {
|
||||
lifecycleScope.launchWhenCreated {
|
||||
try {
|
||||
val discoverPosts = api.discover("Bearer $accessToken")
|
||||
val discoverPosts = api.discover()
|
||||
adapter.addPosts(discoverPosts.posts)
|
||||
showError(show = false)
|
||||
} catch (exception: IOException) {
|
||||
|
@ -74,31 +74,23 @@ interface PixelfedAPI {
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/accounts/{id}/follow")
|
||||
suspend fun follow(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Path("id") statusId: String,
|
||||
@Header("Authorization") authorization: String,
|
||||
@Field("reblogs") reblogs : Boolean = true
|
||||
) : Relationship
|
||||
|
||||
@POST("/api/v1/accounts/{id}/unfollow")
|
||||
suspend fun unfollow(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Path("id") statusId: String,
|
||||
@Header("Authorization") authorization: String
|
||||
) : Relationship
|
||||
|
||||
@POST("api/v1/statuses/{id}/favourite")
|
||||
suspend fun likePost(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String,
|
||||
@Path("id") statusId: String
|
||||
|
||||
) : Status
|
||||
|
||||
@POST("/api/v1/statuses/{id}/unfavourite")
|
||||
suspend fun unlikePost(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String,
|
||||
@Path("id") statusId: String
|
||||
) : Status
|
||||
|
||||
@ -106,8 +98,6 @@ interface PixelfedAPI {
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/statuses")
|
||||
suspend fun postStatus(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String,
|
||||
@Field("status") statusText : String,
|
||||
@Field("in_reply_to_id") in_reply_to_id : String? = null,
|
||||
@Field("media_ids[]") media_ids : List<String> = emptyList(),
|
||||
@ -124,14 +114,12 @@ interface PixelfedAPI {
|
||||
|
||||
@DELETE("/api/v1/statuses/{id}")
|
||||
suspend fun deleteStatus(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Path("id") statusId: String
|
||||
)
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/statuses/{id}/reblog")
|
||||
suspend fun reblogStatus(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Path("id") statusId: String,
|
||||
@Field("visibility") visibility: String? = null
|
||||
) : Status
|
||||
@ -139,14 +127,12 @@ interface PixelfedAPI {
|
||||
@POST("/api/v1/statuses/{id}/unreblog")
|
||||
suspend fun undoReblogStatus(
|
||||
@Path("id") statusId: String,
|
||||
@Header("Authorization") authorization: String
|
||||
) : Status
|
||||
|
||||
//Used in our case to retrieve comments for a given status
|
||||
@GET("/api/v1/statuses/{id}/context")
|
||||
suspend fun statusComments(
|
||||
@Path("id") statusId: String,
|
||||
@Header("Authorization") authorization: String? = null
|
||||
) : Context
|
||||
|
||||
@GET("/api/v1/timelines/public")
|
||||
@ -160,8 +146,6 @@ interface PixelfedAPI {
|
||||
|
||||
@GET("/api/v1/timelines/home")
|
||||
suspend fun timelineHome(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String,
|
||||
@Query("max_id") max_id: String? = null,
|
||||
@Query("since_id") since_id: String? = null,
|
||||
@Query("min_id") min_id: String? = null,
|
||||
@ -171,8 +155,6 @@ interface PixelfedAPI {
|
||||
|
||||
@GET("/api/v2/search")
|
||||
suspend fun search(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String,
|
||||
@Query("account_id") account_id: String? = null,
|
||||
@Query("max_id") max_id: String? = null,
|
||||
@Query("min_id") min_id: String? = null,
|
||||
@ -187,8 +169,6 @@ interface PixelfedAPI {
|
||||
|
||||
@GET("/api/v1/notifications")
|
||||
suspend fun notifications(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String,
|
||||
@Query("max_id") max_id: String? = null,
|
||||
@Query("since_id") since_id: String? = null,
|
||||
@Query("min_id") min_id: String? = null,
|
||||
@ -200,13 +180,12 @@ interface PixelfedAPI {
|
||||
@GET("/api/v1/accounts/verify_credentials")
|
||||
suspend fun verifyCredentials(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String
|
||||
@Header("Authorization") authorization: String? = null
|
||||
): Account
|
||||
|
||||
|
||||
@GET("/api/v1/accounts/{id}/statuses")
|
||||
suspend fun accountPosts(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Path("id") account_id: String,
|
||||
@Query("min_id") min_id: String? = null,
|
||||
@Query("max_id") max_id: String?,
|
||||
@ -215,14 +194,12 @@ interface PixelfedAPI {
|
||||
|
||||
@GET("/api/v1/accounts/relationships")
|
||||
suspend fun checkRelationships(
|
||||
@Header("Authorization") authorization : String,
|
||||
@Query("id[]") account_ids : List<String>
|
||||
) : List<Relationship>
|
||||
|
||||
@GET("/api/v1/accounts/{id}/followers")
|
||||
suspend fun followers(
|
||||
@Path("id") account_id: String,
|
||||
@Header("Authorization") authorization: String,
|
||||
@Query("max_id") max_id: String? = null,
|
||||
@Query("since_id") since_id: String? = null,
|
||||
@Query("limit") limit: Number? = null,
|
||||
@ -232,7 +209,6 @@ interface PixelfedAPI {
|
||||
@GET("/api/v1/accounts/{id}/following")
|
||||
suspend fun following(
|
||||
@Path("id") account_id: String,
|
||||
@Header("Authorization") authorization: String,
|
||||
@Query("max_id") max_id: String? = null,
|
||||
@Query("since_id") since_id: String? = null,
|
||||
@Query("limit") limit: Number? = 40,
|
||||
@ -241,36 +217,29 @@ interface PixelfedAPI {
|
||||
|
||||
@GET("/api/v1/accounts/{id}")
|
||||
suspend fun getAccount(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Path("id") accountId : String
|
||||
): Account
|
||||
|
||||
@GET("/api/v1/statuses/{id}")
|
||||
suspend fun getStatus(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Path("id") accountId : String
|
||||
): Status
|
||||
|
||||
@Multipart
|
||||
@POST("/api/v1/media")
|
||||
fun mediaUpload(
|
||||
//The authorization header needs to be of the form "Bearer <token>"
|
||||
@Header("Authorization") authorization: String,
|
||||
@Part description: MultipartBody.Part? = null,
|
||||
@Part file: MultipartBody.Part
|
||||
): Observable<Attachment>
|
||||
|
||||
// get discover
|
||||
@GET("/api/v2/discover/posts")
|
||||
suspend fun discover(
|
||||
@Header("Authorization") authorization: String
|
||||
) : DiscoverPosts
|
||||
suspend fun discover() : DiscoverPosts
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST("/api/v1/reports")
|
||||
@JvmSuppressWildcards
|
||||
suspend fun report(
|
||||
@Header("Authorization") authorization: String,
|
||||
@Field("account_id") account_id: String,
|
||||
@Field("status_ids") status_ids: List<Status>,
|
||||
@Field("comment") comment: String,
|
||||
|
@ -6,13 +6,7 @@ import android.util.Log
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import com.h.pixeldroid.profile.ProfileActivity
|
||||
import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.HttpException
|
||||
import retrofit2.Response
|
||||
import java.io.IOException
|
||||
import java.io.Serializable
|
||||
|
||||
@ -57,9 +51,9 @@ data class Account(
|
||||
/**
|
||||
* @brief Opens an activity of the profile with the given id
|
||||
*/
|
||||
suspend fun openAccountFromId(id: String, api : PixelfedAPI, context: Context, credential: String) {
|
||||
suspend fun openAccountFromId(id: String, api : PixelfedAPI, context: Context) {
|
||||
val account = try {
|
||||
api.getAccount(credential, id)
|
||||
api.getAccount(id)
|
||||
} catch (exception: IOException) {
|
||||
Log.e("GET ACCOUNT ERROR", exception.toString())
|
||||
return
|
||||
|
@ -8,8 +8,8 @@ interface UserDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
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("UPDATE users SET accessToken = :accessToken, refreshToken = :refreshToken WHERE user_id = :id and instance_uri = :instance_uri")
|
||||
fun updateAccessToken(accessToken: String, refreshToken: String, id: String, instance_uri: String)
|
||||
|
||||
@Query("SELECT * FROM users")
|
||||
fun getAll(): List<UserDatabaseEntity>
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.h.pixeldroid.utils.di
|
||||
|
||||
import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||
import com.h.pixeldroid.utils.api.objects.Token
|
||||
import com.h.pixeldroid.utils.db.AppDatabase
|
||||
import com.h.pixeldroid.utils.db.entities.UserDatabaseEntity
|
||||
import dagger.Module
|
||||
@ -22,17 +23,30 @@ class APIModule{
|
||||
}
|
||||
}
|
||||
|
||||
class TokenAuthenticator(val user: UserDatabaseEntity, val db: AppDatabase) : Authenticator {
|
||||
class TokenAuthenticator(val user: UserDatabaseEntity, val db: AppDatabase, val apiHolder: PixelfedAPIHolder) : Authenticator {
|
||||
|
||||
private val pixelfedAPI = PixelfedAPI.createFromUrl(user.instance_uri)
|
||||
|
||||
// Returns the number of tries for this response by walking through the priorResponses
|
||||
private fun Response.responseCount(): Int {
|
||||
var result = 1
|
||||
var response: Response? = priorResponse
|
||||
|
||||
while (response != null) {
|
||||
result++
|
||||
response = response.priorResponse
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
override fun authenticate(route: Route?, response: Response): Request? {
|
||||
|
||||
if (response.request.header("Authorization") != null) {
|
||||
return null // Give up, we've already failed to authenticate.
|
||||
if (response.responseCount() > 3) {
|
||||
return null // Give up, we've already failed to authenticate a couple times
|
||||
}
|
||||
// Refresh the access_token using a synchronous api request
|
||||
val newAccessToken: String? = try {
|
||||
val newAccessToken: Token = try {
|
||||
runBlocking {
|
||||
pixelfedAPI.obtainToken(
|
||||
scope = "",
|
||||
@ -40,19 +54,25 @@ class TokenAuthenticator(val user: UserDatabaseEntity, val db: AppDatabase) : Au
|
||||
refresh_token = user.refreshToken,
|
||||
client_id = user.clientId,
|
||||
client_secret = user.clientSecret
|
||||
).access_token
|
||||
)
|
||||
}
|
||||
}catch (e: Exception){
|
||||
null
|
||||
return null
|
||||
}
|
||||
|
||||
if (newAccessToken != null) {
|
||||
db.userDao().updateAccessToken(newAccessToken, user.user_id, user.instance_uri)
|
||||
// Save the new access token and refresh token
|
||||
if (newAccessToken.access_token != null && newAccessToken.refresh_token != null) {
|
||||
db.userDao().updateAccessToken(
|
||||
newAccessToken.access_token,
|
||||
newAccessToken.refresh_token,
|
||||
user.user_id, user.instance_uri
|
||||
)
|
||||
apiHolder.setDomainToCurrentUser(db)
|
||||
}
|
||||
|
||||
// Add new header to rejected request and retry it
|
||||
return response.request.newBuilder()
|
||||
.header("Authorization", "Bearer ${newAccessToken.orEmpty()}")
|
||||
.header("Authorization", "Bearer ${newAccessToken.access_token.orEmpty()}")
|
||||
.build()
|
||||
}
|
||||
}
|
||||
@ -61,6 +81,7 @@ class PixelfedAPIHolder(db: AppDatabase?){
|
||||
private val intermediate: Retrofit.Builder = Retrofit.Builder()
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
|
||||
var api: PixelfedAPI? =
|
||||
db?.userDao()?.getActiveUser()?.let {
|
||||
setDomainToCurrentUser(db, it)
|
||||
@ -73,10 +94,11 @@ class PixelfedAPIHolder(db: AppDatabase?){
|
||||
val newAPI = intermediate
|
||||
.baseUrl(user.instance_uri)
|
||||
.client(
|
||||
OkHttpClient().newBuilder().authenticator(TokenAuthenticator(user, db))
|
||||
OkHttpClient().newBuilder().authenticator(TokenAuthenticator(user, db, this))
|
||||
.addInterceptor {
|
||||
it.request().newBuilder().run {
|
||||
header("Accept", "application/json")
|
||||
header("Authorization", "Bearer ${user.accessToken}")
|
||||
it.proceed(build())
|
||||
}
|
||||
}.build()
|
||||
|
@ -4,7 +4,6 @@ import com.github.tomakehurst.wiremock.client.WireMock.*
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockRule
|
||||
import com.h.pixeldroid.utils.api.PixelfedAPI
|
||||
import com.h.pixeldroid.utils.api.objects.*
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Rule
|
||||
@ -91,7 +90,7 @@ class APIUnitTest {
|
||||
statuses = PixelfedAPI.createFromUrl("http://localhost:8089")
|
||||
.timelinePublic(null, null, null, null, null)
|
||||
statusesHome = PixelfedAPI.createFromUrl("http://localhost:8089")
|
||||
.timelineHome("abc", null, null, null,null, null)
|
||||
.timelineHome(null, null, null, null, null)
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user