콘텐츠 댓글 삭제 기능 추가

This commit is contained in:
klaus 2023-09-06 13:59:50 +09:00
parent 4f54545081
commit e9370e02be
9 changed files with 175 additions and 4 deletions

View File

@ -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>>
} }

View File

@ -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()
}
} }

View File

@ -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)

View File

@ -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("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
}
)
)
}
} }

View File

@ -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
)
} }

View File

@ -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,

View File

@ -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
)

View File

@ -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"

View File

@ -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>