Skip to content

Conversation

@onlyone130
Copy link
Contributor

@onlyone130 onlyone130 commented Aug 20, 2025

체크리스트

  • 빌드가 되는 것을 확인 하셨나요??
  • 리뷰어 할당과 본인 할당 잊지마세요
  • 적절한 태그를 부여 해주세요

📝작업 내용

이번 PR에서 작업한 내용을 간략히 설명해주세요

신고하기 버튼 클릭시 커스텀 다이얼로그가 뜨도록 설정

스크린샷

작업한 화면기능의 스크린샷을 첨부해 주세요

💬리뷰 요구사항(선택)

리뷰어가 특별히 봐주었으면 하는 부분이나 함께 고민해봐야할 부분이 있다면 작성해주세요

Summary by CodeRabbit

  • 신규 기능
    • 채팅방 참여자 신고 기능을 전용 신고 다이얼로그로 개선했습니다. 스팸/도배, 스포성 채팅, 욕설, 혐오 발언, 부적절한 닉네임 등 사유를 선택하고 추가 내용을 입력해 제출할 수 있습니다.
    • 참여자 항목 클릭 및 메뉴에서 동일한 신고 다이얼로그를 호출하도록 통합하여 일관된 UX를 제공합니다.
    • 기존 간단 확인 팝업/토스트 흐름을 대체해, 더 명확한 신고 절차와 입력 경험을 제공합니다.

@onlyone130 onlyone130 self-assigned this Aug 20, 2025
@onlyone130 onlyone130 added 🐛 BugFix 오류 해결 🔨 Refactor 코드 리팩토링 labels Aug 20, 2025
@coderabbitai
Copy link

coderabbitai bot commented Aug 20, 2025

Walkthrough

  • ChatRoomParticipantRVAdapter.kt: R import 추가만 수행.
  • ChatRoomParticipantsFragment.kt: 기존 투버튼 팝업 기반 신고 확인 흐름 제거. 참가자 아이템 클릭 및 팝업 메뉴 클릭 시 showReportPopup() 호출로 교체. showReportPopup()는 dialog_report 레이아웃을 AlertDialog로 표시.
  • ReportDialogFragment.kt: 참가자 신고용 DialogFragment 신설. 체크박스 선택 이유 수집, 추가 입력(etDetail) 포함, onSubmit 콜백 제공. 투명 배경, 외부 터치 닫힘, 고정 크기 설정. dpToPx 유틸 포함.
  • 리소스 추가: dialog_report.xml, fragment_report_dialog.xml, item_report_reason.xml.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor U as 사용자
    participant F as ChatRoomParticipantsFragment
    participant D as AlertDialog(dialog_report)
    Note over F: 기존: TwoButtonPopup + Toast 흐름 제거

    U->>F: 참가자 아이템/메뉴에서 "신고" 선택
    F->>F: showReportPopup() 호출
    F->>D: dialog_report 인플레이트 및 표시
    U->>D: 이유 체크/추가 내용 입력 후 제출
    D-->>F: (레이아웃에 정의된 액션에 따름)
Loading
sequenceDiagram
    autonumber
    actor U as 사용자
    participant F as ChatRoomParticipantsFragment
    participant R as ReportDialogFragment
    Note over R: 새로 추가된 대안적 신고 UI

    U->>F: "신고" 선택
    F-->>R: (필요 시) ReportDialogFragment 표시
    U->>R: 이유 선택 + 추가 사유 입력
    R-->>F: onSubmit(reasons, extraReason)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/온보딩-팝업창

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ChatRoomParticipantsFragment.kt (1)

66-69: hostData!! NPE 위험: 아직 hostData가 채워지기 전에 클릭 리스너를 설정하고 있습니다.
초기 로딩 타이밍에 null이면 즉시 크래시 납니다.

간단 가드 또는 hostData 세팅 이후에 리스너를 부여하세요.

-        binding.itemRoomManager.ivMore.setOnClickListener { showPopupMenu( binding.itemRoomManager.ivMore,hostData!! ) }
+        binding.itemRoomManager.ivMore.setOnClickListener {
+            hostData?.let { data -> showPopupMenu(binding.itemRoomManager.ivMore, data) }
+        }

보다 안전한 방법은 setParticipants()에서 hostData가 갱신된 시점에만 리스너/표시를 설정하는 것입니다.

🧹 Nitpick comments (17)
app/src/main/res/layout/dialog_report.xml (6)

5-7: 고정된 dp 크기(320x494)로 레이아웃을 잡으면 기기/회전/키보드 진입 시 레이아웃 깨질 수 있습니다. 다이얼로그 크기 제어는 코드에서, 레이아웃은 wrap_content로 두는 편이 안전합니다.
ReportDialogFragment에서 window.setLayout으로 크기를 제어하고, XML은 내용 크기에 맞추는 것이 권장됩니다.

