Skip to content

Refactor/#56 choo qa#58

Open
starshape7 wants to merge 4 commits into
developfrom
refactor/#56-chooQA
Open

Refactor/#56 choo qa#58
starshape7 wants to merge 4 commits into
developfrom
refactor/#56-chooQA

Conversation

@starshape7
Copy link
Copy Markdown
Collaborator

@starshape7 starshape7 commented Jun 3, 2026

Related issue 🛠

Work Description 📝

  • 작업 내용

Screenshot 📸

Uncompleted Tasks 😅

  • Task1

PR Point 📌

트러블 슈팅 💥

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 앱 로고 클릭 시 홈 화면으로 이동 기능 추가
    • 모집 중인 스터디 항목 클릭 시 상세 페이지 이동 기능 추가
  • UI 개선

    • 보고 모달의 입력 영역 아래 여백 조정
    • 홈 화면 섹션 간 간격 개선
    • 카테고리 선택 드롭다운 메뉴 디자인 개선 및 항목 간 구분선 추가
  • 개선사항

    • 회원탈퇴 확인 다이얼로그 처리 로직 개선
    • 네비게이션 콜백 파라미터 최적화

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

Walkthrough

PR는 앱의 로고 네비게이션 기능, 스터디 리스트 아이템 클릭 콜백 구조 개선, 드롭다운 컴포넌트 마이그레이션, 그리고 레이아웃 간격 조정 등을 포함합니다.

Changes

App Bar Logo Navigation

Layer / File(s) Summary
Logo click callback in AppBarHome
core/designsystem/src/main/java/com/umcspot/spot/designsystem/component/appBar/AppBar.kt
AppBarHomeonLogoClick: () -> Unit 파라미터 추가되고, 로고 이미지에 clickable modifier로 클릭 이벤트 연결; 프리뷰 컴포저블 두 개 업데이트.
MainScreen logo click navigation
feature/main/src/main/java/com/umcspot/spot/main/MainScreen.kt
AppBarHomeonLogoClick을 Home 라우트로의 네비게이션으로 구현하며, popUpTo<Home> { inclusive = true }로 백스택 초기화; 네비게이션 import 추가.

Study Item Click Navigation Refactoring

Layer / File(s) Summary
RecruitingStudyScreen callback signature change
feature/study/src/main/java/com/umcspot/spot/study/recruiting/RecruitingStudyScreen.kt
onItemClick 콜백 타입을 (StudyResult) -> Unit에서 (Long) -> Unit으로 변경; 내부 컴포저블과 아이템 클릭 바인딩도 item.id 전달로 업데이트.
Navigation graph callback updates
feature/study/src/main/java/com/umcspot/spot/study/recruiting/navigation/RecruitingStudyNavigation.kt, feature/main/src/main/java/com/umcspot/spot/main/MainNavHost.kt, feature/mypage/src/main/java/com/umcspot/spot/mypage/navigation/MyPageNavigation.kt
RecruitingStudyNavigation의 콜백 시그니처를 Long ID 기반으로 업데이트; MainNavHostrecruitingStudyGraph에서 아이템 클릭을 navigateToStudyDetail로 연결; MyPageNavigationnavigateToMakeStudy 파라미터 추가 및 전달.

UI Polish & Dialog Refinements

Layer / File(s) Summary
PostingScreen dropdown component migration
feature/board/src/main/java/com/umcspot/spot/feature/board/post/posting/PostingScreen.kt
ExposedDropdownMenu에서 DropdownMenu로 마이그레이션; import 업데이트 및 @OptIn 어노테이션 제거; Box로 감싼 후 clickable로 토글 로직 구현; 드롭다운 항목 사이에 HorizontalDivider 조건부 추가.
Layout spacing and membership cancellation flow
core/designsystem/src/main/java/com/umcspot/spot/designsystem/component/modal/ReportModal.kt, feature/home/src/main/java/com/umcspot/spot/home/HomeScreen.kt, feature/mypage/src/main/java/com/umcspot/spot/mypage/cancelMemberShip/CancelMemberShipScreen.kt, feature/main/src/main/java/com/umcspot/spot/main/MainNavHost.kt
ReportModal의 Spacer 높이 16dp → 20dp 조정; HomeScreen에 24dp Spacer 추가; CancelMemberShipScreen의 탈퇴 다이얼로그 흐름을 showDialog 닫음 + viewModel.leaveSpot() 호출 + leaveStatus 관찰로 변경.

