Dantotsu/app/src/main/java/ani/dantotsu/media/comments/CommentItem.kt
2024-02-17 12:25:18 +05:30

184 lines
No EOL
7.4 KiB
Kotlin

package ani.dantotsu.media.comments
import android.annotation.SuppressLint
import android.view.View
import ani.dantotsu.R
import ani.dantotsu.connections.comments.Comment
import ani.dantotsu.connections.comments.CommentsAPI
import ani.dantotsu.currActivity
import ani.dantotsu.databinding.ItemCommentsBinding
import ani.dantotsu.loadImage
import ani.dantotsu.snackString
import com.xwray.groupie.GroupieAdapter
import com.xwray.groupie.Section
import com.xwray.groupie.viewbinding.BindableItem
import io.noties.markwon.Markwon
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.TimeZone
class CommentItem(val comment: Comment,
private val markwon: Markwon,
private val section: Section,
private val editCallback: (CommentItem) -> Unit
) : BindableItem<ItemCommentsBinding>() {
@SuppressLint("SetTextI18n")
override fun bind(viewBinding: ItemCommentsBinding, position: Int) {
val isUserComment = CommentsAPI.userId == comment.userId
val node = markwon.parse(comment.content)
val spanned = markwon.render(node)
markwon.setParsedMarkdown(viewBinding.commentText, viewBinding.commentText.setSpoilerText(spanned, markwon))
viewBinding.commentDelete.visibility = if (isUserComment || CommentsAPI.isAdmin || CommentsAPI.isMod) View.VISIBLE else View.GONE
viewBinding.commentBanUser.visibility = if ((CommentsAPI.isAdmin || CommentsAPI.isMod) && !isUserComment) View.VISIBLE else View.GONE
viewBinding.commentEdit.visibility = if (isUserComment) View.VISIBLE else View.GONE
viewBinding.commentReply.visibility = View.GONE //TODO: implement reply
viewBinding.commentTotalReplies.visibility = View.GONE //TODO: implement reply
viewBinding.commentReply.setOnClickListener {
}
var isEditing = false
viewBinding.commentEdit.setOnClickListener {
if (!isEditing) {
viewBinding.commentEdit.text = currActivity()!!.getString(R.string.cancel)
isEditing = true
editCallback(this)
} else {
viewBinding.commentEdit.text = currActivity()!!.getString(R.string.edit)
isEditing = false
editCallback(this)
}
}
viewBinding.modBadge.visibility = if (comment.isMod == true) View.VISIBLE else View.GONE
viewBinding.adminBadge.visibility = if (comment.isAdmin == true) View.VISIBLE else View.GONE
viewBinding.commentDelete.setOnClickListener {
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
scope.launch {
val success = CommentsAPI.deleteComment(comment.commentId)
if (success) {
snackString("Comment Deleted")
section.remove(this@CommentItem)
}
}
}
viewBinding.commentBanUser.setOnClickListener {
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
scope.launch {
val success = CommentsAPI.banUser(comment.userId)
if (success) {
snackString("User Banned")
}
}
}
//fill the icon if the user has liked the comment
setVoteButtons(viewBinding)
viewBinding.commentUpVote.setOnClickListener {
val voteType = if (comment.userVoteType == 1) 0 else 1
val previousVoteType = comment.userVoteType
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
scope.launch {
val success = CommentsAPI.vote(comment.commentId, voteType)
if (success) {
comment.userVoteType = voteType
if (previousVoteType == -1) {
comment.downvotes -= 1
}
comment.upvotes += if (voteType == 1) 1 else -1
notifyChanged()
}
}
}
viewBinding.commentDownVote.setOnClickListener {
val voteType = if (comment.userVoteType == -1) 0 else -1
val previousVoteType = comment.userVoteType
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
scope.launch {
val success = CommentsAPI.vote(comment.commentId, voteType)
if (success) {
comment.userVoteType = voteType
if (previousVoteType == 1) {
comment.upvotes -= 1
}
comment.downvotes += if (voteType == -1) 1 else -1
notifyChanged()
}
}
}
viewBinding.commentTotalVotes.text = (comment.upvotes - comment.downvotes).toString()
viewBinding.commentUserAvatar
comment.profilePictureUrl?.let { viewBinding.commentUserAvatar.loadImage(it) }
viewBinding.commentUserName.text = comment.username
viewBinding.commentUserTime.text = "${formatTimestamp(comment.timestamp)}"
}
override fun getLayout(): Int {
return R.layout.item_comments
}
override fun initializeViewBinding(view: View): ItemCommentsBinding {
return ItemCommentsBinding.bind(view)
}
private fun setVoteButtons(viewBinding: ItemCommentsBinding) {
when (comment.userVoteType) {
1 -> {
viewBinding.commentUpVote.setImageResource(R.drawable.ic_round_upvote_active_24)
viewBinding.commentUpVote.alpha = 1f
viewBinding.commentDownVote.setImageResource(R.drawable.ic_round_upvote_inactive_24)
}
-1 -> {
viewBinding.commentUpVote.setImageResource(R.drawable.ic_round_upvote_inactive_24)
viewBinding.commentDownVote.setImageResource(R.drawable.ic_round_upvote_active_24)
viewBinding.commentDownVote.alpha = 1f
}
else -> {
viewBinding.commentUpVote.setImageResource(R.drawable.ic_round_upvote_inactive_24)
viewBinding.commentDownVote.setImageResource(R.drawable.ic_round_upvote_inactive_24)
}
}
}
private fun formatTimestamp(timestamp: String): String {
return try {
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
dateFormat.timeZone = TimeZone.getTimeZone("UTC")
val parsedDate = dateFormat.parse(timestamp)
val currentDate = Date()
val diff = currentDate.time - (parsedDate?.time ?: 0)
val days = diff / (24 * 60 * 60 * 1000)
val hours = diff / (60 * 60 * 1000) % 24
val minutes = diff / (60 * 1000) % 60
return when {
days > 0 -> "$days days ago"
hours > 0 -> "$hours hours ago"
minutes > 0 -> "$minutes minutes ago"
else -> "just now"
}
} catch (e: Exception) {
"now"
}
}
companion object {
fun timestampToMillis(timestamp: String): Long {
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
dateFormat.timeZone = TimeZone.getTimeZone("UTC")
val parsedDate = dateFormat.parse(timestamp)
return parsedDate?.time ?: 0
}
}
}