다음과 같이 변경을 제안드립니다.

-    android:layout_width="320dp"
-    android:layout_height="494dp"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"

32-44: android:showDividers만 지정되어 있고 divider drawable이 없습니다.
divider가 보이지 않을 수 있습니다. 간단한 shape drawable을 지정해 주세요.

예시:

     <LinearLayout
         android:id="@+id/layoutReasons"
         android:layout_width="0dp"
         android:layout_height="0dp"
         android:orientation="vertical"
-        android:showDividers="middle"
+        android:showDividers="middle"
+        android:divider="@drawable/divider_horizontal_1dp"

추가 리소스(res/drawable/divider_horizontal_1dp.xml):

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <size android:height="1dp"/>
    <solid android:color="@android:color/darker_gray"/>
</shape>

67-71: 장식용 화살표 아이콘은 접근성 트리에서 제외하세요.
TalkBack에 불필요한 정보가 읽히지 않도록 장식용 이미지는 contentDescription을 null로 하고 접근성 제외가 좋습니다.

예시:

-    <ImageView
+    <ImageView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:src="@drawable/ic_arrow" />
+        android:src="@drawable/ic_arrow"
+        android:contentDescription="@null"
+        android:importantForAccessibility="no" />

각 항목의 화살표 ImageView에 동일 적용을 권장합니다.

Also applies to: 104-108, 141-145, 178-182, 215-219


232-246: 멀티라인 입력 EditText 스크롤/라인 제어가 없어 입력이 길어질 때 레이아웃이 불안정할 수 있습니다.
최소/최대 라인과 스크롤 속성을 지정해 주세요.

     <EditText
         android:id="@+id/etDetail"
         android:layout_width="0dp"
         android:layout_height="80dp"
         android:hint="추가적인 신고 사유를 작성해주세요."
         android:background="@drawable/background_input_text"
         android:textSize="14sp"
         android:fontFamily="@font/pretendard_regular"
         android:padding="10dp"
         android:gravity="top|start"
-        android:inputType="textMultiLine"
+        android:inputType="textMultiLine"
+        android:minLines="3"
+        android:maxLines="5"
+        android:scrollbars="vertical"
+        android:overScrollMode="ifContentScrolls"
         app:layout_constraintBottom_toTopOf="@id/btnSubmit"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent" />

14-14: 하드코딩된 문자열은 strings.xml로 이동하세요.
다국어/번역/일관된 카피 관리 관점에서 필요합니다.

예시:

  • tvTitle: "[닉네임]의 신고 사유" → @string/report_title
  • "스팸, 도배", "스포성 채팅", "욕설", "혐오 발언", "부적절한 닉네임 사용", 설명 텍스트들, "제출", etDetail 힌트 등 모두 strings.xml로 이전 권장.

Also applies to: 63-65, 76-79, 100-102, 113-116, 137-139, 150-153, 174-176, 187-190, 211-213, 224-227, 253-255, 237-237


45-80: 사유 항목 레이아웃이 반복되어 유지보수성이 떨어집니다. item_report_reason.xml을 재사용하거나 RecyclerView로 전환을 권장합니다.
동일 구조를 include/merge 또는 RecyclerView+Adapter로 구성하면 확장/수정이 쉬워집니다.

간단한 방향:

  • layoutReasons에 RecyclerView 배치
  • item_report_reason.xml을 ViewHolder로 사용
  • 데이터 모델(제목/설명/체크상태)로 리스트 구동

Also applies to: 82-117, 119-154, 156-191, 193-229

app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ChatRoomParticipantRVAdapter.kt (1)

107-121: DiffUtil 구현을 ID 비교로 보완하면 불필요한 전체 리바인딩을 줄일 수 있습니다.
현재 areItemsTheSame/areContentsTheSame 모두 동등성 비교로 동일합니다. ID 기반 비교가 성능/애니메이션에 유리합니다.

         override fun areItemsTheSame(
             oldItem: ParticipantData,
             newItem: ParticipantData
         ): Boolean {
-            return oldItem == newItem
+            return oldItem.userId == newItem.userId
         }

         override fun areContentsTheSame(
             oldItem: ParticipantData,
             newItem: ParticipantData
         ): Boolean {
             return oldItem == newItem
         }
app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ChatRoomParticipantsFragment.kt (2)

131-139: FragmentManager 호출에서 ‘!!’는 불필요/위험합니다.
Null 가능성을 제거하고 child/parentFragmentManager를 명확히 사용하세요.

-        dialog.show(activity?.supportFragmentManager!!, "ChatRoomParticipantsPopup")
+        dialog.show(parentFragmentManager, "ChatRoomParticipantsPopup")

