콘텐츠 댓글 삭제 기능 추가

This commit is contained in:
2023-09-06 13:59:50 +09:00
parent 4f54545081
commit e9370e02be
9 changed files with 175 additions and 4 deletions
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.audio_content
import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.core.Single
import kr.co.vividnext.sodalive.audio_content.comment.GetAudioContentCommentListResponse import kr.co.vividnext.sodalive.audio_content.comment.GetAudioContentCommentListResponse
import kr.co.vividnext.sodalive.audio_content.comment.ModifyCommentRequest
import kr.co.vividnext.sodalive.audio_content.comment.RegisterAudioContentCommentRequest import kr.co.vividnext.sodalive.audio_content.comment.RegisterAudioContentCommentRequest
import kr.co.vividnext.sodalive.audio_content.detail.GetAudioContentDetailResponse import kr.co.vividnext.sodalive.audio_content.detail.GetAudioContentDetailResponse
import kr.co.vividnext.sodalive.audio_content.detail.PutAudioContentLikeRequest import kr.co.vividnext.sodalive.audio_content.detail.PutAudioContentLikeRequest
@@ -137,4 +138,10 @@ interface AudioContentApi {
@Body request: AudioContentDonationRequest, @Body request: AudioContentDonationRequest,
@Header("Authorization") authHeader: String @Header("Authorization") authHeader: String
): Single<ApiResponse<Any>> ): Single<ApiResponse<Any>>
@PUT("/audio-content/comment")
fun modifyComment(
@Body request: ModifyCommentRequest,
@Header("Authorization") authHeader: String
): Single<ApiResponse<Any>>
} }
@@ -1,24 +1,30 @@
package kr.co.vividnext.sodalive.audio_content.comment package kr.co.vividnext.sodalive.audio_content.comment
import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.appcompat.widget.PopupMenu
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import coil.load import coil.load
import coil.transform.CircleCropTransformation import coil.transform.CircleCropTransformation
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.databinding.ItemAudioContentCommentBinding import kr.co.vividnext.sodalive.databinding.ItemAudioContentCommentBinding
import kr.co.vividnext.sodalive.extensions.dpToPx import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.extensions.moneyFormat import kr.co.vividnext.sodalive.extensions.moneyFormat
class AudioContentCommentAdapter( class AudioContentCommentAdapter(
private val creatorId: Long,
private val onClickDelete: (Long) -> Unit,
private val onItemClick: (GetAudioContentCommentListItem) -> Unit private val onItemClick: (GetAudioContentCommentListItem) -> Unit
) : RecyclerView.Adapter<AudioContentCommentAdapter.ViewHolder>() { ) : RecyclerView.Adapter<AudioContentCommentAdapter.ViewHolder>() {
var items = mutableSetOf<GetAudioContentCommentListItem>() var items = mutableSetOf<GetAudioContentCommentListItem>()
inner class ViewHolder( inner class ViewHolder(
private val context: Context,
private val binding: ItemAudioContentCommentBinding private val binding: ItemAudioContentCommentBinding
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
@@ -82,12 +88,31 @@ class AudioContentCommentAdapter(
"답글 쓰기" "답글 쓰기"
} }
if (
item.writerId == SharedPreferenceManager.userId ||
creatorId == SharedPreferenceManager.userId
) {
binding.ivMenu.visibility = View.VISIBLE
binding.ivMenu.setOnClickListener {
showOptionMenu(
context,
binding.ivMenu,
commentId = item.id,
writerId = item.writerId,
creatorId = creatorId
)
}
} else {
binding.ivMenu.visibility = View.GONE
}
binding.tvWriteReply.setOnClickListener { onItemClick(item) } binding.tvWriteReply.setOnClickListener { onItemClick(item) }
binding.root.setOnClickListener { onItemClick(item) } binding.root.setOnClickListener { onItemClick(item) }
} }
} }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
parent.context,
ItemAudioContentCommentBinding.inflate( ItemAudioContentCommentBinding.inflate(
LayoutInflater.from(parent.context), LayoutInflater.from(parent.context),
parent, parent,
@@ -100,4 +125,34 @@ class AudioContentCommentAdapter(
} }
override fun getItemCount() = items.size override fun getItemCount() = items.size
private fun showOptionMenu(
context: Context,
v: View,
commentId: Long,
writerId: Long,
creatorId: Long
) {
val popup = PopupMenu(context, v)
val inflater = popup.menuInflater
if (
writerId == SharedPreferenceManager.userId ||
creatorId == SharedPreferenceManager.userId
) {
inflater.inflate(R.menu.content_comment_option_menu, popup.menu)
}
popup.setOnMenuItemClickListener {
when (it.itemId) {
R.id.menu_review_delete -> {
onClickDelete(commentId)
}
}
true
}
popup.show()
}
} }
@@ -15,6 +15,7 @@ import coil.load
import coil.transform.CircleCropTransformation import coil.transform.CircleCropTransformation
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.base.BaseFragment import kr.co.vividnext.sodalive.base.BaseFragment
import kr.co.vividnext.sodalive.base.SodaDialog
import kr.co.vividnext.sodalive.common.Constants import kr.co.vividnext.sodalive.common.Constants
import kr.co.vividnext.sodalive.common.LoadingDialog import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.common.SharedPreferenceManager
@@ -74,9 +75,30 @@ class AudioContentCommentListFragment : BaseFragment<FragmentAudioContentComment
viewModel.registerComment(audioContentId, comment) viewModel.registerComment(audioContentId, comment)
} }
adapter = AudioContentCommentAdapter { adapter = AudioContentCommentAdapter(
(parentFragment as AudioContentCommentFragment).onClickComment(it) creatorId = 0,
} onClickDelete = {
SodaDialog(
activity = requireActivity(),
layoutInflater = layoutInflater,
title = "댓글 삭제",
desc = "삭제하시겠습니까?",
confirmButtonTitle = "삭제",
confirmButtonClick = {
viewModel.modifyComment(
commentId = it,
audioContentId = audioContentId,
isActive = false
)
},
cancelButtonTitle = "취소",
cancelButtonClick = {}
).show(screenWidth)
},
onItemClick = {
(parentFragment as AudioContentCommentFragment).onClickComment(it)
}
)
val recyclerView = binding.rvComment val recyclerView = binding.rvComment
recyclerView.setHasFixedSize(true) recyclerView.setHasFixedSize(true)
@@ -122,4 +122,61 @@ class AudioContentCommentListViewModel(
) )
) )
} }
fun modifyComment(
commentId: Long,
audioContentId: Long,
comment: String? = null,
isActive: Boolean? = null
) {
if (comment == null && isActive == null) {
_toastLiveData.postValue("변경사항이 없습니다.")
return
}
if (comment != null && comment.isBlank()) {
_toastLiveData.postValue("내용을 입력하세요")
return
}
_isLoading.value = true
val request = ModifyCommentRequest(commentId = commentId)
if (comment != null) {
request.comment = comment
}
if (isActive != null) {
request.isActive = isActive
}
compositeDisposable.add(
repository.modifyComment(
request = request,
token = "Bearer ${SharedPreferenceManager.token}"
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
_isLoading.value = false
if (it.success) {
page = 1
isLast = false
getCommentList(audioContentId)
} else {
val message = it.message ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
_toastLiveData.postValue(message)
}
},
{
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
}
)
)
}
} }
@@ -43,4 +43,9 @@ class AudioContentCommentRepository(private val api: AudioContentApi) {
timezone = TimeZone.getDefault().id, timezone = TimeZone.getDefault().id,
authHeader = token authHeader = token
) )
fun modifyComment(request: ModifyCommentRequest, token: String) = api.modifyComment(
request = request,
authHeader = token
)
} }
@@ -12,6 +12,7 @@ data class GetAudioContentCommentListResponse(
@Parcelize @Parcelize
data class GetAudioContentCommentListItem( data class GetAudioContentCommentListItem(
@SerializedName("id") val id: Long, @SerializedName("id") val id: Long,
@SerializedName("writerId") val writerId: Long,
@SerializedName("nickname") val nickname: String, @SerializedName("nickname") val nickname: String,
@SerializedName("profileUrl") val profileUrl: String, @SerializedName("profileUrl") val profileUrl: String,
@SerializedName("comment") val comment: String, @SerializedName("comment") val comment: String,
@@ -0,0 +1,7 @@
package kr.co.vividnext.sodalive.audio_content.comment
data class ModifyCommentRequest(
val commentId: Long,
var comment: String? = null,
var isActive: Boolean? = null
)
@@ -21,11 +21,20 @@
android:fontFamily="@font/gmarket_sans_medium" android:fontFamily="@font/gmarket_sans_medium"
android:textColor="@color/color_eeeeee" android:textColor="@color/color_eeeeee"
android:textSize="13.3sp" android:textSize="13.3sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@+id/iv_menu"
app:layout_constraintStart_toEndOf="@+id/iv_comment_profile" app:layout_constraintStart_toEndOf="@+id/iv_comment_profile"
app:layout_constraintTop_toTopOf="@+id/iv_comment_profile" app:layout_constraintTop_toTopOf="@+id/iv_comment_profile"
tools:text="alkfje203" /> tools:text="alkfje203" />
<ImageView
android:id="@+id/iv_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/ic_seemore_vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/iv_comment_profile" />
<TextView <TextView
android:id="@+id/tv_comment_date" android:id="@+id/tv_comment_date"
android:layout_width="0dp" android:layout_width="0dp"
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_review_delete"
android:title="삭제"
app:showAsAction="ifRoom" />
</menu>