Possibly Related PRs

  • SPOTeam/Android-V2#27: ReportModal.kt의 Spacer 높이 조정이 동일 컴포넌트에서의 이전 레이아웃 작업과 관련.
  • SPOTeam/Android-V2#32: 스터디 리스트 아이템 클릭 콜백 시그니처가 Long ID 기반으로 변경되어, 상세 화면 네비게이션 로직과 일관성 있게 연결.

Poem

🐰 로고를 탭하면 집으로 돌아가고,
스터디는 ID로 더 가볍게 날아가고,
드롭다운은 새 옷을 입고,
간격들은 숨을 고르고—
더 깔끔한 앱이 완성되었네! ✨

🎯 3 (Moderate) | ⏱️ ~20분

🚥 Pre-merge checks | ✅ 1 | ❌ 4

❌ Failed checks (3 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Title check ⚠️ Warning PR 제목 'Refactor/#56 choo qa'는 변경 사항과 부분적으로 관련되어 있으나, 실제 변경의 핵심을 명확히 설명하지 못하고 있습니다. PR 제목을 더 구체적으로 작성하세요. 예: 'Fix QA issues: AppBar logo click, dropdown refactor, spacing adjustments' 같이 주요 변경 사항을 명확히 설명하는 제목으로 수정해주시기 바랍니다.
Description check ⚠️ Warning PR 설명이 템플릿 구조를 따르고 있으나, 대부분의 섹션이 비어있거나 플레이스홀더만 포함되어 있습니다. 각 섹션을 구체적으로 작성하세요. Work Description에 변경 사항을 상세히 기술하고, PR Point에서 주요 포인트를, Screenshot에 실제 이미지를, Uncompleted Tasks를 완성하거나 제거해주시기 바랍니다.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive 연결된 이슈 #56은 구체적인 요구사항이나 수락 기준이 없어 코드 변경이 이슈 요구사항을 충족하는지 검증할 수 없습니다. 이슈 #56의 설명에 구체적인 QA 반영 항목, 예상 동작, 검증 기준을 추가하여 PR 코드 변경이 실제로 이슈를 해결하는지 명확히 해주시기 바랍니다.
✅ Passed checks (1 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed 모든 코드 변경이 AppBar, Modal, Dropdown, Navigation 등 UI 개선 및 버그 수정에 관련되어 있어 범위를 벗어난 변경이 없습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/#56-chooQA

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

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

Caution

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

⚠️ Outside diff range comments (2)
feature/board/src/main/java/com/umcspot/spot/feature/board/post/posting/PostingScreen.kt (1)

312-338: ⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoff

접근성 시맨틱 정보 추가 필요.

ExposedDropdownMenuBox에서 수동 Box + clickable 구현으로 마이그레이션하면서 내장된 접근성 기능이 제거되었습니다. 현재 구현에는 스크린 리더 사용자를 위한 적절한 역할(role) 및 상태(state) 정보가 없습니다.

clickable modifier에 Modifier.semantics를 추가하여 드롭다운 역할과 확장 상태를 명시해야 합니다.

♿ 접근성 개선 제안
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.stateDescription
                 Row(
                     verticalAlignment = Alignment.CenterVertically,
                     modifier = Modifier
                         .width(screenWidthDp(85.dp))
                         .border(1.dp, SpotTheme.colors.G200, SpotShapes.Hard)
                         .clip(SpotShapes.Hard)
+                        .semantics {
+                            contentDescription = "게시판 선택: ${selected.korean}"
+                            stateDescription = if (expanded) "펼쳐짐" else "접힘"
+                            role = Role.DropdownList
+                        }
                         .clickable { expanded = !expanded }
                         .padding(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/board/src/main/java/com/umcspot/spot/feature/board/post/posting/PostingScreen.kt`
around lines 312 - 338, The custom dropdown Box lost accessibility semantics
when replacing ExposedDropdownMenuBox; update the Modifier chain on the Row (the
one using .clickable { expanded = !expanded }) to include semantics that declare
the control role and expanded state (e.g., add Modifier.semantics { role =
Role.Button; this[SemanticsProperties.Expanded] = expanded } or equivalent
Compose semantics API) so screen readers can announce it; ensure the semantics
modifier references the existing expanded boolean and resides before or combined
with the clickable modifier on the Row inside PostingScreen (the Box/Row using
selected and expanded).
feature/mypage/src/main/java/com/umcspot/spot/mypage/cancelMemberShip/CancelMemberShipScreen.kt (1)

50-57: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

일회성 이벤트를 StateFlow로 처리하는 방식 수정 필요

CancelMemberShipViewModelleaveStatusMutableStateFlow에 그대로 저장되며(초기값 ""), 성공 후 _leaveStatus.value = status만 하고 idle/소비 후 리셋 로직이 없습니다. 이 상태를 CancelMemberShipScreen에서 LaunchedEffect(status)로 다이얼로그를 띄우면 다음 문제가 생깁니다.

  • 실패(MEMBER4006) 후 재시도: 같은 결과 상태가 연속으로 동일 값이면, MutableStateFlow가 값이 동일한 업데이트를 방출하지 않아 status key가 바뀌지 않고 LaunchedEffect가 재실행되지 않아 다이얼로그가 다시 안 뜰 수 있습니다.
  • 화면 회전 등 구성 변경: showFailDialog/showSuccessDialogremember라 초기화되지만 leaveStatus는 ViewModel에 보존되어, 재구성 시 현재 statusLaunchedEffect가 다시 실행되어 이미 처리한 다이얼로그가 다시 노출될 수 있습니다.

leaveStatusone-shot 이벤트(Channel/SharedFlow) 로 바꾸거나, 다이얼로그 표시 직후 소비 후 idle 값("" 등)으로 명시적으로 리셋하는 방식으로 개선하는 게 필요합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/mypage/src/main/java/com/umcspot/spot/mypage/cancelMemberShip/CancelMemberShipScreen.kt`
around lines 50 - 57, The current one-shot event handling using
CancelMemberShipViewModel.leaveStatus (MutableStateFlow) causes missed or
repeated dialog emissions; change leaveStatus to a one-time event (e.g.,
MutableSharedFlow or Channel) in CancelMemberShipViewModel and emit status as an
event, then collect it in CancelMemberShipScreen using a coroutine
(LaunchedEffect or collectAsStateWithLifecycle for SharedFlow) to set
showFailDialog/showSuccessDialog; alternatively, if you prefer to keep
StateFlow, explicitly reset _leaveStatus to an idle value ("" or null)
immediately after the screen handles the status inside the
LaunchedEffect(status) handler so repeated identical emissions and configuration
changes don’t incorrectly suppress or re-show dialogs.
🧹 Nitpick comments (2)
feature/board/src/main/java/com/umcspot/spot/feature/board/post/posting/PostingScreen.kt (1)

332-337: 💤 Low value

드롭다운 상태에 따른 화살표 아이콘 변경 고려.

현재 화살표 아이콘이 expanded 상태와 관계없이 항상 arrow_up으로 고정되어 있습니다. 일반적인 드롭다운 UX 패턴에서는 닫힌 상태에서는 아래 화살표, 열린 상태에서는 위 화살표를 표시하거나 회전 애니메이션을 적용합니다.

시각적 피드백 개선을 위해 expanded 상태에 따라 아이콘을 조건부로 변경하는 것을 고려해보세요.

🎨 아이콘 상태 반영 제안
                     Image(
-                        painter = painterResource(R.drawable.arrow_up),
+                        painter = painterResource(
+                            if (expanded) R.drawable.arrow_up else R.drawable.arrow_down
+                        ),
                         contentDescription = "게시판 선택",
                         colorFilter = ColorFilter.tint(SpotTheme.colors.B500),
                         modifier = Modifier.size(screenWidthDp(14.dp))
                     )

또는 회전 애니메이션 사용:

+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.ui.draw.rotate
+
+    val rotation by animateFloatAsState(
+        targetValue = if (expanded) 180f else 0f,
+        label = "arrow rotation"
+    )
+
                     Image(
                         painter = painterResource(R.drawable.arrow_down),
                         contentDescription = "게시판 선택",
                         colorFilter = ColorFilter.tint(SpotTheme.colors.B500),
-                        modifier = Modifier.size(screenWidthDp(14.dp))
+                        modifier = Modifier
+                            .size(screenWidthDp(14.dp))
+                            .rotate(rotation)
                     )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/board/src/main/java/com/umcspot/spot/feature/board/post/posting/PostingScreen.kt`
around lines 332 - 337, The arrow Image in PostingScreen.kt is always using
R.drawable.arrow_up regardless of the dropdown state; update the UI to reflect
the `expanded` state by either (A) selecting the drawable conditionally (use
R.drawable.arrow_down when expanded == false and R.drawable.arrow_up when
expanded == true) in the Image painterResource call, or (B) apply a rotation
animation using animateFloatAsState and Modifier.graphicsLayer/Modifier.rotate
on the same Image so it visually points down when closed and up when opened;
locate the Image block that renders the arrow and change the painter/Modifier to
depend on the `expanded` boolean.
feature/study/src/main/java/com/umcspot/spot/study/recruiting/RecruitingStudyScreen.kt (1)

238-261: ⚡ Quick win

studies.indexOf(item)itemsIndexed로 대체하세요.

items 루프 안에서 매 아이템마다 studies.indexOf(item)을 호출하면 항목 수에 대해 O(n²) 비용이 발생합니다. loadNextPage로 리스트가 계속 커지는 페이징 화면이라 항목이 많아질수록 비용이 누적되며, equals 기반 조회라 동일 값 항목에서 잘못된 인덱스를 반환할 여지도 있습니다. itemsIndexed로 인덱스를 직접 받으면 더 안전하고 효율적입니다.

♻️ 제안 수정
-        items(
-            items = studies,
-            key = { it.id }
-        ) { item ->
+        itemsIndexed(
+            items = studies,
+            key = { _, item -> item.id }
+        ) { index, item ->
             Spacer(Modifier.padding(screenHeightDp(5.dp)))

             StudyListItem(
                 item = item,
                 modifier = Modifier
                     .fillMaxWidth(),
                 onClick = { onItemClick(item.id) }
             )

-            if(studies.indexOf(item) != studies.lastIndex) {
+            if (index != studies.lastIndex) {
                 Spacer(Modifier.padding(screenHeightDp(5.dp)))

                 HorizontalDivider(
                     modifier = Modifier
                         .fillMaxWidth(),
                     color = SpotTheme.colors.G300,
                     thickness = 1.dp
                 )
             }
         }

itemsIndexed import 추가가 필요합니다:

+import androidx.compose.foundation.lazy.itemsIndexed
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@feature/study/src/main/java/com/umcspot/spot/study/recruiting/RecruitingStudyScreen.kt`
around lines 238 - 261, Replace the current items(...) usage that calls
studies.indexOf(item) with the itemsIndexed(...) variant so you receive the item
index directly (avoid O(n²) and equals-based lookup); inside the lambda use the
provided index to compare against studies.lastIndex to decide when to render the
trailing Spacer and HorizontalDivider; update the call site around StudyListItem
(keeping onItemClick(item.id) and modifiers unchanged) and add the itemsIndexed
import so the composable compiles.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@feature/main/src/main/java/com/umcspot/spot/main/MainScreen.kt`:
- Line 130: The onSearchClick callback is currently a no-op (onSearchClick = {
}) so the search icon does nothing; update the MainScreen usage by implementing
the search handler: either wire it to the existing navigation action (call the
NavController navigate method or the existing navigateToSearch function if
present) or, if search is intentionally deferred, replace the empty lambda with
a clear TODO stub that logs or emits an event (e.g., onSearchRequested) so the
behavior is traceable and testable; locate the onSearchClick parameter in
MainScreen composable invocation to make the change.

---

Outside diff comments:
In
`@feature/board/src/main/java/com/umcspot/spot/feature/board/post/posting/PostingScreen.kt`:
- Around line 312-338: The custom dropdown Box lost accessibility semantics when
replacing ExposedDropdownMenuBox; update the Modifier chain on the Row (the one
using .clickable { expanded = !expanded }) to include semantics that declare the
control role and expanded state (e.g., add Modifier.semantics { role =
Role.Button; this[SemanticsProperties.Expanded] = expanded } or equivalent
Compose semantics API) so screen readers can announce it; ensure the semantics
modifier references the existing expanded boolean and resides before or combined
with the clickable modifier on the Row inside PostingScreen (the Box/Row using
selected and expanded).

In
`@feature/mypage/src/main/java/com/umcspot/spot/mypage/cancelMemberShip/CancelMemberShipScreen.kt`:
- Around line 50-57: The current one-shot event handling using
CancelMemberShipViewModel.leaveStatus (MutableStateFlow) causes missed or
repeated dialog emissions; change leaveStatus to a one-time event (e.g.,
MutableSharedFlow or Channel) in CancelMemberShipViewModel and emit status as an
event, then collect it in CancelMemberShipScreen using a coroutine
(LaunchedEffect or collectAsStateWithLifecycle for SharedFlow) to set
showFailDialog/showSuccessDialog; alternatively, if you prefer to keep
StateFlow, explicitly reset _leaveStatus to an idle value ("" or null)
immediately after the screen handles the status inside the
LaunchedEffect(status) handler so repeated identical emissions and configuration
changes don’t incorrectly suppress or re-show dialogs.

---

Nitpick comments:
In
`@feature/board/src/main/java/com/umcspot/spot/feature/board/post/posting/PostingScreen.kt`:
- Around line 332-337: The arrow Image in PostingScreen.kt is always using
R.drawable.arrow_up regardless of the dropdown state; update the UI to reflect
the `expanded` state by either (A) selecting the drawable conditionally (use
R.drawable.arrow_down when expanded == false and R.drawable.arrow_up when
expanded == true) in the Image painterResource call, or (B) apply a rotation
animation using animateFloatAsState and Modifier.graphicsLayer/Modifier.rotate
on the same Image so it visually points down when closed and up when opened;
locate the Image block that renders the arrow and change the painter/Modifier to
depend on the `expanded` boolean.

In
`@feature/study/src/main/java/com/umcspot/spot/study/recruiting/RecruitingStudyScreen.kt`:
- Around line 238-261: Replace the current items(...) usage that calls
studies.indexOf(item) with the itemsIndexed(...) variant so you receive the item
index directly (avoid O(n²) and equals-based lookup); inside the lambda use the
provided index to compare against studies.lastIndex to decide when to render the
trailing Spacer and HorizontalDivider; update the call site around StudyListItem
(keeping onItemClick(item.id) and modifiers unchanged) and add the itemsIndexed
import so the composable compiles.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f40bdd68-d252-4eb8-9de9-ce6bb22e9788

📥 Commits

Reviewing files that changed from the base of the PR and between 4d7c5dd and 9dfdf17.

📒 Files selected for processing (10)
  • core/designsystem/src/main/java/com/umcspot/spot/designsystem/component/appBar/AppBar.kt
  • core/designsystem/src/main/java/com/umcspot/spot/designsystem/component/modal/ReportModal.kt
  • feature/board/src/main/java/com/umcspot/spot/feature/board/post/posting/PostingScreen.kt
  • feature/home/src/main/java/com/umcspot/spot/home/HomeScreen.kt
  • feature/main/src/main/java/com/umcspot/spot/main/MainNavHost.kt
  • feature/main/src/main/java/com/umcspot/spot/main/MainScreen.kt
  • feature/mypage/src/main/java/com/umcspot/spot/mypage/cancelMemberShip/CancelMemberShipScreen.kt
  • feature/mypage/src/main/java/com/umcspot/spot/mypage/navigation/MyPageNavigation.kt
  • feature/study/src/main/java/com/umcspot/spot/study/recruiting/RecruitingStudyScreen.kt
  • feature/study/src/main/java/com/umcspot/spot/study/recruiting/navigation/RecruitingStudyNavigation.kt

AppBarHome(
hasAlert = hasUnreadAlert,
onSearchClick = { /* TODO */ },
onSearchClick = { },
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

검색 버튼이 동작하지 않는 빈 콜백입니다.

onSearchClick = { }로 인해 검색 아이콘을 눌러도 아무 동작이 없습니다. 의도된 상태(미구현 보류)인지, 아니면 검색 화면으로의 네비게이션 연결이 누락된 것인지 확인해 주세요.

검색 네비게이션 연결이 필요하다면 핸들러 구현을 도와드리거나 추적용 이슈를 열어드릴까요?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@feature/main/src/main/java/com/umcspot/spot/main/MainScreen.kt` at line 130,
The onSearchClick callback is currently a no-op (onSearchClick = { }) so the
search icon does nothing; update the MainScreen usage by implementing the search
handler: either wire it to the existing navigation action (call the
NavController navigate method or the existing navigateToSearch function if
present) or, if search is intentionally deferred, replace the empty lambda with
a clear TODO stub that logs or emits an event (e.g., onSearchRequested) so the
behavior is traceable and testable; locate the onSearchClick parameter in
MainScreen composable invocation to make the change.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Chore] Choo QA

1 participant