또는 requireActivity().supportFragmentManager 사용.


43-59: onCreateView에 @RequiresApi(TIRAMISU)로 전체 수명주기 메서드를 API33에 묶는 것은 위험합니다. 하위 버전에서도 호출됩니다.
BundleCompat.getParcelable 또는 deprecate된 API를 분기하여 안전하게 처리하세요.

예시:

import androidx.core.os.BundleCompat

roomData = BundleCompat.getParcelable(arguments, "room_data", RoomData::class.java)

또는

@Suppress("DEPRECATION")
roomData = arguments?.getParcelable("room_data")

그리고 @RequiresApi는 제거하거나 실제 API33 전용 로직에만 한정하세요.

app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ReportDialogFragment.kt (3)

51-53: 다이얼로그 크기 설정은 onStart에서 수행하는 것이 더 안정적입니다.
onCreateDialog에서 setLayout을 호출하면 일부 기기에서 무시될 수 있습니다.

예시:

override fun onStart() {
    super.onStart()
    dialog?.window?.setLayout(320.dpToPx(resources), 494.dpToPx(resources))
}

아래 dpToPx 개선 코멘트와 함께 적용하세요.


63-65: dp → px 변환에 Resources.getSystem() 사용은 다중 창/locale-density 차이를 반영하지 못합니다. context resources를 사용하세요.

- private fun Int.dpToPx(): Int {
-     return (this * Resources.getSystem().displayMetrics.density).toInt()
- }
+ private fun Int.dpToPx(resources: Resources): Int {
+     return (this * resources.displayMetrics.density).toInt()
+ }

그리고 호출부:

- dialog.window?.setLayout(320.dpToPx(), 494.dpToPx())
+ dialog.window?.setLayout(320.dpToPx(resources), 494.dpToPx(resources))

또는 위 onStart 예시와 함께 적용하세요.

Also applies to: 51-53


31-43: 제출 유효성 검증 및 버튼 상태 제어가 없습니다.
이유 미선택/빈 입력도 제출 가능합니다. UX 관점에서 btnSubmit 활성/비활성 제어가 필요합니다.

  • 체크박스/etDetail TextWatcher를 통해 하나라도 선택/입력 시 enabled = true
  • 색상은 ColorStateList로 enabled/disabled를 구분
  • 서버 연동 시 제출 중 중복 클릭 방지를 위해 enable=false 처리
app/src/main/res/layout/item_report_reason.xml (5)

2-7: 리스트 아이템 터치 영역·리플·접근성 고려(선택) + paddingVertical 대안 제안

  • 전체 행을 탭해 체크 토글하는 UX를 원하신다면 부모 레이아웃에 minHeight(48dp), clickable/focusable, ripple(foreground)까지 주는 것을 권장합니다.
  • android:paddingVertical은 빌드 SDK에 따라 문제는 없겠지만, 명시적으로 paddingTop/Bottom을 사용하는 편이 읽기성과 호환성에 유리합니다.

의도하신 상호작용이 “체크박스만 클릭 가능”인지, “행 전체를 클릭하면 체크 토글”인지 확인 부탁드립니다. 후자라면 아래처럼 반영을 추천드립니다.

-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="horizontal"
-    android:gravity="center_vertical"
-    android:paddingVertical="8dp">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:gravity="center_vertical"
+    android:minHeight="48dp"
+    android:paddingTop="8dp"
+    android:paddingBottom="8dp"
+    android:clickable="true"
+    android:focusable="true"
+    android:foreground="?attr/selectableItemBackground">

9-15: MaterialCheckBox 사용 및 상태별 색상 자동 적용 권장

AppCompat CheckBox + 단일 buttonTint는 상태(checked/disabled 등)별 컬러 대응이 부족할 수 있습니다. Material3 컴포넌트를 사용하면 접근성·상태 컬러가 기본 제공됩니다.

아래처럼 교체를 제안드립니다.

-    <CheckBox
-        android:id="@+id/cbReason"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:buttonTint="@color/main"
-        android:focusable="false"
-        android:focusableInTouchMode="false" />
+    <com.google.android.material.checkbox.MaterialCheckBox
+        android:id="@+id/cbReason"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:focusable="false"
+        android:focusableInTouchMode="false"
+        style="@style/Widget.Material3.CompoundButton.CheckBox"
+        app:useMaterialThemeColors="true" />

루트에 app 네임스페이스 추가가 필요합니다.

-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"

24-31: 하드코딩 텍스트/컬러 제거, 다크모드 대응, 말줄임 처리

  • 문자열은 @string 리소스로 분리하여 i18n/재사용성을 확보하세요.
  • 고정색(@color/black) 대신 테마 속성(?attr/colorOnSurface 등)을 사용하면 다크모드에 자연스럽게 대응됩니다.
  • 제목은 한 줄 말줄임 처리 권장.

