PixelDroid-App-Android/app/src/main/java/org/pixeldroid/app/posts/PostActivity.kt

234 lines
8.6 KiB
Kotlin

package org.pixeldroid.app.posts
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
import android.widget.Toast
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.paging.ExperimentalPagingApi
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.Job
import org.pixeldroid.app.R
import org.pixeldroid.app.databinding.ActivityPostBinding
import org.pixeldroid.app.databinding.CommentBinding
import org.pixeldroid.app.posts.feeds.initAdapter
import org.pixeldroid.app.posts.feeds.launch
import org.pixeldroid.app.posts.feeds.uncachedFeeds.FeedViewModel
import org.pixeldroid.app.posts.feeds.uncachedFeeds.comments.CommentContentRepository
import org.pixeldroid.app.profile.ProfileViewModelFactory
import org.pixeldroid.app.utils.BaseThemedWithBarActivity
import org.pixeldroid.app.utils.api.PixelfedAPI
import org.pixeldroid.app.utils.api.objects.Status
import org.pixeldroid.app.utils.api.objects.Status.Companion.POST_COMMENT_TAG
import org.pixeldroid.app.utils.api.objects.Status.Companion.POST_TAG
import org.pixeldroid.app.utils.api.objects.Status.Companion.VIEW_COMMENTS_TAG
import org.pixeldroid.app.utils.displayDimensionsInPx
import org.pixeldroid.app.utils.setProfileImageFromURL
import retrofit2.HttpException
import java.io.IOException
class PostActivity : BaseThemedWithBarActivity() {
lateinit var domain : String
private lateinit var binding: ActivityPostBinding
private lateinit var profileAdapter: PagingDataAdapter<Status, RecyclerView.ViewHolder>
private lateinit var viewModel: FeedViewModel<Status>
private var job: Job? = null
private lateinit var status: Status
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityPostBinding.inflate(layoutInflater)
setContentView(binding.root)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
status = intent.getSerializableExtra(POST_TAG) as Status
val viewComments: Boolean = intent.getBooleanExtra(VIEW_COMMENTS_TAG, false)
val postComment: Boolean = intent.getBooleanExtra(POST_COMMENT_TAG, false)
val user = db.userDao().getActiveUser()
domain = user?.instance_uri.orEmpty()
supportActionBar?.title = getString(R.string.post_title).format(status.account?.getDisplayName())
val holder = StatusViewHolder(binding.postFragmentSingle)
holder.bind(status, apiHolder, db, lifecycleScope, displayDimensionsInPx(), isActivity = true)
activateCommenter()
retrieveComments()
if(viewComments || postComment){
//Scroll already down as much as possible (since comments are not loaded yet)
binding.scrollview.requestChildFocus(binding.editComment, binding.editComment)
//Open keyboard if we want to post a comment
if(postComment && binding.editComment.requestFocus()) {
window.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE)
binding.editComment.requestFocus()
}
}
}
private fun activateCommenter() {
//Activate commenter
binding.submitComment.setOnClickListener {
val textIn = binding.editComment.text
//Open text input
if(textIn.isNullOrEmpty()) {
Toast.makeText(
binding.root.context,
binding.root.context.getString(R.string.empty_comment),
Toast.LENGTH_SHORT
).show()
} else {
//Post the comment
lifecycleScope.launchWhenCreated {
apiHolder.api?.let { it1 -> postComment(it1) }
}
}
}
}
@OptIn(ExperimentalPagingApi::class)
private fun retrieveComments() {
// get the view model
@Suppress("UNCHECKED_CAST")
viewModel = ViewModelProvider(this@PostActivity, ProfileViewModelFactory(
CommentContentRepository(
apiHolder.setToCurrentUser(),
status.id
)
)
)[FeedViewModel::class.java] as FeedViewModel<Status>
profileAdapter = CommentAdapter()
initAdapter(binding.postCommentsProgressBar, binding.postRefreshLayout,
binding.commentRecyclerView, binding.motionLayout, binding.errorLayout,
profileAdapter)
job = launch(job, lifecycleScope, viewModel, profileAdapter)
}
private suspend fun postComment(
api: PixelfedAPI,
) {
val textIn = binding.editComment.text
val nonNullText = textIn.toString()
status.id.let {
try {
val response = api.postStatus(nonNullText, it)
binding.commentIn.visibility = View.GONE
//Add the comment to the comment section
profileAdapter.refresh()
Toast.makeText(
binding.root.context,
binding.root.context.getString(R.string.comment_posted).format(textIn),
Toast.LENGTH_SHORT
).show()
} catch (exception: IOException) {
Log.e("COMMENT ERROR", exception.toString())
Toast.makeText(
binding.root.context, binding.root.context.getString(R.string.comment_error),
Toast.LENGTH_SHORT
).show()
} catch (exception: HttpException) {
Toast.makeText(
binding.root.context, binding.root.context.getString(R.string.comment_error),
Toast.LENGTH_SHORT
).show()
Log.e("ERROR_CODE", exception.code().toString())
}
}
}
inner class CommentViewHolder(val binding: CommentBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(comment: Status) {
setProfileImageFromURL(binding.profilePic,
comment.account!!.anyAvatar(),
binding.profilePic
)
binding.user.text = comment.account.username
binding.commentText.text = parseHTMLText(
comment.content!!,
comment.mentions.orEmpty(),
apiHolder,
this@PostActivity,
lifecycleScope
)
if(comment.replies_count == 0 || comment.replies_count == null){
binding.replies.visibility = View.GONE
} else {
binding.replies.visibility = View.VISIBLE
binding.replies.text = resources.getQuantityString(
R.plurals.replies_count,
comment.replies_count,
comment.replies_count
)
}
binding.comment.setOnClickListener{ openComment(comment) }
binding.profilePic.setOnClickListener{ comment.account.openProfile(itemView.context) }
binding.user.setOnClickListener { comment.account.openProfile(itemView.context) }
}
private fun openComment(comment: Status) {
val intent = Intent(itemView.context, PostActivity::class.java).apply {
putExtra(POST_TAG, comment)
}
itemView.context.startActivity(intent)
}
}
inner class CommentAdapter : PagingDataAdapter<Status, RecyclerView.ViewHolder>(
UIMODEL_COMPARATOR
) {
fun create(parent: ViewGroup): CommentViewHolder {
val itemBinding = CommentBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
return CommentViewHolder(itemBinding)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return create(parent)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val post = getItem(position)
post?.let {
(holder as CommentViewHolder).bind(it)
}
}
}
private val UIMODEL_COMPARATOR = object : DiffUtil.ItemCallback<Status>() {
override fun areItemsTheSame(oldItem: Status, newItem: Status): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Status, newItem: Status): Boolean =
oldItem.content == newItem.content
}
}