fix: code cleanup | reply/edit stability

This commit is contained in:
rebelonion 2024-02-21 22:59:45 -06:00
parent a74b9e985d
commit ba7c665a9d
3 changed files with 336 additions and 353 deletions

View file

@ -194,10 +194,23 @@ object CommentsAPI {
429 -> "Rate limited. :(" 429 -> "Rate limited. :("
else -> "Failed to connect" else -> "Failed to connect"
} }
snackString("Error $code: ${reason ?: error}") val parsed = try {
Json.decodeFromString<ErrorResponse>(reason!!)
} catch (e: Exception) {
null
}
val message = parsed?.message ?: reason ?: error
snackString("Error $code: $message")
} }
} }
@Serializable
data class ErrorResponse(
@SerialName("message")
val message: String
)
@Serializable @Serializable
data class AuthResponse( data class AuthResponse(
@SerialName("authToken") @SerialName("authToken")

View file

@ -26,13 +26,14 @@ import java.util.TimeZone
class CommentItem(val comment: Comment, class CommentItem(val comment: Comment,
private val markwon: Markwon, private val markwon: Markwon,
private val section: Section, private val section: Section,
private val editCallback: (CommentItem) -> Unit, private val commentsActivity: CommentsActivity,
private val viewReplyCallback: (CommentItem) -> Unit,
private val replyCallback: (CommentItem) -> Unit
) : BindableItem<ItemCommentsBinding>() { ) : BindableItem<ItemCommentsBinding>() {
var binding: ItemCommentsBinding? = null var binding: ItemCommentsBinding? = null
val adapter = GroupieAdapter() val adapter = GroupieAdapter()
val repliesSection = Section() val repliesSection = Section()
private var isEditing = false
private var isReplying = false
private var repliesVisible = false
init { init {
adapter.add(repliesSection) adapter.add(repliesSection)
@ -58,37 +59,25 @@ class CommentItem(val comment: Comment,
} }
viewBinding.commentReply.visibility = View.VISIBLE viewBinding.commentReply.visibility = View.VISIBLE
viewBinding.commentTotalReplies.setOnClickListener { viewBinding.commentTotalReplies.setOnClickListener {
viewBinding.commentTotalReplies.visibility = View.GONE if (repliesVisible) {
viewReplyCallback(this) repliesSection.clear()
} viewBinding.commentTotalReplies.text = "View ${comment.replyCount} repl${if (comment.replyCount == 1) "y" else "ies"}"
var isEditing = false repliesVisible = false
var isReplying = false
viewBinding.commentEdit.setOnClickListener {
if (!isEditing) {
viewBinding.commentEdit.text = currActivity()!!.getString(R.string.cancel)
isEditing = true
isReplying = false
viewBinding.commentReply.text = "Reply"
editCallback(this)
} else { } else {
viewBinding.commentEdit.text = currActivity()!!.getString(R.string.edit) viewBinding.commentTotalReplies.text = "Hide Replies"
isEditing = false repliesSection.clear()
editCallback(this) commentsActivity.viewReplyCallback(this)
repliesVisible = true
}
} }
viewBinding.commentEdit.setOnClickListener {
editing(!isEditing)
commentsActivity.editCallback(this)
} }
viewBinding.commentReply.setOnClickListener { viewBinding.commentReply.setOnClickListener {
if (!isReplying) { replying(!isReplying)
viewBinding.commentReply.text = currActivity()!!.getString(R.string.cancel) commentsActivity.replyCallback(this)
isReplying = true
isEditing = false
viewBinding.commentEdit.text = currActivity()!!.getString(R.string.edit)
replyCallback(this)
} else {
viewBinding.commentReply.text = "Reply"
isReplying = false
replyCallback(this)
}
} }
viewBinding.modBadge.visibility = if (comment.isMod == true) View.VISIBLE else View.GONE 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.adminBadge.visibility = if (comment.isAdmin == true) View.VISIBLE else View.GONE
@ -165,6 +154,16 @@ class CommentItem(val comment: Comment,
return ItemCommentsBinding.bind(view) return ItemCommentsBinding.bind(view)
} }
fun replying(isReplying: Boolean) {
binding?.commentReply?.text = if (isReplying) currActivity()!!.getString(R.string.cancel) else "Reply"
this.isReplying = isReplying
}
fun editing(isEditing: Boolean) {
binding?.commentEdit?.text = if (isEditing) currActivity()!!.getString(R.string.cancel) else currActivity()!!.getString(R.string.edit)
this.isEditing = isEditing
}
private fun setVoteButtons(viewBinding: ItemCommentsBinding) { private fun setVoteButtons(viewBinding: ItemCommentsBinding) {
when (comment.userVoteType) { when (comment.userVoteType) {
1 -> { 1 -> {

View file

@ -11,6 +11,8 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.comments.Comment
import ani.dantotsu.connections.comments.CommentResponse
import ani.dantotsu.connections.comments.CommentsAPI import ani.dantotsu.connections.comments.CommentsAPI
import ani.dantotsu.databinding.ActivityCommentsBinding import ani.dantotsu.databinding.ActivityCommentsBinding
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
@ -43,10 +45,18 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale
import java.util.TimeZone import java.util.TimeZone
class CommentsActivity : AppCompatActivity() { class CommentsActivity : AppCompatActivity() {
lateinit var binding: ActivityCommentsBinding lateinit var binding: ActivityCommentsBinding
private var interactionState = InteractionState.NONE
private var commentWithInteraction: CommentItem? = null
private val section = Section()
private val adapter = GroupieAdapter()
private var mediaId: Int = -1
var pagesLoaded = 1
var totalPages = 1
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -60,9 +70,8 @@ class CommentsActivity : AppCompatActivity() {
snackString("Invalid Media ID") snackString("Invalid Media ID")
finish() finish()
} }
this.mediaId = mediaId
val adapter = GroupieAdapter()
val section = Section()
val markwon = buildMarkwon() val markwon = buildMarkwon()
binding.commentUserAvatar.loadImage(Anilist.avatar) binding.commentUserAvatar.loadImage(Anilist.avatar)
@ -74,250 +83,88 @@ class CommentsActivity : AppCompatActivity() {
) )
) )
binding.commentReplyToContainer.visibility = View.GONE //TODO: implement reply binding.commentReplyToContainer.visibility = View.GONE //TODO: implement reply
var editing = false
var editingCommentId = -1
var replying = false
var replyingComment: CommentItem? = null
fun editCallback(comment: CommentItem) {
replying = false
replyingComment = null
if (editingCommentId == comment.comment.commentId) {
editing = false
editingCommentId = -1
binding.commentInput.setText("")
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.commentInput.windowToken, 0)
} else {
editing = true
editingCommentId = comment.comment.commentId
binding.commentInput.setText(comment.comment.content)
binding.commentInput.requestFocus()
binding.commentInput.setSelection(binding.commentInput.text.length)
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.commentInput, InputMethodManager.SHOW_IMPLICIT)
}
}
fun replyCallback(comment: CommentItem) {
editing = false
editingCommentId = -1
if (replyingComment?.comment?.commentId == comment.comment.commentId) {
replying = false
replyingComment = null
binding.commentInput.setText("")
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.commentInput.windowToken, 0)
} else {
replying = true
replyingComment = comment
binding.commentInput.requestFocus()
binding.commentInput.setSelection(binding.commentInput.text.length)
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.commentInput, InputMethodManager.SHOW_IMPLICIT)
}
}
fun viewReplyCallback(comment: CommentItem) {
lifecycleScope.launch {
val replies = withContext(Dispatchers.IO) {
CommentsAPI.getRepliesFromId(comment.comment.commentId)
}
replies?.comments?.forEach {
comment.repliesSection.add(CommentItem(it, buildMarkwon(), comment.repliesSection, { comment ->
editCallback(comment)
}, { comment ->
viewReplyCallback(comment)
}, { comment ->
replyCallback(comment)
}))
}
}
}
binding.commentsRefresh.setOnRefreshListener { binding.commentsRefresh.setOnRefreshListener {
lifecycleScope.launch { lifecycleScope.launch {
binding.commentsList.visibility = View.GONE loadAndDisplayComments()
adapter.clear()
section.clear()
withContext(Dispatchers.IO) {
val comments = CommentsAPI.getCommentsForId(mediaId)
val sorted = when (PrefManager.getVal(PrefName.CommentSortOrder, "newest")) {
"newest" -> comments?.comments?.sortedByDescending { comment ->
CommentItem.timestampToMillis(comment.timestamp)
}
"oldest" -> comments?.comments?.sortedBy { comment ->
CommentItem.timestampToMillis(comment.timestamp)
}
"highest_rated" -> comments?.comments?.sortedByDescending { comment ->
comment.upvotes - comment.downvotes
}
"lowest_rated" -> comments?.comments?.sortedBy { comment ->
comment.upvotes - comment.downvotes
}
else -> comments?.comments
}
sorted?.forEach {
withContext(Dispatchers.Main) {
section.add(CommentItem(it, buildMarkwon(), section, { comment ->
editCallback(comment)
}, { comment ->
viewReplyCallback(comment)
}, { comment ->
replyCallback(comment)
}))
}
}
}
adapter.add(section)
binding.commentsList.visibility = View.VISIBLE
binding.commentsRefresh.isRefreshing = false binding.commentsRefresh.isRefreshing = false
} }
} }
var pagesLoaded = 1
var totalPages = 1
binding.commentsList.adapter = adapter binding.commentsList.adapter = adapter
binding.commentsList.layoutManager = LinearLayoutManager(this) binding.commentsList.layoutManager = LinearLayoutManager(this)
lifecycleScope.launch { lifecycleScope.launch {
binding.commentsProgressBar.visibility = View.VISIBLE loadAndDisplayComments()
binding.commentsList.visibility = View.GONE
withContext(Dispatchers.IO) {
val comments = CommentsAPI.getCommentsForId(mediaId)
val sorted = when (PrefManager.getVal(PrefName.CommentSortOrder, "newest")) {
"newest" -> comments?.comments?.sortedByDescending { comment ->
CommentItem.timestampToMillis(comment.timestamp)
} }
"oldest" -> comments?.comments?.sortedBy { comment -> binding.commentSort.setOnClickListener { view ->
CommentItem.timestampToMillis(comment.timestamp) fun sortComments(sortOrder: String) {
val groups = section.groups
when (sortOrder) {
"newest" -> groups.sortByDescending { CommentItem.timestampToMillis((it as CommentItem).comment.timestamp) }
"oldest" -> groups.sortBy { CommentItem.timestampToMillis((it as CommentItem).comment.timestamp) }
"highest_rated" -> groups.sortByDescending { (it as CommentItem).comment.upvotes - it.comment.downvotes }
"lowest_rated" -> groups.sortBy { (it as CommentItem).comment.upvotes - it.comment.downvotes }
}
section.update(groups)
} }
"highest_rated" -> comments?.comments?.sortedByDescending { comment -> val popup = PopupMenu(this, view)
comment.upvotes - comment.downvotes
}
"lowest_rated" -> comments?.comments?.sortedBy { comment ->
comment.upvotes - comment.downvotes
}
else -> comments?.comments
}
sorted?.forEach {
withContext(Dispatchers.Main) {
section.add(CommentItem(it, buildMarkwon(), section, { comment ->
editCallback(comment)
}, { comment ->
viewReplyCallback(comment)
}, { comment ->
replyCallback(comment)
}))
}
}
totalPages = comments?.totalPages ?: 1
}
binding.commentsProgressBar.visibility = View.GONE
binding.commentsList.visibility = View.VISIBLE
adapter.add(section)
}
binding.commentSort.setOnClickListener {
val popup = PopupMenu(this, it)
popup.setOnMenuItemClickListener { item -> popup.setOnMenuItemClickListener { item ->
when (item.itemId) { val sortOrder = when (item.itemId) {
R.id.comment_sort_newest -> { R.id.comment_sort_newest -> "newest"
PrefManager.setVal(PrefName.CommentSortOrder, "newest") R.id.comment_sort_oldest -> "oldest"
val groups = section.groups R.id.comment_sort_highest_rated -> "highest_rated"
groups.sortByDescending { comment -> R.id.comment_sort_lowest_rated -> "lowest_rated"
comment as CommentItem else -> return@setOnMenuItemClickListener false
CommentItem.timestampToMillis(comment.comment.timestamp)
}
section.update(groups)
binding.commentsList.scrollToPosition(0)
} }
R.id.comment_sort_oldest -> { PrefManager.setVal(PrefName.CommentSortOrder, sortOrder)
PrefManager.setVal(PrefName.CommentSortOrder, "oldest") sortComments(sortOrder)
val groups = section.groups
groups.sortBy { comment ->
comment as CommentItem
CommentItem.timestampToMillis(comment.comment.timestamp)
}
section.update(groups)
binding.commentsList.scrollToPosition(0) binding.commentsList.scrollToPosition(0)
}
R.id.comment_sort_highest_rated -> {
PrefManager.setVal(PrefName.CommentSortOrder, "highest_rated")
val groups = section.groups
groups.sortByDescending { comment ->
comment as CommentItem
comment.comment.upvotes - comment.comment.downvotes
}
section.update(groups)
binding.commentsList.scrollToPosition(0)
}
R.id.comment_sort_lowest_rated -> {
PrefManager.setVal(PrefName.CommentSortOrder, "lowest_rated")
val groups = section.groups
groups.sortBy { comment ->
comment as CommentItem
comment.comment.upvotes - comment.comment.downvotes
}
section.update(groups)
binding.commentsList.scrollToPosition(0)
}
}
true true
} }
popup.inflate(R.menu.comments_sort_menu) popup.inflate(R.menu.comments_sort_menu)
popup.show() popup.show()
} }
var fetching = false var isFetching = false
//if we have scrolled to the bottom of the list, load more comments //if we have scrolled to the bottom of the list, load more comments
binding.commentsList.addOnScrollListener(object : binding.commentsList.addOnScrollListener(object : androidx.recyclerview.widget.RecyclerView.OnScrollListener() {
androidx.recyclerview.widget.RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: androidx.recyclerview.widget.RecyclerView, dx: Int, dy: Int) {
override fun onScrolled(
recyclerView: androidx.recyclerview.widget.RecyclerView,
dx: Int,
dy: Int
) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
if (!recyclerView.canScrollVertically(1)) { if (shouldLoadMoreComments(recyclerView)) {
if (pagesLoaded < totalPages && !fetching) { loadMoreComments()
fetching = true
lifecycleScope.launch {
withContext(Dispatchers.IO) {
val comments =
CommentsAPI.getCommentsForId(mediaId, pagesLoaded + 1)
comments?.comments?.forEach {
withContext(Dispatchers.Main) {
section.add(
CommentItem(
it,
buildMarkwon(),
section, { comment ->
editCallback(comment)
}, { comment ->
viewReplyCallback(comment)
}, { comment ->
replyCallback(comment)
})
)
} }
} }
private fun shouldLoadMoreComments(recyclerView: androidx.recyclerview.widget.RecyclerView): Boolean {
return !recyclerView.canScrollVertically(1) && pagesLoaded < totalPages && !isFetching
}
private fun loadMoreComments() {
isFetching = true
lifecycleScope.launch {
val comments = fetchComments()
comments?.comments?.forEach { comment ->
updateUIWithComment(comment)
}
totalPages = comments?.totalPages ?: 1 totalPages = comments?.totalPages ?: 1
}
pagesLoaded++ pagesLoaded++
fetching = false isFetching = false
} }
} }
private suspend fun fetchComments(): CommentResponse? {
return withContext(Dispatchers.IO) {
CommentsAPI.getCommentsForId(mediaId, pagesLoaded + 1)
}
}
private suspend fun updateUIWithComment(comment: Comment) {
withContext(Dispatchers.Main) {
section.add(CommentItem(comment, buildMarkwon(), section, this@CommentsActivity))
} }
} }
}) })
@ -342,79 +189,137 @@ class CommentsActivity : AppCompatActivity() {
snackString("You are banned from commenting :(") snackString("You are banned from commenting :(")
return@setOnClickListener return@setOnClickListener
} }
fun onSuccess() {
binding.commentInput.text.toString().let { if (PrefManager.getVal(PrefName.FirstComment)) {
if (it.isNotEmpty()) { showCommentRulesDialog()
binding.commentInput.text.clear() } else {
processComment()
}
}
}
enum class InteractionState {
NONE, EDIT, REPLY
}
private suspend fun loadAndDisplayComments() {
binding.commentsProgressBar.visibility = View.VISIBLE
binding.commentsList.visibility = View.GONE
adapter.clear()
section.clear()
val comments = withContext(Dispatchers.IO) {
CommentsAPI.getCommentsForId(mediaId)
}
val sortedComments = sortComments(comments?.comments)
sortedComments.forEach {
withContext(Dispatchers.Main) {
section.add(CommentItem(it, buildMarkwon(), section, this@CommentsActivity))
}
}
totalPages = comments?.totalPages ?: 1
binding.commentsProgressBar.visibility = View.GONE
binding.commentsList.visibility = View.VISIBLE
adapter.add(section)
}
private fun sortComments(comments: List<Comment>?): List<Comment> {
if (comments == null) return emptyList()
val sortOrder = PrefManager.getVal(PrefName.CommentSortOrder, "newest")
return when (sortOrder) {
"newest" -> comments.sortedByDescending { CommentItem.timestampToMillis(it.timestamp) }
"oldest" -> comments.sortedBy { CommentItem.timestampToMillis(it.timestamp) }
"highest_rated" -> comments.sortedByDescending { it.upvotes - it.downvotes }
"lowest_rated" -> comments.sortedBy { it.upvotes - it.downvotes }
else -> comments
}
}
/**
* Resets the old state of the comment input
* @return the old state
*/
private fun resetOldState(): InteractionState {
val oldState = interactionState
interactionState = InteractionState.NONE
return when (oldState) {
InteractionState.EDIT -> {
binding.commentInput.setText("")
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.commentInput.windowToken, 0)
commentWithInteraction?.editing(false)
InteractionState.EDIT
}
InteractionState.REPLY -> {
binding.commentInput.setText("")
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(binding.commentInput.windowToken, 0)
commentWithInteraction?.replying(false)
InteractionState.REPLY
}
else -> {
InteractionState.NONE
}
}
}
/**
* Callback from the comment item to edit the comment
* Called every time the edit button is clicked
* @param comment the comment to edit
*/
fun editCallback(comment: CommentItem) {
if (resetOldState() == InteractionState.EDIT) return
commentWithInteraction = comment
binding.commentInput.setText(comment.comment.content)
binding.commentInput.requestFocus()
binding.commentInput.setSelection(binding.commentInput.text.length)
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.commentInput, InputMethodManager.SHOW_IMPLICIT)
interactionState = InteractionState.EDIT
}
/**
* Callback from the comment item to reply to the comment
* Called every time the reply button is clicked
* @param comment the comment to reply to
*/
fun replyCallback(comment: CommentItem) {
if (resetOldState() == InteractionState.REPLY) return
commentWithInteraction = comment
binding.commentInput.requestFocus()
binding.commentInput.setSelection(binding.commentInput.text.length)
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(binding.commentInput, InputMethodManager.SHOW_IMPLICIT)
interactionState = InteractionState.REPLY
}
fun viewReplyCallback(comment: CommentItem) {
lifecycleScope.launch { lifecycleScope.launch {
if (editing) { val replies = withContext(Dispatchers.IO) {
val success = withContext(Dispatchers.IO) { CommentsAPI.getRepliesFromId(comment.comment.commentId)
CommentsAPI.editComment(editingCommentId, it)
} }
if (success) { replies?.comments?.forEach {
val groups = section.groups comment.repliesSection.add(
groups.forEach { item ->
if (item is CommentItem) {
if (item.comment.commentId == editingCommentId) {
item.comment.content = it
val dateFormat =
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
dateFormat.timeZone =
TimeZone.getTimeZone("UTC")
item.comment.timestamp =
dateFormat.format(System.currentTimeMillis())
item.notifyChanged()
snackString("Comment edited")
}
}
}
}
} else {
val success = withContext(Dispatchers.IO) {
CommentsAPI.comment(mediaId, if (replying) replyingComment!!.comment.commentId else null, it)
}
if (success != null)
if (replying) {
replyingComment?.repliesSection?.add(
0,
CommentItem( CommentItem(
success, it,
buildMarkwon(), buildMarkwon(),
replyingComment?.repliesSection!!, { comment -> comment.repliesSection,
editCallback(comment) this@CommentsActivity)
}, { comment ->
viewReplyCallback(comment)
}, { comment ->
replyCallback(comment)
})
)
} else {
section.add(
0,
CommentItem(
success,
buildMarkwon(),
section, { comment ->
editCallback(comment)
}, { comment ->
viewReplyCallback(comment)
}, { comment ->
replyCallback(comment)
})
) )
} }
} }
} }
} else {
snackString("Comment cannot be empty")
}
}
}
val firstComment = PrefManager.getVal<Boolean>(PrefName.FirstComment) /**
if (firstComment) { * Shows the comment rules dialog
//show a dialog explaining the rules * Called when the user tries to comment for the first time
*/
private fun showCommentRulesDialog() {
val alertDialog = android.app.AlertDialog.Builder(this, R.style.MyPopup) val alertDialog = android.app.AlertDialog.Builder(this, R.style.MyPopup)
.setTitle("Commenting Rules") .setTitle("Commenting Rules")
.setMessage( .setMessage(
@ -433,20 +338,86 @@ class CommentsActivity : AppCompatActivity() {
.setPositiveButton("I Understand") { dialog, _ -> .setPositiveButton("I Understand") { dialog, _ ->
dialog.dismiss() dialog.dismiss()
PrefManager.setVal(PrefName.FirstComment, false) PrefManager.setVal(PrefName.FirstComment, false)
onSuccess() processComment()
} }
.setNegativeButton("Cancel") { dialog, _ -> .setNegativeButton("Cancel") { dialog, _ ->
dialog.dismiss() dialog.dismiss()
} }
val dialog = alertDialog.show() val dialog = alertDialog.show()
dialog?.window?.setDimAmount(0.8f) dialog?.window?.setDimAmount(0.8f)
}
private fun processComment() {
val commentText = binding.commentInput.text.toString()
if (commentText.isEmpty()) {
snackString("Comment cannot be empty")
return
}
binding.commentInput.text.clear()
lifecycleScope.launch {
if (interactionState == InteractionState.EDIT) {
handleEditComment(commentText)
} else { } else {
onSuccess() handleNewComment(commentText)
} }
} }
} }
private suspend fun handleEditComment(commentText: String) {
val success = withContext(Dispatchers.IO) {
CommentsAPI.editComment(commentWithInteraction?.comment?.commentId ?: return@withContext false, commentText)
}
if (success) {
updateCommentInSection(commentText)
}
}
private fun updateCommentInSection(commentText: String) {
val groups = section.groups
groups.forEach { item ->
if (item is CommentItem && item.comment.commentId == commentWithInteraction?.comment?.commentId) {
updateCommentItem(item, commentText)
snackString("Comment edited")
}
}
}
private fun updateCommentItem(item: CommentItem, commentText: String) {
item.comment.content = commentText
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
dateFormat.timeZone = TimeZone.getTimeZone("UTC")
item.comment.timestamp = dateFormat.format(System.currentTimeMillis())
item.notifyChanged()
}
private suspend fun handleNewComment(commentText: String) {
val success = withContext(Dispatchers.IO) {
CommentsAPI.comment(
mediaId,
if (interactionState == InteractionState.REPLY) commentWithInteraction?.comment?.commentId else null,
commentText
)
}
success?.let {
if (interactionState == InteractionState.REPLY) {
commentWithInteraction?.repliesSection?.add(
0,
CommentItem(it, buildMarkwon(), commentWithInteraction!!.repliesSection, this@CommentsActivity)
)
} else {
section.add(
0,
CommentItem(it, buildMarkwon(), section, this@CommentsActivity)
)
}
}
}
/**
* Builds the markwon instance with all the plugins
* @return the markwon instance
*/
private fun buildMarkwon(): Markwon { private fun buildMarkwon(): Markwon {
val markwon = Markwon.builder(this) val markwon = Markwon.builder(this)
.usePlugin(SoftBreakAddsNewLinePlugin.create()) .usePlugin(SoftBreakAddsNewLinePlugin.create())