아래처럼 수정 제안드립니다.

-        <TextView
-            android:id="@+id/tvTitle"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="스팸, 도배"
-            android:textSize="14sp"
-            android:textColor="@color/black"
-            android:fontFamily="@font/pretendard_medium"/>
+        <TextView
+            android:id="@+id/tvTitle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/report_reason_spam"
+            android:textSize="14sp"
+            android:textColor="?attr/colorOnSurface"
+            android:maxLines="1"
+            android:ellipsize="end"
+            android:fontFamily="@font/pretendard_medium"/>

strings.xml 예시(별도 파일):

<string name="report_reason_spam">스팸, 도배</string>

원하시면 TextAppearance 스타일로 폰트/사이즈를 통합해 드릴 수 있습니다.


33-40: 설명 텍스트도 리소스화 + 다크모드/가독성 개선

  • 설명도 @string으로 이동 권장.
  • 색상은 테마 속성(?attr/colorOnSurfaceVariant 등)으로 교체.
  • 두세 줄까지 노출하고 넘치면 말줄임.

아래처럼 제안드립니다.

-        <TextView
-            android:id="@+id/tvDescription"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="반복적이거나 무의미한 메시지로 채팅 흐름을 방해하는 경우"
-            android:textSize="10sp"
-            android:textColor="@color/text4"
-            android:fontFamily="@font/pretendard_regular"/>
+        <TextView
+            android:id="@+id/tvDescription"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/report_reason_spam_desc"
+            android:textSize="10sp"
+            android:textColor="?attr/colorOnSurfaceVariant"
+            android:maxLines="2"
+            android:ellipsize="end"
+            android:fontFamily="@font/pretendard_regular"/>

strings.xml 예시(별도 파일):

<string name="report_reason_spam_desc">반복적이거나 무의미한 메시지로 채팅 흐름을 방해하는 경우</string>

가독성이 중요하면 textSize를 12sp로 상향하는 것도 고려해보세요.


2-15: 접근성(스크린리더) 관점 확인

체크박스를 focusable=false로 둔 상태에서 부모가 클릭/포커스 처리를 하지 않으면, 스크린리더가 텍스트와 체크박스를 따로 읽고 토글도 혼란스러울 수 있습니다. “행 전체 클릭으로 토글” UX라면 부모에 contentDescription을(동적으로) 세팅하거나, TalkBack 포커스가 부모로만 가도록 구성하는 것을 권장합니다.

원하시면 부모를 단일 접근성 노드로 취급하는 샘플(부모 clickable/focusable 설정 + 자식 importantForAccessibility 조정 + contentDescription 바인딩) 코드 템플릿을 제공하겠습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 902fda3 and 4b29c11.

📒 Files selected for processing (6)
  • app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ChatRoomParticipantRVAdapter.kt (1 hunks)
  • app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ChatRoomParticipantsFragment.kt (4 hunks)
  • app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ReportDialogFragment.kt (1 hunks)
  • app/src/main/res/layout/dialog_report.xml (1 hunks)
  • app/src/main/res/layout/fragment_report_dialog.xml (1 hunks)
  • app/src/main/res/layout/item_report_reason.xml (1 hunks)
🔇 Additional comments (2)
app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ChatRoomParticipantRVAdapter.kt (1)

11-11: 단순 import 추가는 문제 없습니다.
R 리소스 참조 대비용 import로 보이며 사이드 이펙트 없습니다.

app/src/main/res/layout/item_report_reason.xml (1)

17-22: 0dp + weight 배치 적절

텍스트 컨테이너를 0dp 너비 + layout_weight=1로 확장하는 구성은 적절합니다. paddingStart로 체크박스와의 간격도 명확합니다.

Comment on lines +77 to 84
// val text = data.nickname+"님을 신고하시겠습니까?"
// val textList = listOf(text,"예","아니오")
// showPopup(text =textList, left = {
// Toast.makeText(requireContext(),"신고 접수 되었습니다", Toast.LENGTH_SHORT).show()
// }, right = {} )

showReportPopup()
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

신고 클릭 시 AlertDialog로 레이아웃만 띄워 로직이 전혀 연결되지 않습니다. ReportDialogFragment를 사용해 데이터와 콜백을 연결하세요.
현재 showReportPopup()은 닉네임 타이틀/제출 액션/닫기 등이 동작하지 않습니다.

-                showReportPopup()
+                showReportDialog(data)

