feat: 온보딩-온보딩 UI 구현 - #41
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthrough온보딩 1~6단계 화면과 입력·선택 컴포넌트를 추가하고, 단계별 네비게이션 키와 상태 저장, 앱 진입 및 완료 후 홈 이동을 연결했다. 날짜·온도·키워드·선호 시간 선택과 통화 확인 팝업도 포함한다. Changes온보딩 계약과 기반 UI
재사용 온보딩 컴포넌트
온보딩 화면
상태와 네비게이션
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: Sequence Diagram(s)sequenceDiagram
participant AppScreen
participant OnboardingEntryBuilder
participant OnboardingScreens
participant OnboardingViewModel
participant Home
AppScreen->>OnboardingEntryBuilder: 단계별 엔트리와 콜백 등록
AppScreen->>OnboardingScreens: Onboarding1NavKey로 시작
OnboardingScreens->>OnboardingViewModel: 입력 상태 갱신
OnboardingScreens->>AppScreen: 다음 단계 콜백 전달
AppScreen->>OnboardingScreens: 다음 단계 NavKey로 이동
OnboardingScreens->>AppScreen: 지금 전화 또는 나중 전화 이벤트 전달
AppScreen->>Home: HomeNavKey로 replaceAll
🚥 Pre-merge checks | ✅ 5 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
Gemini AI 코드리뷰안녕하세요! 시니어 Android 개발자로서 GitHub Pull Request 리뷰를 시작하겠습니다. 전반적으로 온보딩 플로우를 위한 컴포저블들을 잘 분리하고 각 기능을 구현한 것으로 보입니다. 몇 가지 개선 사항과 피드백을 드릴게요. General Feedback
File-specific Feedback
|
There was a problem hiding this comment.
Actionable comments posted: 16
🧹 Nitpick comments (10)
feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding3Screen.kt (1)
38-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
SpeechStyle/Relationshipenum을 Screen 파일 밖으로 분리 고려.두 enum이
Onboarding3Screen.kt(UI 파일)에 정의되어 있고OnboardingEntryBuilder,AppScreen에서 직접 import됩니다.Trait,PreferTime처럼 component/model 파일로 옮기면 UI 파일과 도메인성 타입 간 결합이 줄어듭니다.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding3Screen.kt` around lines 38 - 48, Onboarding3Screen의 SpeechStyle와 Relationship enum을 UI 파일 밖의 component/model 영역으로 이동하고, OnboardingEntryBuilder와 AppScreen을 포함한 모든 사용처의 import를 새 위치로 갱신하세요. Trait와 PreferTime이 배치된 기존 모델 구조와 명명 규칙을 따르며 enum 정의와 동작은 그대로 유지하세요.feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt (1)
204-251: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win이름 편집 오버레이 로직이 두 화면에 거의 동일하게 중복되어 있습니다.
EditingNameField/Onboarding2EditingNameFieldenum 정의부터 배경 dismiss,MessageInputField연동까지 동일한 패턴이 두 파일에 복사되어 있어, 향후 한쪽만 수정되면(예: 이번 리뷰의 focus/keyboard hide 누락처럼) 동작이 갈릴 위험이 있습니다.
feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt#L204-L251: enum·상태·오버레이 UI를 재사용 가능한 공용 컴포넌트(예:NameEditOverlay(editingField, nameInput, onValueChange, onSend, onDismiss, placeholder))로 추출.feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding2Screen.kt#L215-L254: 동일 공용 컴포넌트를 사용하도록 교체.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt` around lines 204 - 251, Extract the duplicated EditingNameField/Onboarding2EditingNameField definitions and name-edit overlay behavior into one reusable NameEditOverlay component, including background dismissal, MessageInputField integration, placeholder handling, and callbacks. Update feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt lines 204-251 to use the shared component, and update feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding2Screen.kt lines 215-254 likewise; preserve each screen’s existing state updates through the component callbacks.feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt (2)
34-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winModifier 파라미터가 다른 옵셔널 파라미터 뒤에 위치합니다. 두 화면 모두
modifier: Modifier = Modifier가 필수 파라미터 바로 뒤가 아니라initialSelectedKeywords/initialPreferTime같은 다른 옵셔널 파라미터보다 뒤에, 즉 파라미터 목록의 맨 마지막에 위치합니다.
feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt#L34-L39:modifier를onNextClick바로 뒤,initialSelectedKeywords앞으로 이동.feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.kt#L29-L34:modifier를onNextClick바로 뒤,initialPreferTime앞으로 이동.As per path instructions for
**/*Screen.kt, "Modifier 파라미터 위치(파라미터 앞쪽) 및 기본값 없이 전달 여부."🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt` around lines 34 - 39, Reorder the parameters in Onboarding4Screen (feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt, lines 34-39) so modifier: Modifier = Modifier immediately follows onNextClick and precedes initialSelectedKeywords. Apply the same ordering in Onboarding5Screen (feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.kt, lines 29-34), placing modifier before initialPreferTime.Source: Path instructions
46-116: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win두 화면이 거의 동일한 스캐폴드 구조를 반복합니다.
BackStepBar→TopTitle→SubGray2배경의 스크롤 가능한 콘텐츠 컬럼(navigationBarsPadding 포함) → 하단 고정SecondaryButton으로 이어지는 구조가 두 파일에서 그대로 복제되어 있어 공통 스캐폴드 컴포저블로 추출할 여지가 있습니다.
feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt#L46-L116: 이 레이아웃 골격을 공통OnboardingStepScaffold(topTitle, bottomButton, content)형태로 추출하는 후보로 사용.feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.kt#L38-L97: 동일한 공통 스캐폴드를 재사용하도록 리팩터링.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt` around lines 46 - 116, Onboarding4Screen.kt lines 46-116와 Onboarding5Screen.kt lines 38-97의 중복 레이아웃을 공통 OnboardingStepScaffold(topTitle, bottomButton, content) 컴포저블로 추출하세요. BackStepBar, TopTitle, SubGray2 콘텐츠 영역의 navigationBarsPadding, 하단 고정 SecondaryButton 구조를 스캐폴드가 담당하게 하고, 각 화면은 고유 콘텐츠와 버튼 동작만 content 및 인자로 전달하도록 두 파일을 리팩터링하세요.feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding6Screen.kt (1)
90-117: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winOnboarding6Screen의 custom
trackPressState를 제거하세요.
PrimaryButton이미collectIsPressedAsState()로 내부 press 상태를 토글하고 이미지 버튼의 state도 토글 중이라contentColor조건은 쓸모없습니다.PrimaryButton은interactionSource로 접근 가능한 public API가 아니라 현재 구조에서 커스텀 modifier를 붙일 필요가 없습니다.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding6Screen.kt` around lines 90 - 117, Onboarding6Screen의 두 PrimaryButton에서 custom trackPressState 사용과 isCallNowPressed/isCallLaterPressed 기반 contentColor 조건을 제거하세요. 각 버튼의 contentColor는 기존 비활성 색상(첫 번째는 White, 두 번째는 Gray600)으로 고정하고, PrimaryButton의 내부 press 상태 처리와 pressedContainerColor 동작은 그대로 유지하세요.feature/onboarding/api/src/main/java/kr/co/call/api/OnboardingRoute.kt (1)
10-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win빈 객체 본문을 제거하세요.
Onboarding2NavKey만 불필요한 본문을 가져 detektEmptyClassBlock경고를 발생시킵니다. 다른 단계 키와 동일하게 본문 없는 선언으로 정리하세요.수정 예시
-data object Onboarding2NavKey: NavKey { -} +data object Onboarding2NavKey : NavKey🤖 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/onboarding/api/src/main/java/kr/co/call/api/OnboardingRoute.kt` around lines 10 - 11, Remove the empty body from the Onboarding2NavKey declaration and make it a bodyless object declaration, matching the style of the other onboarding navigation keys.Source: Linters/SAST tools
feature/onboarding/impl/src/main/java/kr/co/call/impl/component/RelatonshipChoiceCard.kt (1)
1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value파일명 오타:
RelatonshipChoiceCard.kt→RelationshipChoiceCard.kt.파일명이 실제 컴포저블 이름(
RelationshipChoiceCard, L39)과 철자가 다릅니다(“i” 누락). Kotlin 관례상 최상위 선언명과 파일명을 일치시키는 것이 탐색/일관성 측면에서 좋습니다.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/component/RelatonshipChoiceCard.kt` at line 1, Rename the file containing the RelationshipChoiceCard composable from RelatonshipChoiceCard.kt to RelationshipChoiceCard.kt so the filename matches the top-level declaration and corrects the missing “i”.feature/onboarding/impl/src/main/java/kr/co/call/impl/component/KeywordChoice.kt (1)
31-63: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
keyword필드가 enum 이름과 항상 동일해 중복됩니다.각 항목의
keyword값이 자기 자신의 enum 상수명과 완전히 같습니다(HUMOROUS("HUMOROUS", ...)). 이후 리팩터링 시 한쪽만 수정하면fromKeyword매핑이 조용히 깨질 수 있습니다.Trait.name을 직접 사용하도록 단순화하는 것을 권장합니다.♻️ 제안 리팩터링
enum class Trait( - val keyword: String, val emoji: String, val label: String, ){ - HUMOROUS("HUMOROUS", "😃", "유머러스한"), - PLAYFUL("PLAYFUL", "🤡", "장난기 많은"), + HUMOROUS("😃", "유머러스한"), + PLAYFUL("🤡", "장난기 많은"), ... companion object { fun fromKeyword(key: String): Trait? { - return entries.find { it.keyword == key } + return entries.find { it.name == key } } } }🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/component/KeywordChoice.kt` around lines 31 - 63, Remove the redundant keyword constructor property and its duplicated string arguments from Trait, and update fromKeyword to compare each entry’s name directly with the supplied key. Preserve the existing enum names, emojis, labels, and nullable lookup behavior.feature/onboarding/impl/src/main/java/kr/co/call/impl/component/TopTitle.kt (2)
32-39: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
modifier파라미터를 필수 파라미터 뒤로 옮겨주세요.
title,description같은 필수 파라미터가 현재modifier뒤에 있죠. Compose 컴포지블 파라미터 기준에서는modifier는 필수 파라미터 뒤의 첫 번째 선택적 인수여야 합니다.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/component/TopTitle.kt` around lines 32 - 39, TopTitle의 파라미터 순서를 수정해 필수 파라미터인 title과 description을 먼저 배치하고, 첫 번째 선택적 파라미터로 modifier를 배치하세요. currentStep, totalStep, horizontalPadding의 기존 순서와 기본값은 유지하세요.
1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueCompose 컴포저블의
modifier를 필수 파라미터 뒤로 배치하세요. Compose 가이드라인에서modifier는 필수 파라미터 이후 첫 번째 선택적 파라미터여야 합니다.
TopTitle.kt:title/description을 먼저 두고modifier를 그 뒤에 배치하세요.MemberChoice.kt:label,selected,placeholder,options,onOptionSelected를 먼저 두고modifier를 그 뒤에 배치하세요.TempControl.kt:onTemperatureChange를 먼저 두고modifier를 그 뒤에 배치하세요.ProfileChoice.kt:imageUrl,onClick을 먼저 두고modifier를 그 이후에 배치하세요.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/component/TopTitle.kt` at line 1, Reorder the parameters of the Compose functions in TopTitle.kt, MemberChoice.kt, TempControl.kt, and ProfileChoice.kt so all required parameters come first and modifier is the first optional parameter afterward: title/description, label/selected/placeholder/options/onOptionSelected, onTemperatureChange, and imageUrl/onClick respectively. Preserve the existing parameter types, defaults, and behavior.
🤖 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 `@app/src/main/java/kr/co/call/callfromai/AppScreen.kt`:
- Around line 59-60: Update the comment above the rememberNavBackStack call to
accurately state that navigation currently starts at Onboarding1NavKey, while
retaining the note that login-based branching will be implemented later.
- Around line 118-157: Update the onboardingEntry callbacks in AppScreen so
every value received by onOnboarding1Next, onOnboarding2Next, onOnboarding3Next,
onOnboarding4Next, and onOnboarding5Next is retained and propagated through the
existing state or domain/data persistence pipeline; do not discard the
birthday/job/MBTI, speech style/temperature, keyword, preference-time, or other
onboarding fields while navigating. If no persistence path exists yet,
explicitly document the intentional data discard at these callbacks.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/component/MemberChoice.kt`:
- Around line 48-56: Reorder the MemberChoice function parameters so the
required label, selectedOption, placeholder, options, and onOptionSelected
parameters come first, followed by modifier, then the remaining optional
required parameter.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/component/ProfileChoice.kt`:
- Around line 29-34: Update the ProfileChoice function signature so the required
imageUrl and onClick parameters come first, followed by modifier with a default
of Modifier, then the existing size default. Preserve the function behavior and
update any affected call sites to use the revised parameter order.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/component/TempControl.kt`:
- Around line 55-58: TempControl의 파라미터 순서를 변경해 필수 파라미터인 onTemperatureChange를
modifier보다 앞에 배치하세요. modifier의 기본값과 나머지 동작은 그대로 유지해 Compose 권장 순서와 컴파일 가능성을
보장합니다.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt`:
- Line 57: Rename the profileImageURl parameter to profileImageUrl in the
Onboarding1Screen declaration and update all references within that file,
including the usages around lines 115 and 268, while preserving the existing
behavior.
- Around line 46-58: Onboarding1Screen 변경에 대한 PR 설명에 해당 화면(사진 선택/나를 소개하기)의 스크린샷
또는 화면 녹화를 추가했는지 확인하고, 누락되었다면 Onboarding2/4/6 캡처와 함께 첨부한다.
- Around line 204-236: Update the name-edit overlay dismissal paths in
Onboarding1Screen so both the background clickable handler and
MessageInputField.onSendClick clear focus through focusManager and hide the
keyboard through keyboardController before resetting the editing state. Match
the existing handling used by Onboarding2Screen while preserving the current
name update behavior.
- Around line 65-67: Update the birthday state declaration in Onboarding1Screen
to use rememberSaveable instead of remember, persisting LocalDate through a
Bundle-compatible representation such as an ISO-8601 string or dayOfYear and
restoring it to LocalDate. Preserve 2000-01-01 as the initial default while
retaining the user-selected birthday across recomposition and state restoration.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding3Screen.kt`:
- Around line 50-59: Onboarding3Screen의 말투·관계 선택 화면이 PR 설명에 포함되도록 해당 화면의 스크린샷 또는
화면 녹화를 추가하세요. 기존 Onboarding2/4/6 캡처와 별도로 Onboarding3Screen이 명확히 식별되어야 합니다.
- Around line 193-198: Replace the non-null assertions in the onNextClick
invocation with nested or combined let calls on selectedSpeech and
selectedRelationship, invoking onNextClick only when both values are available.
Preserve the existing temperature argument and canMoveNext behavior while
removing the runtime-unsafe !! operators.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.kt`:
- Around line 1-114: Update the PR description to include a screenshot or screen
recording of the Onboarding5Screen preference-time selection UI, alongside the
existing onboarding screen evidence; no code changes are required.
- Around line 35-37: Initialize selectedPreferTime in Onboarding5Screen’s
rememberSaveable state from the initialPreferTime parameter instead of always
using null. Preserve saved state restoration while ensuring the supplied initial
value, such as PreferTime.DAY in the preview, renders as selected when no saved
value exists.
- Around line 86-94: Update the SecondaryButton in the onboarding screen to pass
enabled = selectedPreferTime != null, keeping the existing onClick behavior so
the “다음” button is disabled until a preferred time is selected.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding6Screen.kt`:
- Around line 159-174: Update the TwoButtonPopup invocation in the
showCallDialog block so onDismissRequest sets showCallDialog to false, allowing
back-button and outside-tap dismissal while preserving the existing positive and
negative click behavior.
- Line 61: Rename the Boolean state variable showCallDialog in the onboarding
screen to an is-prefixed name such as isCallDialogVisible, and update every
usage accordingly, including its initialization, conditional checks, and
assignments in the dialog click handlers.
---
Nitpick comments:
In `@feature/onboarding/api/src/main/java/kr/co/call/api/OnboardingRoute.kt`:
- Around line 10-11: Remove the empty body from the Onboarding2NavKey
declaration and make it a bodyless object declaration, matching the style of the
other onboarding navigation keys.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/component/KeywordChoice.kt`:
- Around line 31-63: Remove the redundant keyword constructor property and its
duplicated string arguments from Trait, and update fromKeyword to compare each
entry’s name directly with the supplied key. Preserve the existing enum names,
emojis, labels, and nullable lookup behavior.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/component/RelatonshipChoiceCard.kt`:
- Line 1: Rename the file containing the RelationshipChoiceCard composable from
RelatonshipChoiceCard.kt to RelationshipChoiceCard.kt so the filename matches
the top-level declaration and corrects the missing “i”.
In `@feature/onboarding/impl/src/main/java/kr/co/call/impl/component/TopTitle.kt`:
- Around line 32-39: TopTitle의 파라미터 순서를 수정해 필수 파라미터인 title과 description을 먼저
배치하고, 첫 번째 선택적 파라미터로 modifier를 배치하세요. currentStep, totalStep, horizontalPadding의
기존 순서와 기본값은 유지하세요.
- Line 1: Reorder the parameters of the Compose functions in TopTitle.kt,
MemberChoice.kt, TempControl.kt, and ProfileChoice.kt so all required parameters
come first and modifier is the first optional parameter afterward:
title/description, label/selected/placeholder/options/onOptionSelected,
onTemperatureChange, and imageUrl/onClick respectively. Preserve the existing
parameter types, defaults, and behavior.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt`:
- Around line 204-251: Extract the duplicated
EditingNameField/Onboarding2EditingNameField definitions and name-edit overlay
behavior into one reusable NameEditOverlay component, including background
dismissal, MessageInputField integration, placeholder handling, and callbacks.
Update
feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt
lines 204-251 to use the shared component, and update
feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding2Screen.kt
lines 215-254 likewise; preserve each screen’s existing state updates through
the component callbacks.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding3Screen.kt`:
- Around line 38-48: Onboarding3Screen의 SpeechStyle와 Relationship enum을 UI 파일 밖의
component/model 영역으로 이동하고, OnboardingEntryBuilder와 AppScreen을 포함한 모든 사용처의
import를 새 위치로 갱신하세요. Trait와 PreferTime이 배치된 기존 모델 구조와 명명 규칙을 따르며 enum 정의와 동작은
그대로 유지하세요.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt`:
- Around line 34-39: Reorder the parameters in Onboarding4Screen
(feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt,
lines 34-39) so modifier: Modifier = Modifier immediately follows onNextClick
and precedes initialSelectedKeywords. Apply the same ordering in
Onboarding5Screen
(feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.kt,
lines 29-34), placing modifier before initialPreferTime.
- Around line 46-116: Onboarding4Screen.kt lines 46-116와 Onboarding5Screen.kt
lines 38-97의 중복 레이아웃을 공통 OnboardingStepScaffold(topTitle, bottomButton, content)
컴포저블로 추출하세요. BackStepBar, TopTitle, SubGray2 콘텐츠 영역의 navigationBarsPadding, 하단
고정 SecondaryButton 구조를 스캐폴드가 담당하게 하고, 각 화면은 고유 콘텐츠와 버튼 동작만 content 및 인자로 전달하도록 두
파일을 리팩터링하세요.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding6Screen.kt`:
- Around line 90-117: Onboarding6Screen의 두 PrimaryButton에서 custom
trackPressState 사용과 isCallNowPressed/isCallLaterPressed 기반 contentColor 조건을
제거하세요. 각 버튼의 contentColor는 기존 비활성 색상(첫 번째는 White, 두 번째는 Gray600)으로 고정하고,
PrimaryButton의 내부 press 상태 처리와 pressedContainerColor 동작은 그대로 유지하세요.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: b8fb2d5e-9010-4ffc-834d-1ebe16c0f9cc
⛔ Files ignored due to path filters (7)
feature/onboarding/impl/src/main/res/drawable/ic_down.pngis excluded by!**/*.pngfeature/onboarding/impl/src/main/res/drawable/ic_up.pngis excluded by!**/*.pngfeature/onboarding/impl/src/main/res/drawable/onboarding_check.pngis excluded by!**/*.pngfeature/onboarding/impl/src/main/res/drawable/relationship_first.pngis excluded by!**/*.pngfeature/onboarding/impl/src/main/res/drawable/relationship_old.pngis excluded by!**/*.pngfeature/onboarding/impl/src/main/res/drawable/relationship_some.pngis excluded by!**/*.pngfeature/onboarding/impl/src/main/res/drawable/spendbutton.pngis excluded by!**/*.png
📒 Files selected for processing (33)
app/src/main/java/kr/co/call/callfromai/AppScreen.ktcore/designsystem/src/main/java/kr/co/call/designsystem/theme/Color.ktcore/designsystem/src/main/java/kr/co/call/designsystem/theme/Type.ktfeature/onboarding/api/src/main/java/kr/co/call/api/OnboardingRoute.ktfeature/onboarding/impl/build.gradle.ktsfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/AgeInputField.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/BackStepBar.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/BirthdayChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/BottomWheel.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/KeywordChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/MemberChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/MessageInputField.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/NameBox.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/PreferTime.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/ProfileChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/RelatonshipChoiceCard.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/SpeechChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/TempControl.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/TopTitle.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/entry/OnboardingEntryBuilder.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding2Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding3Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding6Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/OnboardingScreen.ktfeature/onboarding/impl/src/main/res/drawable/ic_back.xmlfeature/onboarding/impl/src/main/res/drawable/ic_calendar.xmlfeature/onboarding/impl/src/main/res/drawable/ic_left.xmlfeature/onboarding/impl/src/main/res/drawable/ic_right.xmlfeature/onboarding/impl/src/main/res/drawable/onboarding_profile.xmlfeature/onboarding/impl/src/main/res/drawable/onboarding_profile2.xml
💤 Files with no reviewable changes (1)
- feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/OnboardingScreen.kt
| // TODO: 로그인 구현 후 로그인 여부에 따른 분기처리 필요. 일단은 시작점을 홈 화면으로 설정 | ||
| val backStack = rememberNavBackStack(HomeNavKey) | ||
| val backStack = rememberNavBackStack(Onboarding1NavKey) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
주석과 코드가 불일치합니다.
주석은 "시작점을 홈 화면으로 설정"이라고 되어 있지만, 실제로는 Onboarding1NavKey로 시작하도록 변경되었습니다. 주석을 갱신해 주세요.
🤖 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 `@app/src/main/java/kr/co/call/callfromai/AppScreen.kt` around lines 59 - 60,
Update the comment above the rememberNavBackStack call to accurately state that
navigation currently starts at Onboarding1NavKey, while retaining the note that
login-based branching will be implemented later.
| fun MemberChoice( | ||
| modifier: Modifier=Modifier, | ||
| label: String, | ||
| selectedOption: String, //드롭다운이 보여줄 값 | ||
| placeholder: String, | ||
| options:List<String>, //선택 가능한 목록 | ||
| onOptionSelected: (String)->Unit,//선택됐을 때 실행할 동작 | ||
| required: Boolean=false, | ||
| ){ |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and inspect the target file around the function signature.
if [ -f feature/onboarding/impl/src/main/java/kr/co/call/impl/component/MemberChoice.kt ]; then
sed -n '1,90p' feature/onboarding/impl/src/main/java/kr/co/call/impl/component/MemberChoice.kt
else
echo "Target file not found"
fi
# Search for relevant Compose guideline/docs references in repo if any local copy exists.
rg -n "Modifier must be|modifier parameter|first optional|optional parameter" . \
--glob '!build/**' \
--glob '!**/build/**' \
| head -100 || trueRepository: call-from-ai/CallFromAi_Android
Length of output: 3327
🌐 Web query:
Jetpack Compose developer guidelines modifier parameter order first optional parameter after required parameters
💡 Result:
According to the official Jetpack Compose API guidelines, the modifier parameter must be the first optional parameter in a composable function's parameter list [1][2][3]. The required parameter order for a composable function is as follows [1][2]: 1. Required parameters (parameters without default values) [1][2]. 2. Single modifier: Modifier = Modifier parameter [1][2][4]. 3. Optional parameters (parameters with default values) [1][2]. 4. (Optional) Trailing @Composable lambda (typically named content) [1][2]. This convention is enforced to ensure consistency across the API surface, allowing developers to predictably pass a modifier to any composable as the first optional argument without needing to use named parameters [4][5]. The modifier parameter must be named exactly modifier, have a default value of Modifier, and be applied to the root-most layout element within the composable implementation [1][6][7][3]. This guideline is also enforced by automated lint checks in Android Studio [8].
Citations:
- 1: https://android.googlesource.com/platform/frameworks/support/+/androidx-main/compose/docs/compose-component-api-guidelines.md
- 2: https://github.com/androidx/androidx/blob/androidx-main/compose/docs/compose-component-api-guidelines.md
- 3: https://developer.android.com/reference/kotlin/androidx/compose/ui/Modifier
- 4: https://android.googlesource.com/platform/frameworks/support/+/androidx-main/compose/docs/compose-api-guidelines.md
- 5: https://github.com/androidx/androidx/blob/androidx-main/compose/docs/compose-api-guidelines.md
- 6: https://github.com/chrisbanes/skills/blob/main/skills/compose-modifier-and-layout-style/SKILL.md
- 7: https://developer.android.com/develop/ui/compose/modifiers
- 8: https://googlesamples.github.io/android-custom-lint-rules/checks/ModifierParameter.md.html
Modifier 파라미터 위치를 필수 파라미터 뒤로 옮기세요.
Compose API 가이드에 따라 modifier는 필수 파라미터 후, 다른 선택적 파라미터 전에 있어야 합니다. 현재 MemberChoice의 label, selectedOption, placeholder, options, onOptionSelected 뒤에 위치하도록 정리하세요.
🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/component/MemberChoice.kt`
around lines 48 - 56, Reorder the MemberChoice function parameters so the
required label, selectedOption, placeholder, options, and onOptionSelected
parameters come first, followed by modifier, then the remaining optional
required parameter.
| package kr.co.call.impl.screen | ||
|
|
||
| import androidx.compose.foundation.background | ||
| import androidx.compose.foundation.layout.Arrangement | ||
| import androidx.compose.foundation.layout.Column | ||
| import androidx.compose.foundation.layout.Spacer | ||
| import androidx.compose.foundation.layout.fillMaxSize | ||
| import androidx.compose.foundation.layout.fillMaxWidth | ||
| import androidx.compose.foundation.layout.height | ||
| import androidx.compose.foundation.layout.navigationBarsPadding | ||
| import androidx.compose.foundation.layout.padding | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.mutableStateOf | ||
| import androidx.compose.runtime.saveable.rememberSaveable | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.unit.dp | ||
| import kr.co.call.designsystem.component.button.SecondaryButton | ||
| import kr.co.call.designsystem.theme.SubGray2 | ||
| import kr.co.call.designsystem.theme.White | ||
| import kr.co.call.impl.component.BackStepBar | ||
| import kr.co.call.impl.component.PreferTime | ||
| import kr.co.call.impl.component.TopTitle | ||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.runtime.setValue | ||
| import androidx.compose.ui.tooling.preview.Preview | ||
| import kr.co.call.designsystem.theme.CallFromAiTheme | ||
|
|
||
| @Composable | ||
| fun Onboarding5Screen( | ||
| onBackClick: () -> Unit, | ||
| onNextClick: (PreferTime) -> Unit, | ||
| initialPreferTime: PreferTime? = null, | ||
| modifier: Modifier = Modifier, | ||
| ){ | ||
| var selectedPreferTime by rememberSaveable { | ||
| mutableStateOf<PreferTime?>(null) | ||
| } | ||
| Column( | ||
| modifier = modifier | ||
| .fillMaxSize() | ||
| .padding( | ||
| top = 54.dp, | ||
| bottom = 18.dp, | ||
| ) | ||
| .background(White), | ||
| ) { | ||
| BackStepBar(onBackClick = onBackClick) | ||
|
|
||
| TopTitle( | ||
| title = "언제 먼저 통화를\n걸어드리면 좋을까요?", | ||
| description = "편하게 통화하기 좋은 시간대를 선택해주세요.", | ||
| currentStep = 4, | ||
| totalStep = 4, | ||
| horizontalPadding = 27.dp, | ||
| ) | ||
|
|
||
| Spacer(modifier = Modifier.height(5.dp)) | ||
|
|
||
| Column( | ||
| modifier = Modifier | ||
| .weight(1f) | ||
| .fillMaxWidth() | ||
| .background(SubGray2) | ||
| .navigationBarsPadding(), | ||
| ) { | ||
| Column( | ||
| modifier = Modifier.padding( | ||
| start = 27.dp, | ||
| end = 27.dp, | ||
| top = 26.dp, | ||
| ), | ||
| verticalArrangement = Arrangement.spacedBy(22.dp), | ||
| ) { | ||
| PreferTime.entries | ||
| .forEach { preferTime -> | ||
| PreferTime( | ||
| preferTime = preferTime, | ||
| selected = selectedPreferTime == preferTime, | ||
| onClick = { selectedPreferTime = preferTime }, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| Spacer(modifier = Modifier.weight(1f)) | ||
|
|
||
| SecondaryButton( | ||
| modifier = Modifier.padding( | ||
| start = 27.dp, | ||
| end = 27.dp, | ||
| bottom = 18.dp, | ||
| ), | ||
| text = "다음", | ||
| onClick = { selectedPreferTime?.let(onNextClick) }, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Preview( | ||
| name = "Onboarding 5", | ||
| showBackground = true, | ||
| widthDp = 393, | ||
| heightDp = 852, | ||
| ) | ||
| @Composable | ||
| private fun Onboarding5ScreenPreview() { | ||
| CallFromAiTheme { | ||
| Onboarding5Screen( | ||
| onBackClick = {}, | ||
| onNextClick = {}, | ||
| initialPreferTime = PreferTime.DAY, | ||
| ) | ||
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
변경된 Screen.kt 파일에 대한 스크린샷 누락 가능성.
PR 설명에는 온보딩 2단계(Image 1), 4단계(Image 2), 6단계(Image 3) 화면 이미지만 첨부되어 있고, 이 파일이 구현하는 5단계(선호 시간 선택) 화면에 대한 스크린샷/화면 녹화는 보이지 않습니다.
As per coding guidelines, "Jetpack Compose 화면 파일(예: *Screen.kt...)이 변경된 경우, PR 설명에 스크린샷 또는 화면 녹화가 첨부되었는지 확인하고 없으면 경고한다."
🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.kt`
around lines 1 - 114, Update the PR description to include a screenshot or
screen recording of the Onboarding5Screen preference-time selection UI,
alongside the existing onboarding screen evidence; no code changes are required.
Source: Coding guidelines
| if (showCallDialog){ | ||
| TwoButtonPopup( | ||
| label="통화 연결", | ||
| title="${firstName}에게 바로\n통화를 연결할까요?", | ||
| positiveText = "연결", | ||
| negativeText = "취소", | ||
| onPositiveClick = { | ||
| showCallDialog=false | ||
| onCallNowClick() | ||
| }, | ||
| onNegativeClick = { | ||
| showCallDialog=false | ||
| }, | ||
| onDismissRequest = {}, | ||
| ) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
팝업이 뒤로가기/바깥 탭으로 닫히지 않습니다.
onDismissRequest = {}로 비워져 있어 시스템 뒤로가기나 다이얼로그 바깥을 탭해도 닫히지 않고, "취소" 버튼을 눌러야만 닫힙니다. 의도적인 강제 선택이 아니라면 onDismissRequest = { showCallDialog = false }로 맞추는 것이 일반적인 다이얼로그 UX에 부합합니다.
🛠️ 제안하는 수정
onNegativeClick = {
showCallDialog=false
},
- onDismissRequest = {},
+ onDismissRequest = { showCallDialog = false },
)📝 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.
| if (showCallDialog){ | |
| TwoButtonPopup( | |
| label="통화 연결", | |
| title="${firstName}에게 바로\n통화를 연결할까요?", | |
| positiveText = "연결", | |
| negativeText = "취소", | |
| onPositiveClick = { | |
| showCallDialog=false | |
| onCallNowClick() | |
| }, | |
| onNegativeClick = { | |
| showCallDialog=false | |
| }, | |
| onDismissRequest = {}, | |
| ) | |
| } | |
| if (showCallDialog){ | |
| TwoButtonPopup( | |
| label="통화 연결", | |
| title="${firstName}에게 바로\n통화를 연결할까요?", | |
| positiveText = "연결", | |
| negativeText = "취소", | |
| onPositiveClick = { | |
| showCallDialog=false | |
| onCallNowClick() | |
| }, | |
| onNegativeClick = { | |
| showCallDialog=false | |
| }, | |
| onDismissRequest = { showCallDialog = false }, | |
| ) | |
| } |
🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding6Screen.kt`
around lines 159 - 174, Update the TwoButtonPopup invocation in the
showCallDialog block so onDismissRequest sets showCallDialog to false, allowing
back-button and outside-tap dismissal while preserving the existing positive and
negative click behavior.
Gemini AI 코드리뷰안녕하세요! PR을 잘 만드셨네요. 시니어 개발자로서 PR diff를 꼼꼼히 리뷰해 드리겠습니다. 전반적으로 새로운 온보딩 플로우를 잘 구현하신 것 같고, Compose 컴포넌트들을 재사용성 높게 잘 분리하신 점이 인상 깊습니다. 몇 가지 개선 사항과 주의 깊게 봐야 할 부분을 짚어드리겠습니다. 🔍 PR Diff 코드 리뷰1. Kotlin & General
2. Jetpack Compose
3. Repository/DataSource (Diff에 없음)
4. ViewModel (
5. FCM/SSE/실시간 통신 (Diff에 없음)
총평새로운 온보딩 플로우를 위한 컴포넌트들이 매우 체계적이고 재사용 가능하게 잘 구현되었습니다. 가장 중요한 개선 사항은 또한, 사용자에게 보여지는 텍스트는 전반적으로 훌륭한 작업이며, 지적된 사항들을 개선하면 더욱 견고하고 유지보수하기 쉬운 코드가 될 것입니다. 수고 많으셨습니다! |
There was a problem hiding this comment.
Actionable comments posted: 2
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/kr/co/call/callfromai/AppScreen.kt (1)
151-153: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win완료 후 온보딩 백스택을 정리하세요.
appNavigator.navigate(HomeNavKey)는 단순 push라서 홈에서 뒤로가기를 하면 온보딩 6 단계 및 이전 온보딩 단계가 다시 노출됩니다. 완료 시homeEntry의navigateToHome처럼appNavigator.replaceAll(HomeNavKey)를 사용하거나, 온보딩 경로를 제거하는 별도 내비게이션 함수로 교체하세요.🤖 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 `@app/src/main/java/kr/co/call/callfromai/AppScreen.kt` around lines 151 - 153, 온보딩 완료 후 백스택이 남지 않도록 onOnboarding6CallLater의 appNavigator.navigate(HomeNavKey)를 appNavigator.replaceAll(HomeNavKey)로 변경하세요. homeEntry의 navigateToHome과 동일하게 홈만 남기는 동작을 유지하세요.
🧹 Nitpick comments (1)
feature/onboarding/impl/src/main/java/kr/co/call/impl/entry/OnboardingEntryBuilder.kt (1)
36-102: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift저장한 온보딩 상태를 각 단계의 초기값으로 다시 주입하세요.
현재
uiState는 6단계의 이름 표시에만 사용됩니다. 앞 단계 destination이 재생성되면 입력 UI가 기본값으로 시작합니다. 4·5단계에는 각각traits와preferTime을 초기값으로 전달하고, 1~3단계도 동일하게 상태 호이스팅 가능한 초기값 계약을 추가하세요.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/entry/OnboardingEntryBuilder.kt` around lines 36 - 102, Update OnboardingEntryBuilder so each onboarding screen receives its saved onboardingViewModel uiState values as initial inputs when destinations are recreated. Add initial-value parameters to Onboarding1Screen, Onboarding2Screen, and Onboarding3Screen, and pass the corresponding saved profile, AI profile, and conversation-style state; also pass traits and preferTime to Onboarding4Screen and Onboarding5Screen. Preserve the existing update callbacks while ensuring every step can restore its prior inputs.
🤖 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 `@app/src/main/java/kr/co/call/callfromai/AppScreen.kt`:
- Around line 148-150: Update the onOnboarding6CallNow callback in AppScreen so
tapping “연결” either navigates to the existing call route or disables the CTA
until that destination is implemented; remove the no-op TODO behavior and
preserve the onboarding flow.
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingViewModel.kt`:
- Around line 16-83: Update OnboardingViewModel to use the Orbit MVI
ContainerHost pattern used by other feature implementation ViewModels: replace
the MutableStateFlow fields and each direct update call in updateUserProfile,
updateAiProfile, updateConversationStyle, updateTraits, and updatePreferTime
with intent blocks that reduce state via state.copy(...). Preserve the existing
field assignments and expose the Orbit container state through the established
pattern.
---
Outside diff comments:
In `@app/src/main/java/kr/co/call/callfromai/AppScreen.kt`:
- Around line 151-153: 온보딩 완료 후 백스택이 남지 않도록 onOnboarding6CallLater의
appNavigator.navigate(HomeNavKey)를 appNavigator.replaceAll(HomeNavKey)로 변경하세요.
homeEntry의 navigateToHome과 동일하게 홈만 남기는 동작을 유지하세요.
---
Nitpick comments:
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/entry/OnboardingEntryBuilder.kt`:
- Around line 36-102: Update OnboardingEntryBuilder so each onboarding screen
receives its saved onboardingViewModel uiState values as initial inputs when
destinations are recreated. Add initial-value parameters to Onboarding1Screen,
Onboarding2Screen, and Onboarding3Screen, and pass the corresponding saved
profile, AI profile, and conversation-style state; also pass traits and
preferTime to Onboarding4Screen and Onboarding5Screen. Preserve the existing
update callbacks while ensuring every step can restore its prior inputs.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 1e329b28-c6e9-4d4d-b0c1-826e95e30648
📒 Files selected for processing (9)
app/src/main/java/kr/co/call/callfromai/AppScreen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/MemberChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/ProfileChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/TempControl.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/entry/OnboardingEntryBuilder.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding6Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingUiState.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingViewModel.kt
🚧 Files skipped from review as they are similar to previous changes (4)
- feature/onboarding/impl/src/main/java/kr/co/call/impl/component/MemberChoice.kt
- feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding5Screen.kt
- feature/onboarding/impl/src/main/java/kr/co/call/impl/component/TempControl.kt
- feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding6Screen.kt
Gemini AI 코드리뷰안녕하세요, 시니어 Android 개발자입니다. Pull Request를 검토해 보았습니다. 전반적으로 새로운 온보딩 플로우와 관련 컴포넌트들을 추가하는 작업으로 보이며, Compose와 Hilt 사용에 대한 이해도가 높게 반영된 것 같습니다. 몇 가지 개선 사항과 잠재적인 문제를 발견하여 코멘트를 남깁니다.
|
…Android into feature/21-onboarding-ui
…om-ai/CallFromAi_Android into feature/21-onboarding-ui
Gemini AI 코드리뷰안녕하세요! 시니어 Android 개발자로서 Pull Request를 리뷰해 드리겠습니다. 이번 PR은 온보딩 플로우를 새로 추가하고, 이에 필요한 UI 컴포넌트들을 구현한 내용으로 보입니다. 전반적으로 Jetpack Compose의 모범 사례들을 잘 따르고 있어서 인상 깊었습니다. 특히 State Hoisting 원칙을 거의 모든 컴포넌트에서 준수하고 있는 점, 그리고 몇 가지 개선점과 추가로 고려하면 좋을 사항들을 정리해 보았습니다. 1.
|
There was a problem hiding this comment.
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/kr/co/call/callfromai/AppScreen.kt (1)
128-130: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift프로필 사진 선택 콜백을 무동작으로 두지 마세요.
onProfileClick이 빈 람다라서 온보딩의+프로필 선택 UI를 눌러도 아무 동작이 없습니다. 사진 선택이 이번 요구사항이면 picker와 상태 저장을 연결하고, 범위 밖이면 버튼을 비활성화해 오작동처럼 보이지 않게 해 주세요.PR 설명의 프로필 사진 선택 UI와 현재 콜백 구현을 기준으로 판단했습니다.
🤖 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 `@app/src/main/java/kr/co/call/callfromai/AppScreen.kt` around lines 128 - 130, Replace the empty onProfileClick callback in AppScreen with a working profile-image picker flow that updates and persists the selected photo state; if photo selection is out of scope, disable the corresponding profile-selection button instead of leaving the callback inert.
🤖 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.
Outside diff comments:
In `@app/src/main/java/kr/co/call/callfromai/AppScreen.kt`:
- Around line 128-130: Replace the empty onProfileClick callback in AppScreen
with a working profile-image picker flow that updates and persists the selected
photo state; if photo selection is out of scope, disable the corresponding
profile-selection button instead of leaving the callback inert.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: fcfc307d-72a2-44e3-9dd4-233be62e34b8
📒 Files selected for processing (4)
app/src/main/java/kr/co/call/callfromai/AppScreen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/entry/OnboardingEntryBuilder.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingViewModel.kt
🚧 Files skipped from review as they are similar to previous changes (2)
- feature/onboarding/impl/src/main/java/kr/co/call/impl/entry/OnboardingEntryBuilder.kt
- feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt
| val aiAge: String = "", | ||
| val aiJob: String = "", | ||
| val aiMbti: String = "", | ||
|
|
There was a problem hiding this comment.
state에서는 기본값 null 말고 디폴트로 맞춰주면 좋을 것 같아요~!
| fun Onboarding2Screen( | ||
| onBackClick: () -> Unit, | ||
| onProfileClick: () -> Unit, | ||
| onNextClick: ( |
There was a problem hiding this comment.
변수들 묶음으로 전달하는 것보다 Onboarding2State 이런식으로 상태로 보내는것도 좋아보입니당
| selectedOption = mbti, | ||
| placeholder = "MBTI를 선택해주세요", | ||
| options = listOf( | ||
| "INFP", "INFJ", "ENFP", "ENFJ", |
There was a problem hiding this comment.
별도 enum으로 분리하는 게 좋을 것 같아요 서버에 보내야 하는 값이라서!
| import kr.co.call.impl.component.TempControl | ||
| import kr.co.call.impl.component.TopTitle | ||
| import kr.co.call.onboarding.impl.R | ||
|
|
There was a problem hiding this comment.
요것도 스크린보다는 분리하는게 좋을 것 같긴 합니다..!
저는 상태나 도메인에 같이 분리해두는 편입니당
Gemini AI 코드리뷰안녕하세요, 팀원 여러분! 멀티스텝 온보딩 플로우를 통합하고 새로운 UI 컴포넌트들을 추가해주셔서 감사합니다. 온보딩 과정을 명확한 단계와 전용 내비게이션 키로 나눈 접근 방식은 훌륭한 아키텍처 결정이며, 새롭게 추가된 컴포넌트들도 깔끔하게 구현되었습니다. PR을 검토하면서 몇 가지 의견과 제안 사항을 드립니다. 주로 유지보수성, 현지화, 그리고 모범 사례 준수에 중점을 두었습니다.
|
There was a problem hiding this comment.
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 (1)
feature/onboarding/impl/src/main/java/kr/co/call/impl/component/BirthdayChoice.kt (1)
115-117: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win날짜 표시 포맷을 화면 명세와 맞춰 주세요.
현재
2000 / 1 / 1처럼 슬래시 주변에 공백이 표시됩니다. PR 설명의 화면 명세인2000/1/1과 맞추려면 구분자를 공백 없이 반환해야 합니다.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/component/BirthdayChoice.kt` around lines 115 - 117, Update the LocalDate.toDisplayText() formatting to return year, month, and day separated by "/" without surrounding spaces, matching the specified display format such as 2000/1/1.
🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/component/BirthdayChoice.kt`:
- Around line 101-106: Update the BottomWheel flow in the showBottomWheel block
so the display fallback LocalDate.now() is not treated as the selected value.
Track a nullable draft/explicit user selection separately and have
onConfirmClick call onDateSelected only when that value was explicitly chosen;
otherwise keep the picker open or reject confirmation, while preserving the
existing dismissal behavior after a valid selection.
---
Outside diff comments:
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/component/BirthdayChoice.kt`:
- Around line 115-117: Update the LocalDate.toDisplayText() formatting to return
year, month, and day separated by "/" without surrounding spaces, matching the
specified display format such as 2000/1/1.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7d0a8a41-05f5-41a1-85fe-cf7333678b8f
📒 Files selected for processing (7)
app/src/main/java/kr/co/call/callfromai/AppScreen.ktcore/designsystem/src/main/java/kr/co/call/designsystem/theme/Type.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/BirthdayChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingUiState.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingViewModel.kt
🚧 Files skipped from review as they are similar to previous changes (4)
- feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding4Screen.kt
- core/designsystem/src/main/java/kr/co/call/designsystem/theme/Type.kt
- feature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingViewModel.kt
- feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt
codebidoof
left a comment
There was a problem hiding this comment.
고생많았엉 지원이 피드백이랑 뷰모델 주입위치만 수정해 줘~~
| with(density) { bottomBarHeightPx.toDp() } | ||
| } | ||
|
|
||
| val onboardingViewModel: OnboardingViewModel = hiltViewModel() |
There was a problem hiding this comment.
온보딩 뷰모델 인스턴스는 여기서 생성해서 주입하지 말고 OnboardingEntryBuilder에서 생성해 주입해줘야 할 것 같아~~
Gemini AI 코드리뷰PR 리뷰 요청에 따라 시니어 Android 개발자의 관점에서 코드 리뷰를 진행하겠습니다. 🟢 Overall Review Summary새로운 온보딩 플로우를 위한 컴포넌트 추가 및 내비게이션 구조 변경이 주요 내용입니다. 전반적으로 Jetpack Compose의 모범 사례인 State hoisting, side effect 관리, UI 상태 표현 등을 잘 따르고 있습니다. 몇 가지 개선점은 주로 하드코딩된 문자열 및 매직 넘버, 그리고 사소한 코드 스타일 및 잠재적 UX 흐름에 대한 것입니다. 📝 Files Review1.
|
There was a problem hiding this comment.
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 (1)
feature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingUiState.kt (1)
14-14: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
userBirthday기본값이 실제 선택 가능한 날짜입니다.다른 3단계 이후 필드들(
speechStyle,relationship,preferTime등)은null로 "미입력"을 표현하는데,userBirthday만LocalDate.of(2000, 1, 1)라는 유효한 날짜를 기본값으로 사용합니다. 현재는Onboarding1Screen에서birthday != null일 때만updateUserProfile을 호출해 실사용 리스크는 없지만, 모델만 보면 "미선택"과 "2000-01-01 선택"을 구분할 수 없습니다.- val userBirthday: LocalDate = LocalDate.of(2000, 1, 1), + val userBirthday: LocalDate? = null,Based on learnings, "Onboarding 화면에서 생년월일(DOB) 입력의 '미선택/미완료' 상태를 표현할 때, 실제로 사용자가 선택할 수 있는 값(예: 2000/1/1)을 기본값으로 쓰지 마세요."
🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingUiState.kt` at line 14, Update the userBirthday property in OnboardingUiState to use a nullable type and a null default, matching the unset-state representation used by later onboarding fields. Preserve the existing selected-date behavior when a birthday is provided, while ensuring an unselected birthday cannot be confused with 2000-01-01.Source: Learnings
♻️ Duplicate comments (3)
feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt (3)
62-64: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
birthday가 구성 변경 시 유실됩니다 -rememberSaveable을 사용하세요.기본값을
null로 바꿔 "확인만 눌러도 오늘 날짜 저장" 문제는 해결됐지만,remember만 사용해 화면 회전 등 구성 변경 시 사용자가 선택한 생일이 초기화됩니다.LocalDate는Serializable이므로 커스텀 Saver 없이rememberSaveable만으로 충분합니다.🛠️ 제안 수정
- var birthday by remember { + var birthday by rememberSaveable { mutableStateOf<LocalDate?>(null) }🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt` around lines 62 - 64, Update the birthday state declaration in Onboarding1Screen to use rememberSaveable instead of remember, while preserving its nullable LocalDate type and null initial value so the selected birthday survives configuration changes without restoring today’s date.
54-54: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
profileImageURl오타 -profileImageUrl로 수정하세요 (기존 지적 미반영).camelCase 컨벤션 위반이며,
Onboarding2Screen은profileImageUrl로 올바르게 사용 중입니다.🛠️ 제안 수정
- profileImageURl: String?=null, + profileImageUrl: String? = null,그리고 사용처(114-117번 줄 부근)도 함께 변경:
ProfileChoice( state= ProfileChoiceState( - imageUrl = profileImageURl, + imageUrl = profileImageUrl, size=99.dp, ),As per path instructions,
**/*.kt: "네이밍 컨벤션 준수 여부: 클래스/인터페이스 PascalCase, 함수/변수 camelCase..."Also applies to: 113-117
🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt` at line 54, Rename the parameter profileImageURl to profileImageUrl in the onboarding screen declaration and update every corresponding usage around the referenced call sites. Keep the existing nullable type and behavior unchanged, matching the naming used by Onboarding2Screen.Source: Path instructions
204-251: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win이름 편집 오버레이 dismiss 시 키보드/포커스 정리 누락 (기존 지적 미반영).
배경 클릭과 전송 처리 모두에서
focusManager.clearFocus()/keyboardController?.hide()를 호출하지 않습니다.Onboarding2Screen의 동일 로직(218-219, 235-236)은 두 경로 모두 처리하는데 여기서는 빠져 있어 오버레이가 사라진 뒤에도 키보드가 남을 수 있습니다.🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt` around lines 204 - 251, Update the name-edit overlay dismissal paths in the editingNameField block, including the background clickable handler and MessageInputField.onSendClick, to clear focus through the screen’s focus manager and hide the keyboard through its keyboard controller before resetting the editing state. Match the existing Onboarding2Screen behavior while preserving the current name assignment and input reset logic.
🧹 Nitpick comments (1)
feature/onboarding/impl/src/main/java/kr/co/call/impl/component/BottomWheel.kt (1)
59-85: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win스크롤 감지용
LaunchedEffect3개 중복 - 헬퍼로 추출하세요.
yearState/monthState/dayState에 대해 동일한snapshotFlow { it.isScrollInProgress }.filter{it}.collect{ hasUserChangedDate = true }패턴이 세 번 반복됩니다. 사설 컴포저블 헬퍼로 추출하면 유지보수가 쉬워집니다.♻️ 제안 리팩터
+@Composable +private fun TrackWheelInteraction(listState: LazyListState, onChanged: () -> Unit) { + LaunchedEffect(listState) { + snapshotFlow { listState.isScrollInProgress } + .filter { it } + .collect { onChanged() } + } +} + ... - LaunchedEffect(yearState) { - snapshotFlow { yearState.isScrollInProgress } - .filter { it } - .collect { - hasUserChangedDate = true - } - } - - LaunchedEffect(monthState) { - snapshotFlow { monthState.isScrollInProgress } - .filter { it } - .collect { - hasUserChangedDate = true - } - } - - LaunchedEffect(dayState) { - snapshotFlow { dayState.isScrollInProgress } - .filter { it } - .collect { - hasUserChangedDate = true - } - } + TrackWheelInteraction(yearState) { hasUserChangedDate = true } + TrackWheelInteraction(monthState) { hasUserChangedDate = true } + TrackWheelInteraction(dayState) { hasUserChangedDate = true }🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/component/BottomWheel.kt` around lines 59 - 85, Extract the repeated scroll-detection logic from the three LaunchedEffect blocks into a private composable helper that accepts a wheel state and updates hasUserChangedDate when scrolling begins. Replace the yearState, monthState, and dayState blocks with calls to that helper while preserving the existing snapshotFlow and filtering behavior.
🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/state/Onboarding1State.kt`:
- Line 8: Update the birthday property in Onboarding1State to represent an
unselected birth date as null, matching the nullable selection flow in
Onboarding1Screen.kt; remove the LocalDate.now() default and ensure the
next-step submission validation rejects a null birthday before proceeding.
---
Outside diff comments:
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingUiState.kt`:
- Line 14: Update the userBirthday property in OnboardingUiState to use a
nullable type and a null default, matching the unset-state representation used
by later onboarding fields. Preserve the existing selected-date behavior when a
birthday is provided, while ensuring an unselected birthday cannot be confused
with 2000-01-01.
---
Duplicate comments:
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.kt`:
- Around line 62-64: Update the birthday state declaration in Onboarding1Screen
to use rememberSaveable instead of remember, while preserving its nullable
LocalDate type and null initial value so the selected birthday survives
configuration changes without restoring today’s date.
- Line 54: Rename the parameter profileImageURl to profileImageUrl in the
onboarding screen declaration and update every corresponding usage around the
referenced call sites. Keep the existing nullable type and behavior unchanged,
matching the naming used by Onboarding2Screen.
- Around line 204-251: Update the name-edit overlay dismissal paths in the
editingNameField block, including the background clickable handler and
MessageInputField.onSendClick, to clear focus through the screen’s focus manager
and hide the keyboard through its keyboard controller before resetting the
editing state. Match the existing Onboarding2Screen behavior while preserving
the current name assignment and input reset logic.
---
Nitpick comments:
In
`@feature/onboarding/impl/src/main/java/kr/co/call/impl/component/BottomWheel.kt`:
- Around line 59-85: Extract the repeated scroll-detection logic from the three
LaunchedEffect blocks into a private composable helper that accepts a wheel
state and updates hasUserChangedDate when scrolling begins. Replace the
yearState, monthState, and dayState blocks with calls to that helper while
preserving the existing snapshotFlow and filtering behavior.
🪄 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: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 9db1ed60-28d8-4153-8ae9-ed4fc9ad85fe
📒 Files selected for processing (16)
app/src/main/java/kr/co/call/callfromai/AppScreen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/BirthdayChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/BottomWheel.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/component/ProfileChoice.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/entry/OnboardingEntryBuilder.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding1Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding2Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/screen/Onboarding3Screen.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingUiState.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/OnboardingViewModel.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/model/Mbti.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/model/Relationship.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/model/SpeechStyle.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/state/Onboarding1State.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/state/Onboarding2State.ktfeature/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/state/ProfileChoiceState.kt
💤 Files with no reviewable changes (1)
- app/src/main/java/kr/co/call/callfromai/AppScreen.kt
| data class Onboarding1State ( | ||
| val lastName: String="", | ||
| val firstName: String="", | ||
| val birthday: LocalDate=LocalDate.now(), |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
생년월일 미선택 상태에 오늘 날짜를 사용하지 마세요.
LocalDate.now()는 사용자가 생년월일을 선택하지 않은 기본 생성·상태 복원·부분 입력 경로에서 오늘 날짜를 실제 생년월일로 오인하게 만들 수 있습니다. LocalDate? = null 또는 별도의 선택 여부 상태로 모델링하고, 다음 단계에서 미선택 상태를 검증하세요.
Based on learnings, 생년월일 미선택 상태는 실제 선택 가능한 날짜가 아닌 별도 상태로 표현해야 하며, 제공된 Onboarding1Screen.kt의 nullable 선택 흐름과도 일치시켜야 합니다.
제안 수정
- val birthday: LocalDate=LocalDate.now(),
+ val birthday: LocalDate? = null,📝 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.
| val birthday: LocalDate=LocalDate.now(), | |
| val birthday: LocalDate? = null, |
🤖 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/onboarding/impl/src/main/java/kr/co/call/impl/viewmodel/state/Onboarding1State.kt`
at line 8, Update the birthday property in Onboarding1State to represent an
unselected birth date as null, matching the nullable selection flow in
Onboarding1Screen.kt; remove the LocalDate.now() default and ensure the
next-step submission validation rejects a null birthday before proceeding.
Source: Learnings
Gemini AI 코드리뷰안녕하세요, 시니어 Android 개발자입니다. PR diff 잘 검토했습니다. [전반적인 피드백]
[세부 코드 리뷰]1.
|
Gemini AI 코드리뷰안녕하세요! 시니어 안드로이드 개발자로서 GitHub Pull Request 리뷰를 시작하겠습니다. 온보딩 플로우를 개선하고 새로운 컴포넌트들을 도입하는 작업으로 보이네요. 전반적으로 코드 품질이 좋고 Jetpack Compose의 모범 사례를 잘 따르려고 노력한 흔적이 보입니다. 몇 가지 개선점을 제안해 드릴게요. PR 요약이 PR은 주로 온보딩(Onboarding) 플로우를 여러 단계로 세분화하고, 이를 위한 새로운 Jetpack Compose UI 컴포넌트들을 추가합니다.
코드 리뷰 상세1. Kotlin 코드 리뷰 (일반)
2. Jetpack Compose 코드 리뷰
3. Repository/DataSource 레이어
4. ViewModel
5. FCM/SSE/실시간 통신 관련 코드
전반적인 개선 제안
긍정적인 측면
결론: 전반적으로 매우 훌륭한 PR입니다. 특히 Jetpack Compose의 모범 사례를 잘 따르며 재사용 가능한 컴포넌트를 효과적으로 구현한 점이 인상 깊습니다. 위에서 언급한 하드코딩된 문자열과 매직 넘버들을 리소스 및 상수로 분리하는 작업을 해주시면 더욱 완벽한 코드가 될 것 같습니다. 리뷰해주셔서 감사합니다! |
📄 작업 내용 요약
-온보딩 UI 구현
📎 Issue 번호
✅ 작업 목록
📝 기타 참고사항
Summary by CodeRabbit