feat(character-comment): 신고 BottomSheet 추가 및 삭제 확인 팝업 도입
- 신고 BottomSheet(제목/단일선택 리스트/신고 버튼) 구현 및 더보기→신고 흐름 연동 - 삭제 버튼 클릭 시 확인 다이얼로그 표시 후 확정 시 리스트에서 제거 - 신고/삭제 API 호출부는 스텁으로 남겨둠(후속 연동 예정)
This commit is contained in:
@@ -92,14 +92,29 @@ class CharacterCommentListFragment : BaseFragment<FragmentCharacterCommentListBi
|
||||
onClickMore = { item, isOwner, anchor ->
|
||||
CharacterCommentMoreBottomSheet.newInstance(isOwner).apply {
|
||||
onReport = {
|
||||
Toast.makeText(requireContext(), "신고되었습니다 (stub)", Toast.LENGTH_SHORT).show()
|
||||
// 더보기 닫히고 신고 BottomSheet 열림
|
||||
val reportSheet = CharacterCommentReportBottomSheet.newInstance()
|
||||
reportSheet.onSubmit = { reason ->
|
||||
// 신고 API 스텁 호출 지점
|
||||
Toast.makeText(requireContext(), "신고 접수: $reason (stub)", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
reportSheet.show(childFragmentManager, "comment_report")
|
||||
}
|
||||
onDelete = {
|
||||
val index = adapter.items.indexOfFirst { it.commentId == item.commentId }
|
||||
if (index >= 0) {
|
||||
adapter.items.removeAt(index)
|
||||
adapter.notifyItemRemoved(index)
|
||||
}
|
||||
// 삭제 확인 팝업
|
||||
androidx.appcompat.app.AlertDialog.Builder(requireContext())
|
||||
.setTitle(getString(R.string.confirm_delete_title))
|
||||
.setMessage(getString(R.string.confirm_delete_message))
|
||||
.setPositiveButton(getString(R.string.confirm)) { _, _ ->
|
||||
// 삭제 API 스텁 호출 지점
|
||||
val index = adapter.items.indexOfFirst { it.commentId == item.commentId }
|
||||
if (index >= 0) {
|
||||
adapter.items.removeAt(index)
|
||||
adapter.notifyItemRemoved(index)
|
||||
}
|
||||
}
|
||||
.setNegativeButton(getString(R.string.cancel), null)
|
||||
.show()
|
||||
}
|
||||
}.show(childFragmentManager, "comment_more")
|
||||
},
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
package kr.co.vividnext.sodalive.chat.character.comment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import kr.co.vividnext.sodalive.R
|
||||
|
||||
/**
|
||||
* 댓글/답글 신고 BottomSheet (Stub)
|
||||
* - 제목: 신고
|
||||
* - 신고 이유 단일 선택 목록(String List 주입 가능, 미주입 시 기본 목록 사용)
|
||||
* - 최하단 신고 버튼(선택 전 비활성화, 선택 후 활성화)
|
||||
* - 신고 버튼 클릭 시 onSubmit(reason) 콜백 호출 후 닫기 (API 스텁 호출은 콜백 쪽에서 처리)
|
||||
*/
|
||||
class CharacterCommentReportBottomSheet : BottomSheetDialogFragment() {
|
||||
|
||||
var onSubmit: ((String) -> Unit)? = null
|
||||
|
||||
private var reasons: ArrayList<String>? = null
|
||||
private var selectedIndex: Int = -1
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
reasons = arguments?.getStringArrayList(ARG_REASONS) ?: DEFAULT_REASONS
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
val view = inflater.inflate(R.layout.dialog_character_comment_report, container, false)
|
||||
val tvTitle = view.findViewById<TextView>(R.id.tv_title)
|
||||
val llList = view.findViewById<LinearLayout>(R.id.ll_reason_list)
|
||||
val btnReport = view.findViewById<Button>(R.id.btn_report)
|
||||
val ivClose = view.findViewById<ImageView>(R.id.iv_close)
|
||||
|
||||
tvTitle.text = getString(R.string.report_title)
|
||||
btnReport.isEnabled = false
|
||||
|
||||
val items = reasons ?: DEFAULT_REASONS
|
||||
|
||||
// 동적 리스트 구성: 단일 선택
|
||||
items.forEachIndexed { index, text ->
|
||||
val itemView = inflater.inflate(R.layout.item_report_reason, llList, false)
|
||||
val tvText = itemView.findViewById<TextView>(R.id.tv_reason)
|
||||
val ivCheck = itemView.findViewById<ImageView>(R.id.iv_check)
|
||||
tvText.text = text
|
||||
ivCheck.isVisible = index == selectedIndex
|
||||
itemView.setOnClickListener {
|
||||
selectedIndex = index
|
||||
// 전체를 다시 그릴 정도는 아니므로 자식들만 순회하며 체크 상태 갱신
|
||||
for (i in 0 until llList.childCount) {
|
||||
val child = llList.getChildAt(i)
|
||||
val check = child.findViewById<ImageView>(R.id.iv_check)
|
||||
check?.isVisible = i == selectedIndex
|
||||
}
|
||||
btnReport.isEnabled = true
|
||||
}
|
||||
llList.addView(itemView)
|
||||
}
|
||||
|
||||
ivClose.setOnClickListener { dismiss() }
|
||||
btnReport.setOnClickListener {
|
||||
val idx = selectedIndex
|
||||
if (idx in items.indices) {
|
||||
onSubmit?.invoke(items[idx])
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ARG_REASONS = "arg_reasons"
|
||||
|
||||
private val DEFAULT_REASONS = arrayListOf(
|
||||
"스팸/광고", "욕설/비하", "음란물/불건전", "개인정보 노출", "기타"
|
||||
)
|
||||
|
||||
fun newInstance(reasons: ArrayList<String>? = null): CharacterCommentReportBottomSheet {
|
||||
return CharacterCommentReportBottomSheet().apply {
|
||||
arguments = bundleOf(ARG_REASONS to reasons)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import coil.load
|
||||
import coil.transform.CircleCropTransformation
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||
import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentListBottomSheet
|
||||
import kr.co.vividnext.sodalive.chat.talk.room.ChatRoomActivity
|
||||
import kr.co.vividnext.sodalive.common.LoadingDialog
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
@@ -226,14 +227,14 @@ class CharacterDetailActivity : BaseActivity<ActivityCharacterDetailBinding>(
|
||||
binding.llCommentsSection.setOnClickListener(null)
|
||||
if (detail.totalComments > 0) {
|
||||
binding.llCommentsSection.setOnClickListener {
|
||||
val sheet = kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentListBottomSheet(detail.characterId)
|
||||
val sheet = CharacterCommentListBottomSheet(detail.characterId)
|
||||
sheet.show(supportFragmentManager, "character_comments")
|
||||
}
|
||||
}
|
||||
if (
|
||||
detail.totalComments > 0 &&
|
||||
detail.latestComment != null &&
|
||||
!detail.latestComment.comment.isNullOrBlank()
|
||||
detail.latestComment.comment.isNotBlank()
|
||||
) {
|
||||
binding.llLatestComment.visibility = View.VISIBLE
|
||||
binding.llNoComment.visibility = View.GONE
|
||||
@@ -256,10 +257,7 @@ class CharacterDetailActivity : BaseActivity<ActivityCharacterDetailBinding>(
|
||||
}
|
||||
}
|
||||
|
||||
val commentText = latest.comment
|
||||
binding.tvLatestComment.text = if (!commentText.isNullOrBlank()) {
|
||||
commentText
|
||||
} else {
|
||||
binding.tvLatestComment.text = latest.comment.ifBlank {
|
||||
latest.memberNickname
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user