아래의 showReportDialog 구현 제안을 참고해 주세요.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ChatRoomParticipantsFragment.kt
around lines 77 to 84, the current showReportPopup() only displays a static
AlertDialog layout with no data or callbacks wired; replace this with
ReportDialogFragment usage: instantiate
ReportDialogFragment.newInstance(nickname or data.id as needed), set its submit
and close callbacks (e.g., fragment.setOnSubmit { reason ->
submitReport(memberId, reason) } and fragment.setOnClose { /* dismiss */ }),
show it via childFragmentManager, and remove the old showReportPopup call so the
dialog title, submit action and close behavior are fully connected to the
fragment logic and backend report handling.

Comment on lines 169 to 176
popupBinding.tvReport.setOnClickListener {
val text = data.nickname+"님을 신고하시겠습니까?"
val textList = listOf(text,"","아니오")
showPopup(text =textList, left = {
Toast.makeText(requireContext(),"신고 접수 되었습니다", Toast.LENGTH_SHORT).show()
}, right = {} )
// val text = data.nickname+"님을 신고하시겠습니까?"
// val textList = listOf(text,"예","아니오")
// showPopup(text =textList, left = {
// Toast.makeText(requireContext(),"신고 접수 되었습니다", Toast.LENGTH_SHORT).show()
// }, right = {} )
showReportPopup()
popupWindow.dismiss()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

팝업 메뉴의 신고도 동일하게 ReportDialogFragment로 연결 필요.
AlertDialog 단순 inflate는 기능 미구현 상태를 유발합니다.

-            showReportPopup()
+            showReportDialog(data)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
popupBinding.tvReport.setOnClickListener {
val text = data.nickname+"님을 신고하시겠습니까?"
val textList = listOf(text,"","아니오")
showPopup(text =textList, left = {
Toast.makeText(requireContext(),"신고 접수 되었습니다", Toast.LENGTH_SHORT).show()
}, right = {} )
// val text = data.nickname+"님을 신고하시겠습니까?"
// val textList = listOf(text,"예","아니오")
// showPopup(text =textList, left = {
// Toast.makeText(requireContext(),"신고 접수 되었습니다", Toast.LENGTH_SHORT).show()
// }, right = {} )
showReportPopup()
popupWindow.dismiss()
popupBinding.tvReport.setOnClickListener {
showReportDialog(data)
popupWindow.dismiss()
}

Comment on lines +197 to +208

//방장쪽에도 함수 있다함.
private fun showReportPopup(){
val dialogView = LayoutInflater.from(requireContext())
.inflate(R.layout.dialog_report, null)

val dialog = android.app.AlertDialog.Builder(requireContext())
.setView(dialogView)
.create()

dialog.show()
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

AlertDialog로의 단순 inflate(showReportPopup)는 제거하고 ReportDialogFragment를 사용하세요.
참가자 정보 전달, 제출 콜백 처리, UI 바인딩을 일관되게 처리할 수 있습니다.

아래처럼 교체를 제안드립니다. (현재 ReportDialogFragment의 생성자 패턴을 그대로 사용한 최소 변경안)

-    //방장쪽에도 함수 있다함.
-    private fun showReportPopup(){
-        val dialogView = LayoutInflater.from(requireContext())
-            .inflate(R.layout.dialog_report, null)
-
-        val dialog = android.app.AlertDialog.Builder(requireContext())
-            .setView(dialogView)
-            .create()
-
-        dialog.show()
-    }
+    private fun showReportDialog(target: ParticipantData) {
+        ReportDialogFragment(
+            participant = target,
+            onSubmit = { reasons, extra ->
+                // TODO: 서버 신고 API 연동 (예: viewModel.reportUser)
+                Toast.makeText(
+                    requireContext(),
+                    "${target.nickname}님 신고 접수(${reasons.joinToString()})",
+                    Toast.LENGTH_SHORT
+                ).show()
+            }
+        ).show(parentFragmentManager, "ReportDialog")
+    }

참고: ReportDialogFragment의 생성자 주입은 프로세스 재시작 시 크래시 위험이 있어, newInstance(arguments) 방식으로의 리팩터도 아래 코멘트에서 제안드립니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
//방장쪽에도 함수 있다함.
private fun showReportPopup(){
val dialogView = LayoutInflater.from(requireContext())
.inflate(R.layout.dialog_report, null)
val dialog = android.app.AlertDialog.Builder(requireContext())
.setView(dialogView)
.create()
dialog.show()
}
private fun showReportDialog(target: ParticipantData) {
ReportDialogFragment(
participant = target,
onSubmit = { reasons, extra ->
// TODO: 서버 신고 API 연동 (예: viewModel.reportUser)
Toast.makeText(
requireContext(),
"${target.nickname}님 신고 접수(${reasons.joinToString()})",
Toast.LENGTH_SHORT
).show()
}
).show(parentFragmentManager, "ReportDialog")
}
🤖 Prompt for AI Agents
In
app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ChatRoomParticipantsFragment.kt
around lines 197 to 208, replace the manual AlertDialog inflate showReportPopup
implementation with instantiation and presentation of ReportDialogFragment:
create the fragment using its current constructor pattern, pass the selected
participant info and a submit callback (or listener) so the fragment can handle
data binding and submission, and show it via
parentFragmentManager.beginTransaction()/show(parentFragmentManager, TAG) or
fragment.show(parentFragmentManager, TAG). Also update the callback wiring so
the fragment returns submission results to this fragment. Finally, mark a TODO
to refactor ReportDialogFragment to a newInstance(arguments) factory method for
safe argument passing on process restart.

Comment on lines +10 to +13
class ReportDialogFragment(
private val participant: ParticipantData,
private val onSubmit: (reasons: List<String>, extraReason: String) -> Unit
) : DialogFragment() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fragment에 생성자로 인자/콜백을 주입하면 프로세스 재시작 시 복원에 실패해 크래시 납니다. newInstance(ARG) + setter/FragmentResult로 전환하세요.
안정성을 위해 표준 패턴으로 리팩터가 필요합니다.

아래와 같이 최소 변경으로 전환을 제안드립니다.

-class ReportDialogFragment(
-    private val participant: ParticipantData,
-    private val onSubmit: (reasons: List<String>, extraReason: String) -> Unit
-) : DialogFragment() {
+class ReportDialogFragment : DialogFragment() {
 
-    private var _binding: DialogReportBinding? = null
+    private var _binding: DialogReportBinding? = null
     private val binding get() = _binding!!
+    private lateinit var participant: ParticipantData
+    private var onSubmit: ((reasons: List<String>, extraReason: String) -> Unit)? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        participant = requireArguments().getParcelable(ARG_PARTICIPANT)!!
+    }
 
     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
         // layoutInflater 사용
         _binding = DialogReportBinding.inflate(layoutInflater)
@@
-            onSubmit(reasons, extraReason)
+            onSubmit?.invoke(reasons, extraReason)
             dismiss()
         }
@@
-        return dialog
+        return dialog
     }
@@
 }
 
-private fun Int.dpToPx(): Int {
-    return (this * Resources.getSystem().displayMetrics.density).toInt()
-}
+companion object {
+    private const val ARG_PARTICIPANT = "arg_participant"
+    fun newInstance(participant: ParticipantData) = ReportDialogFragment().apply {
+        arguments = Bundle().apply { putParcelable(ARG_PARTICIPANT, participant) }
+    }
+}
+
+fun setOnSubmitListener(listener: (List<String>, String) -> Unit) {
+    this.onSubmit = listener
+}

이후 호출부에서는:

ReportDialogFragment.newInstance(target).apply {
    setOnSubmitListener { reasons, extra -> /* ... */ }
}.show(parentFragmentManager, "ReportDialog")

Also applies to: 15-17, 41-43

🤖 Prompt for AI Agents
In
app/src/main/java/umc/onairmate/ui/chat_room/drawer/participants/ReportDialogFragment.kt
around lines 10-13 (and also for lines 15-17, 41-43), the fragment currently
takes ParticipantData and an onSubmit callback via its primary constructor which
breaks fragment state restoration; change to the standard pattern: remove
constructor parameters, add a companion object newInstance(participant:
ParticipantData) that packages the participant (or its
id/serializable/parcelable fields) into a Bundle and sets it as arguments,
restore the participant from arguments in onCreate/onCreateView, and replace the
constructor callback with either a nullable setOnSubmitListener(reasons,
extra)->Unit setter or the FragmentResult API (provide setOnSubmitListener
method or sendResult in submit path). Update all call sites to use
ReportDialogFragment.newInstance(...).apply { setOnSubmitListener { ... } }.
Ensure fields are nullable and accessed after arguments restore to avoid
crashes.

Comment on lines +21 to +29
<!-- 닫기 버튼 -->
<ImageView
android:id="@+id/btnClose"
android:layout_width="10dp"
android:layout_height="10dp"
android:src="@drawable/btn_close"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

닫기 버튼 터치 타깃(10dp)이 너무 작고 접근성 속성이 없습니다. 최소 48dp 터치 영역과 contentDescription을 추가하세요.
터치 타깃 부족은 실사용에서 누르기 어렵고, TalkBack 사용자를 배려하지 못합니다.

아래처럼 개선을 권장합니다.

     <ImageView
         android:id="@+id/btnClose"
-        android:layout_width="10dp"
-        android:layout_height="10dp"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:minWidth="48dp"
+        android:minHeight="48dp"
+        android:padding="12dp"
+        android:contentDescription="@string/a11y_close"
+        android:clickable="true"
+        android:focusable="true"
+        android:background="?attr/selectableItemBackgroundBorderless"
         android:src="@drawable/btn_close"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         android:layout_marginTop="10dp"/>

추가로 strings.xml에 다음 키를 정의해 주세요.

<string name="a11y_close">닫기</string>

Comment on lines +248 to +260
<!-- 제출 버튼 -->
<Button
android:id="@+id/btnSubmit"
android:layout_width="100dp"
android:layout_height="20dp"
android:text="제출"
android:textSize="12sp"
android:fontFamily="@font/pretendard_semi_bold"
android:backgroundTint="@color/disable"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

제출 버튼 높이 20dp는 터치 타깃 가이드(48dp)를 크게 하회합니다. 또한 배경색이 ‘disable’로 되어 있어 활성 상태로 보이지 않습니다.
터치성/가독성/일관된 머티리얼 스타일을 위해 수정 필요합니다.

     <Button
         android:id="@+id/btnSubmit"
         android:layout_width="100dp"
-        android:layout_height="20dp"
+        android:layout_height="wrap_content"
+        android:minHeight="48dp"
         android:text="제출"
         android:textSize="12sp"
         android:fontFamily="@font/pretendard_semi_bold"
-        android:backgroundTint="@color/disable"
+        android:backgroundTint="?attr/colorPrimary"
         android:textColor="@android:color/white"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent" />

추가로 ReportDialogFragment에서 체크박스 선택/추가 입력 유무에 따라 btnSubmit enabled 상태 및 색상(StateList)을 제어하면 UX가 좋아집니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<!-- 제출 버튼 -->
<Button
android:id="@+id/btnSubmit"
android:layout_width="100dp"
android:layout_height="20dp"
android:text="제출"
android:textSize="12sp"
android:fontFamily="@font/pretendard_semi_bold"
android:backgroundTint="@color/disable"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<!-- 제출 버튼 -->
<Button
android:id="@+id/btnSubmit"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:text="제출"
android:textSize="12sp"
android:fontFamily="@font/pretendard_semi_bold"
android:backgroundTint="?attr/colorPrimary"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
🤖 Prompt for AI Agents
In app/src/main/res/layout/dialog_report.xml around lines 248 to 260, the Submit
button uses android:layout_height="20dp" (below 48dp touch target) and a
backgroundTint="@color/disable" making it appear inactive; update the button to
have a minimum touch-friendly height (e.g., set layout_height to at least 48dp
or use minHeight/vertical padding to meet 48dp) and change the default tint to
an active color; replace hard-coded disabled color with a ColorStateList
selector resource and reference that selector via backgroundTint so the button
visually reflects enabled/disabled states. Additionally, in ReportDialogFragment
implement logic to enable/disable btnSubmit and switch its state (enabled and
selected) based on checkbox selection and additional input presence, wiring the
StateList selector to the button so color updates automatically.

Comment on lines +1 to +262
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="320dp"
android:layout_height="494dp"
android:padding="20dp">

<!-- 타이틀 -->
<TextView
android:id="@+id/tvTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="[닉네임]의 신고 사유"
android:textAppearance="@style/TextAppearance.App.SemiBold.16sp"
android:gravity="center"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<!-- 닫기 버튼 -->
<ImageView
android:id="@+id/btnClose"
android:layout_width="10dp"
android:layout_height="10dp"
android:src="@drawable/btn_close"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="10dp"/>

<!-- 신고 사유 리스트 -->
<LinearLayout
android:id="@+id/layoutReasons"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
android:showDividers="middle"
app:layout_constraintTop_toBottomOf="@id/tvTitle"
app:layout_constraintBottom_toTopOf="@id/etDetail"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp">

<!-- 하나의 항목 예시 (스팸, 도배) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="6dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">

<CheckBox
android:id="@+id/cbSpam"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="스팸, 도배"
android:textSize="14sp"
android:fontFamily="@font/pretendard_medium"/>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow" />
</LinearLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="반복적이거나 무의미한 메시지로 채팅 흐름을 방해하는 경우"
android:textSize="10sp"
android:textColor="@color/text4"
android:fontFamily="@font/pretendard_regular"/>
</LinearLayout>

<!-- 스포성 채팅 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="6dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">

<CheckBox
android:id="@+id/cbSpoiler"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="스포성 채팅"
android:textSize="14sp"
android:fontFamily="@font/pretendard_medium"/>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow" />
</LinearLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="콘텐츠의 즐거리, 결말 등을 미리 언급해 시청 경험을 방해하는 경우"
android:textSize="10sp"
android:textColor="@color/text4"
android:fontFamily="@font/pretendard_regular"/>
</LinearLayout>

<!-- 욕설 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="6dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">

<CheckBox
android:id="@+id/cbAbuse"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="욕설"
android:textSize="14sp"
android:fontFamily="@font/pretendard_medium"/>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow" />
</LinearLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="상대방을 향한 비속어 또는 공격적인 언어를 사용하는 경우"
android:textSize="10sp"
android:textColor="@color/text4"
android:fontFamily="@font/pretendard_regular"/>
</LinearLayout>

<!-- 혐오 발언 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="6dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">

<CheckBox
android:id="@+id/cbHate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="혐오 발언"
android:textSize="14sp"
android:fontFamily="@font/pretendard_medium"/>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow" />
</LinearLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="성별, 인종, 외모 등 특정 대상에 대한 차별적 발언을 하는 경우"
android:textSize="10sp"
android:textColor="@color/text4"
android:fontFamily="@font/pretendard_regular"/>
</LinearLayout>

<!-- 부적절한 닉네임 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingVertical="6dp">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">

<CheckBox
android:id="@+id/cbNickname"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="부적절한 닉네임 사용"
android:textSize="14sp"
android:fontFamily="@font/pretendard_medium"/>

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_arrow" />
</LinearLayout>

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="불쾌감을 줄 수 있는 닉네임이나 선정적/모욕적인 표현을 사용하는 경우"
android:textSize="10sp"
android:textColor="@color/text4"
android:fontFamily="@font/pretendard_regular"/>
</LinearLayout>

</LinearLayout>

<!-- 추가 사유 입력 -->
<EditText
android:id="@+id/etDetail"
android:layout_width="0dp"
android:layout_height="80dp"
android:hint="추가적인 신고 사유를 작성해주세요."
android:background="@drawable/background_input_text"
android:textSize="14sp"
android:fontFamily="@font/pretendard_regular"
android:padding="10dp"
android:gravity="top|start"
android:inputType="textMultiLine"
app:layout_constraintBottom_toTopOf="@id/btnSubmit"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

<!-- 제출 버튼 -->
<Button
android:id="@+id/btnSubmit"
android:layout_width="100dp"
android:layout_height="20dp"
android:text="제출"
android:textSize="12sp"
android:fontFamily="@font/pretendard_semi_bold"
android:backgroundTint="@color/disable"
android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout> No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

dialog_report.xml과 사실상 동일한 중복 리소스입니다. 하나만 유지하세요.
현재 코드에서는 DialogReportBinding(dialog_report.xml)만 사용됩니다. fragment_report_dialog.xml은 미사용 가능성이 높습니다.

다음 스크립트로 사용 여부를 확인하고, 미사용이면 제거를 권장합니다. item_report_reason.xml 사용 여부도 함께 점검합니다.

또한 접근성/터치 타깃/문자열 리소스화 등은 dialog_report.xml에서 제안한 개선을 동일하게 적용하세요.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Searching references to fragment_report_dialog.xml and item_report_reason.xml..."
rg -n -C2 'fragment_report_dialog' || true
rg -n -C2 'R\.layout\.fragment_report_dialog' || true
rg -n -C2 'item_report_reason' || true
rg -n -C2 'R\.layout\.item_report_reason' || true

Length of output: 376


사용되지 않는 레이아웃 리소스 제거 권장

rg 검색 결과 fragment_report_dialog.xmlitem_report_reason.xml 모두 코드 내 참조가 없습니다. 따라서 다음을 수행해주세요:

  • app/src/main/res/layout/fragment_report_dialog.xml 삭제
  • app/src/main/res/layout/item_report_reason.xml 삭제

추가로, 기존에 사용 중인 dialog_report.xml에 대해서도

  • 접근성 개선
  • 터치 타깃 크기 보장
  • 모든 문자열 리소스화

등 이전 리뷰에서 제안된 내용을 동일하게 적용해 주세요.

🤖 Prompt for AI Agents
app/src/main/res/layout/fragment_report_dialog.xml (lines 1-262): This layout
file (and app/src/main/res/layout/item_report_reason.xml) are not referenced
anywhere in the codebase — delete both unused layout resources to remove dead
assets; additionally open the actively used
app/src/main/res/layout/dialog_report.xml and apply the previous review
suggestions: move all hardcoded strings into strings.xml, increase interactive
controls to meet touch-target minimums, and adjust semantics/labels
(contentDescription, focus order, contrast) to improve accessibility.

@jiyoung02
Copy link
Contributor

수고하셨습니다! 팝업창 뜨는것은 잘 되는데, 중간 체크리스트 부분이 뷰에서 사라진 것 같습니다...! 한번 확인 부탁드려요

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 BugFix 오류 해결 🔨 Refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants