Conversation
Walkthrough스낵바에 아이콘 타입 지원을 추가하고 퀘스트 관련 리뷰(공통/개인 답변) UI, 바텀시트 옵션 및 관련 네비게이션 경로들을 대규모로 추가/연결했습니다. Changes
|퀘스트 리뷰 UI — 공통 답변 Sequence Diagram(s)(생략) Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 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 |
There was a problem hiding this comment.
Actionable comments posted: 6
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/com/byeboo/app/presentation/quest/screen/CommonJourneyScreen.kt (1)
186-193:⚠️ Potential issue | 🔴 Critical
onAnswerClick에 하드코딩된 값1이 전달되고 있습니다.현재
onAnswerClick(1)로 하드코딩되어 있어, 어떤 답변 항목을 클릭해도 항상 answerId가 1로 전달됩니다. 실제 답변의 ID를 전달해야 합니다.🐛 수정 제안
items( items = state.answers, key = { it.answerId }, ) { answer -> CommonAnswerItem( answer = answer, - onClick = { onAnswerClick(1) }, + onClick = { onAnswerClick(answer.answerId) }, modifier = Modifier .padding(horizontal = screenWidthDp(24.dp)) .padding(bottom = screenHeightDp(24.dp)), ) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/screen/CommonJourneyScreen.kt` around lines 186 - 193, The onClick for CommonAnswerItem is passing a hardcoded 1 to onAnswerClick; change it to pass the clicked answer's ID (e.g., use answer.id or answer.answerId depending on the model) so the real answer identifier is forwarded to onAnswerClick; update the onClick lambda in CommonAnswerItem to call onAnswerClick with the answer's id property (and add a null/exists check if the model uses a nullable id).
🧹 Nitpick comments (13)
app/src/main/res/drawable/ic_report.xml (1)
10-26: 색상 하드코딩 대신 색상 리소스 참조로 바꾸는 것을 권장합니다.
#FF3B3E가 여러 path에 중복되어 있어 추후 테마 대응(다크모드/브랜드 컬러 변경) 시 유지보수 비용이 커집니다.@color/...로 추출해 공통 관리하는 편이 안전합니다.♻️ 제안 diff
- android:strokeColor="#FF3B3E"/> + android:strokeColor="@color/snackbar_alert_icon"/> - android:strokeColor="#FF3B3E" + android:strokeColor="@color/snackbar_alert_icon" - android:fillColor="#FF3B3E"/> + android:fillColor="@color/snackbar_alert_icon"/> - android:fillColor="#FF3B3E"/> + android:fillColor="@color/snackbar_alert_icon"/>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/res/drawable/ic_report.xml` around lines 10 - 26, 해당 XML의 여러 path 요소(android:strokeColor 및 android:fillColor)에 하드코딩된 색상값 "#FF3B3E"가 중복되어 있으니 colors.xml에 예: <color name="ic_report_tint">#FF3B3E</color> 같은 리소스를 추가한 뒤 ic_report.xml의 모든 android:strokeColor 및 android:fillColor="#FF3B3E"를 `@color/ic_report_tint로` 교체하세요; 변경 대상 식별에는 각 <path> 요소의 android:pathData 값(예: "M18,16H6V9.538...", "M4,20L20,20", "M12.005,6.5...", "M12,12.5m-1,0...")과 속성 이름(strokeColor, fillColor)을 참고하면 됩니다.app/src/main/res/drawable/ic_overflow_menu.xml (1)
1-9: 전반적으로 LGTM, 색상 리소스 사용 고려 권장벡터 드로어블 구조와 아이콘 형태는 적절합니다. 다만
fillColor가#ffffff로 하드코딩되어 있어 다크/라이트 테마 지원이나 다른 배경에서의 재사용성이 제한될 수 있습니다.스낵바 등 특정 UI에서만 사용될 경우 현재 구현도 무방하지만, 향후 유연성을 위해 색상 리소스나 테마 속성 사용을 고려해 보세요.
♻️ 색상 리소스 사용 제안
<path android:pathData="M12,16.5C12.398,16.5 12.779,16.658 13.061,16.939C13.342,17.221 13.5,17.602 13.5,18C13.5,18.398 13.342,18.779 13.061,19.061C12.779,19.342 12.398,19.5 12,19.5C11.602,19.5 11.221,19.342 10.939,19.061C10.658,18.779 10.5,18.398 10.5,18C10.5,17.602 10.658,17.221 10.939,16.939C11.221,16.658 11.602,16.5 12,16.5ZM12,10.5C12.398,10.5 12.779,10.658 13.061,10.939C13.342,11.221 13.5,11.602 13.5,12C13.5,12.398 13.342,12.779 13.061,13.061C12.779,13.342 12.398,13.5 12,13.5C11.602,13.5 11.221,13.342 10.939,13.061C10.658,12.779 10.5,12.398 10.5,12C10.5,11.602 10.658,11.221 10.939,10.939C11.221,10.658 11.602,10.5 12,10.5ZM12,4.5C12.398,4.5 12.779,4.658 13.061,4.939C13.342,5.221 13.5,5.602 13.5,6C13.5,6.398 13.342,6.779 13.061,7.061C12.779,7.342 12.398,7.5 12,7.5C11.602,7.5 11.221,7.342 10.939,7.061C10.658,6.779 10.5,6.398 10.5,6C10.5,5.602 10.658,5.221 10.939,4.939C11.221,4.658 11.602,4.5 12,4.5Z" - android:fillColor="#ffffff"/> + android:fillColor="@color/white"/> </vector>또는 런타임에
ImageView.setColorFilter()또는app:tint를 사용하여 아이콘 색상을 동적으로 적용하는 방법도 있습니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/res/drawable/ic_overflow_menu.xml` around lines 1 - 9, Replace the hardcoded android:fillColor="#ffffff" in the <path> of the vector drawable with a color resource or theme attribute so the icon follows dark/light themes and can be reused; e.g. change android:fillColor to a reference like `@color/overflow_icon` or a theme attribute like ?attr/colorOnSurface (or make the vector tintable and remove the fillColor so callers can set app:tint or ImageView.setColorFilter), update the color resource if needed, and ensure usages apply the intended tint/theme attribute.app/src/main/res/drawable/ic_block.xml (1)
6-8:clip-path는 제거해도 동일하게 동작합니다.Line 7-8은 전체 캔버스를 그대로 클리핑해서 렌더링 결과 변화가 없습니다. 단순화를 위해 제거를 권장합니다.
Diff 제안
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - <group> - <clip-path - android:pathData="M0,0h24v24h-24z"/> <path android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0" android:strokeWidth="2" android:fillColor="#00000000" android:strokeColor="#ffffff"/> <path android:pathData="M6.327,17.26L17.327,7.26" android:strokeWidth="2" android:fillColor="#00000000" android:strokeColor="#ffffff"/> - </group> </vector>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/res/drawable/ic_block.xml` around lines 6 - 8, SVG/XML contains an unnecessary clip-path that clips the whole canvas (the <clip-path> element with android:pathData="M0,0h24v24h-24z"); remove that <clip-path> element (and its enclosing empty group if it becomes redundant) from ic_block.xml so the drawable is simplified without changing rendering.app/src/main/java/com/byeboo/app/presentation/quest/component/card/MyAnswerItem.kt (1)
60-60: Spacer에padding대신height사용 필요Line 60에서
Spacer에padding을 사용하고 있습니다.padding은 모든 방향에 여백을 추가하므로 의도한 12dp가 아닌 24dp(위아래 합산)의 수직 공간이 생깁니다. Line 70처럼height를 사용해야 합니다.♻️ 수정 제안
- Spacer(modifier = Modifier.padding(screenHeightDp(12.dp))) + Spacer(modifier = Modifier.height(screenHeightDp(12.dp)))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/component/card/MyAnswerItem.kt` at line 60, In MyAnswerItem (file MyAnswerItem.kt) the Spacer uses Modifier.padding(screenHeightDp(12.dp)) which adds padding both top and bottom (totaling 24dp) instead of providing a 12dp vertical gap; change the Spacer's modifier to Modifier.height(screenHeightDp(12.dp)) so it produces the intended 12dp vertical space (refer to the Spacer instance around the commented line and mirror the approach used later on line 70).app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerViewModel.kt (1)
84-90: 불필요한viewModelScope.launch블록현재
when블록 내에 suspend 함수 호출이 없어viewModelScope.launch가 불필요합니다. TODO 구현 시 실제 비동기 작업이 추가되면 필요하겠지만, 현재로서는 제거하거나 실제 구현 시 추가하는 것이 더 명확합니다.♻️ 선택적 수정 제안
fun onOptionClick(option: OptionType) { onDismissBottomSheet() - viewModelScope.launch { - when (option) { - OptionType.EDIT -> { /* TODO 수정 화면 이동 */ } - OptionType.DELETE -> { /* TODO 삭제 모달 띄우기 */ } - else -> {} - } + when (option) { + OptionType.EDIT -> { /* TODO 수정 화면 이동 */ } + OptionType.DELETE -> { /* TODO 삭제 모달 띄우기 */ } + else -> {} } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerViewModel.kt` around lines 84 - 90, The current viewModelScope.launch wrapper around the when(option) block is unnecessary because there are no suspend calls; remove the viewModelScope.launch call and execute the when(option) directly (retaining the OptionType.EDIT and OptionType.DELETE branches) and only reintroduce viewModelScope.launch around the when when you implement actual asynchronous work for those branches (or make the called functions suspend and keep the launch). Refer to the viewModelScope.launch and the when(option) handling OptionType.EDIT / OptionType.DELETE in MyAnswerViewModel to locate and update the code.app/src/main/java/com/byeboo/app/presentation/offboarding/offboardingquestcompleted/OffboardingQuestCompletedViewModel.kt (1)
60-68: onFailure 내부의 중첩launch는 제거하는 편이 좋습니다.이미
viewModelScope.launch안에서 실행 중이라_sideEffect.emit(...)을 직접 호출해도 됩니다. 중첩 코루틴을 줄이면 흐름이 단순해집니다.제안 diff
- }.onFailure { - viewModelScope.launch { - _sideEffect.emit( - QuestCompletedSideEffect.ShowSnackBar( - message = "서버에 연결할 수 없습니다. 잠시 후 시도해 주세요.", - iconType = CustomSnackBarType.ALERT, - ), - ) - } - } + }.onFailure { + _sideEffect.emit( + QuestCompletedSideEffect.ShowSnackBar( + message = "서버에 연결할 수 없습니다. 잠시 후 시도해 주세요.", + iconType = CustomSnackBarType.ALERT, + ), + ) + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/offboarding/offboardingquestcompleted/OffboardingQuestCompletedViewModel.kt` around lines 60 - 68, In OffboardingQuestCompletedViewModel inside the onFailure block, remove the nested viewModelScope.launch and directly call _sideEffect.emit(...) from the surrounding coroutine context (you are already inside viewModelScope.launch), so replace the inner launch-wrapped emit with a direct _sideEffect.emit call (keep the same QuestCompletedSideEffect.ShowSnackBar parameters and CustomSnackBarType.ALERT).app/src/main/java/com/byeboo/app/presentation/quest/start/QuestStartViewModel.kt (1)
92-95: 동일한 에러 스낵바 emit 로직은 헬퍼로 합치는 것을 권장합니다.현재 두 실패 분기에서 동일한 블록이 반복되어 유지보수 시 메시지/타입 변경 누락 위험이 있습니다.
♻️ 제안 diff
@@ - _sideEffect.emit( - QuestStartSideEffect.ShowSnackBar( - message = "서버에 연결할 수 없습니다. 잠시 후 시도해 주세요.", - iconType = CustomSnackBarType.ALERT, - ), - ) + emitServerConnectionErrorSnackBar() @@ - _sideEffect.emit( - QuestStartSideEffect.ShowSnackBar( - message = "서버에 연결할 수 없습니다. 잠시 후 시도해 주세요.", - iconType = CustomSnackBarType.ALERT, - ), - ) + emitServerConnectionErrorSnackBar() @@ + private suspend fun emitServerConnectionErrorSnackBar() { + _sideEffect.emit( + QuestStartSideEffect.ShowSnackBar( + message = "서버에 연결할 수 없습니다. 잠시 후 시도해 주세요.", + iconType = CustomSnackBarType.ALERT, + ), + ) + }Also applies to: 132-135
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/start/QuestStartViewModel.kt` around lines 92 - 95, Duplicate ShowSnackBar emission with the same message/type is repeated in QuestStartViewModel (the QuestStartSideEffect.ShowSnackBar blocks at the two failure branches around the existing emits), so extract a single helper method (e.g., emitServerConnectionSnackBar or emitErrorSnackBar) inside QuestStartViewModel that constructs/emits QuestStartSideEffect.ShowSnackBar with the shared message and CustomSnackBarType.ALERT, then replace both duplicated blocks (the ones around lines 92-95 and 132-135) with calls to that helper to centralize the message/type and avoid drift.app/src/main/java/com/byeboo/app/core/designsystem/component/snackbar/CustomSnackBarVisuals.kt (1)
7-13: 구현이 올바르며, data class 사용을 고려해 볼 수 있습니다.
SnackbarVisuals인터페이스 구현이 적절합니다. 선택적으로data class로 변경하면equals,hashCode,copy메서드를 자동으로 얻을 수 있어 테스트나 비교 시 유용할 수 있습니다.♻️ data class로 변경 제안
-class CustomSnackBarVisuals( +data class CustomSnackBarVisuals( override val message: String, val type: CustomSnackBarType, override val actionLabel: String? = null, override val withDismissAction: Boolean = false, override val duration: SnackbarDuration = SnackbarDuration.Short, ) : SnackbarVisuals🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/core/designsystem/component/snackbar/CustomSnackBarVisuals.kt` around lines 7 - 13, Convert the CustomSnackBarVisuals class into a data class to automatically get equals/hashCode/copy/toString for easier testing and comparisons; update the declaration of CustomSnackBarVisuals (which implements SnackbarVisuals and references CustomSnackBarType, message, actionLabel, withDismissAction, duration) so it is declared as a data class while keeping the same primary constructor parameters and the implemented interface SnackbarVisuals.app/src/main/java/com/byeboo/app/presentation/quest/component/type/OptionType.kt (1)
6-29: 하드코딩된 문자열을 string resource로 이동하는 것을 고려해 주세요.
optionTitle값들이 직접 하드코딩되어 있습니다. 향후 다국어 지원(i18n)을 위해 string resource로 관리하는 것이 좋습니다.♻️ String resource 사용 제안
enum class OptionType( `@DrawableRes` val optionIcon: Int, - val optionTitle: String, + `@StringRes` val optionTitleRes: Int, ) { BLOCK( optionIcon = R.drawable.ic_block, - optionTitle = "사용자 차단하기", + optionTitleRes = R.string.option_block_user, ), // ... 나머지 항목도 동일하게 적용 }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/component/type/OptionType.kt` around lines 6 - 29, The enum OptionType currently hardcodes Korean titles in the optionTitle property for entries BLOCK, REPORT, EDIT, DELETE; change optionTitle to reference string resources instead (e.g., R.string.option_block, R.string.option_report, R.string.option_edit, R.string.option_delete) and update callers to resolve the string via Context or a string provider when displaying (keep the enum values as resource IDs or store `@StringRes` ints rather than raw Strings). Ensure you add the corresponding entries to strings.xml and mark optionTitle as an Int annotated with `@StringRes` in the OptionType class.app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt (1)
122-126: 뒤로 가기 버튼이 비활성화 상태입니다.PR 목표에서 "뒤로 가기 아이콘 네비 연결"이 미완료 항목으로 언급되어 있습니다.
navigateUp콜백을MyAnswerDetailRoute에 추가하고 연결해야 합니다.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt` around lines 122 - 126, Add a navigateUp callback to the MyAnswerDetailRoute and wire it to the back icon's click handler: update the MyAnswerDetailRoute signature to accept a navigateUp: () -> Unit parameter, pass that down to MyAnswerDetailScreen, and replace the TODO in the Modifier.noRippleClickable used for the back icon so it calls navigateUp() when clicked; ensure any callers of MyAnswerDetailRoute provide the appropriate NavController::navigateUp or equivalent lambda.app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt (1)
129-133: 뒤로 가기 버튼 클릭 핸들러가 누락되었습니다.PR 목표에서 "뒤로 가기 아이콘 네비 연결"이 미완료 항목으로 언급되어 있습니다. 이후 작업 시
navigateUp또는navigateToQuest콜백을 연결해야 합니다.이 기능을 구현하기 위한 코드를 생성해 드릴까요, 아니면 추적을 위한 이슈를 생성할까요?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt` around lines 129 - 133, The back icon currently lacks a click handler; wrap the Icon in a clickable surface (e.g., IconButton or Modifier.clickable) and invoke the appropriate navigation callback passed into CommonAnswerScreen (use the existing navigateUp or navigateToQuest parameter/name) to perform navigation when tapped; ensure the click target uses the same tint and accessibility by keeping contentDescription non-null (e.g., "Back") so TalkBack users get the action.app/src/main/java/com/byeboo/app/presentation/quest/component/bottomsheet/MoreOptionsBottomSheet.kt (1)
85-92: 일관성을 위해screenHeightDp사용을 고려해 주세요.다른 부분에서는
screenHeightDp/screenWidthDp를 사용하여 반응형 레이아웃을 구현하고 있는데,HorizontalDivider의padding(vertical = 20.dp)에서는 하드코딩된 값을 사용하고 있습니다.♻️ 수정 제안
HorizontalDivider( modifier = Modifier .fillMaxWidth() - .padding(vertical = 20.dp), + .padding(vertical = screenHeightDp(20.dp)), thickness = 1.dp, color = ByeBooTheme.colors.gray800, )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/component/bottomsheet/MoreOptionsBottomSheet.kt` around lines 85 - 92, Replace the hardcoded Vertical padding on HorizontalDivider in MoreOptionsBottomSheet (the Modifier.padding(vertical = 20.dp) call) with a responsive value derived from the existing screenHeightDp/screenWidthDp approach used in this file; compute the vertical padding from screenHeightDp (using the same scale factor pattern used elsewhere) and apply that computed value to Modifier.padding so the divider spacing scales with screen size.app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerScreen.kt (1)
88-92: 뒤로 가기 버튼이 비활성화 상태입니다.
noRippleClickable에 클릭 핸들러가 없어 뒤로 가기 아이콘이 동작하지 않습니다. TODO 주석이 있으니 이후 네비게이션 연결이 필요합니다.이 기능을 구현하는 코드를 생성해 드릴까요?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerScreen.kt` around lines 88 - 92, The back button is non-functional because Modifier.noRippleClickable has no onClick handler; in MyAnswerScreen replace the TODO with a lambda that performs navigation (e.g., Modifier.noRippleClickable { navController.popBackStack() } ) or, if NavController isn't available in this composable, add an onBackPressed/onNavigateUp: ()->Unit parameter to MyAnswerScreen and call that inside the noRippleClickable lambda (Modifier.noRippleClickable { onBackPressed() }) so the icon actually navigates back.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@app/src/main/java/com/byeboo/app/presentation/quest/component/bottomsheet/MoreOptionsBottomSheet.kt`:
- Line 76: The Spacer uses Modifier.padding(end = screenWidthDp(12.dp)) which
doesn't create horizontal space; replace the padding modifier with a width
modifier so the Spacer actually occupies horizontal gap (change Spacer(...
Modifier.padding(end = screenWidthDp(12.dp))) to use
Modifier.width(screenWidthDp(12.dp))) in MoreOptionsBottomSheet (also update the
second occurrence around the other Spacer noted in the comment).
In
`@app/src/main/java/com/byeboo/app/presentation/quest/navigation/QuestNavigation.kt`:
- Around line 133-137: MyAnswerDetailRoute is not receiving the answerId from
the QuestMyAnswersDetail nav route, so the UI always shows the first answer;
update the navigation composable to pass the route args into the route and
change MyAnswerViewModel to read the answerId from SavedStateHandle (use
savedStateHandle.toRoute<QuestMyAnswersDetail>().answerId) and use that id to
load the specific answer; target symbols: composable<QuestMyAnswersDetail>,
MyAnswerDetailRoute, MyAnswerViewModel, SavedStateHandle, toRoute, answerId.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt`:
- Around line 147-148: In CommonAnswerScreen.kt the Spacer inside the Row uses
Modifier.padding(bottom = screenHeightDp(16.dp)) which has no effect because Row
lays out children horizontally; either remove the unused Spacer or replace its
modifier to produce the intended spacing: if you wanted horizontal space use
Modifier.width(...), if you wanted vertical space move the Spacer out of the Row
into a Column/parent and use Modifier.height(screenHeightDp(16.dp)) or apply the
bottom padding to the Row or parent container; update the Spacer or parent
accordingly to reflect the intended vertical/horizontal spacing.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt`:
- Line 139: The Spacer inside the Row in MyAnswerDetailScreen.kt is using
Modifier.padding(bottom = screenHeightDp(16.dp)), which has no effect in a
horizontal Row; replace that Spacer with a vertical spacing approach by using a
Spacer with Modifier.height(screenHeightDp(16.dp)) or move the bottom padding to
a parent Column/Box that controls vertical spacing (refer to the Spacer instance
and the surrounding Row in MyAnswerDetailScreen.kt and mirror the fix used in
CommonAnswerScreen.kt).
- Line 64: The current code uses uiState.answers.first() which throws
NoSuchElementException for empty lists; change that to a safe access (e.g., use
firstOrNull() or getOrNull(0)) and handle the null case rather than letting it
crash — update the val answerState assignment in MyAnswerDetailScreen to use
uiState.answers.firstOrNull() (or uiState.answers.getOrNull(0)) and then either
early-return, show an empty/error UI, or provide a fallback value so downstream
code using answerState is not executed with a missing item.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerScreen.kt`:
- Around line 96-106: The Text composable in MyAnswerScreen currently hardcodes
the nickname string ("하츠핑하츠님의") inside the buildAnnotatedString; replace that
hardcoded text by injecting the real user nickname from the screen state (e.g.,
use uiState.nickname or a value exposed by the ViewModel) when building the
string in the Text composable (the buildAnnotatedString block used for the
header), ensuring you handle null/empty nickname with a sensible fallback.
---
Outside diff comments:
In
`@app/src/main/java/com/byeboo/app/presentation/quest/screen/CommonJourneyScreen.kt`:
- Around line 186-193: The onClick for CommonAnswerItem is passing a hardcoded 1
to onAnswerClick; change it to pass the clicked answer's ID (e.g., use answer.id
or answer.answerId depending on the model) so the real answer identifier is
forwarded to onAnswerClick; update the onClick lambda in CommonAnswerItem to
call onAnswerClick with the answer's id property (and add a null/exists check if
the model uses a nullable id).
---
Nitpick comments:
In
`@app/src/main/java/com/byeboo/app/core/designsystem/component/snackbar/CustomSnackBarVisuals.kt`:
- Around line 7-13: Convert the CustomSnackBarVisuals class into a data class to
automatically get equals/hashCode/copy/toString for easier testing and
comparisons; update the declaration of CustomSnackBarVisuals (which implements
SnackbarVisuals and references CustomSnackBarType, message, actionLabel,
withDismissAction, duration) so it is declared as a data class while keeping the
same primary constructor parameters and the implemented interface
SnackbarVisuals.
In
`@app/src/main/java/com/byeboo/app/presentation/offboarding/offboardingquestcompleted/OffboardingQuestCompletedViewModel.kt`:
- Around line 60-68: In OffboardingQuestCompletedViewModel inside the onFailure
block, remove the nested viewModelScope.launch and directly call
_sideEffect.emit(...) from the surrounding coroutine context (you are already
inside viewModelScope.launch), so replace the inner launch-wrapped emit with a
direct _sideEffect.emit call (keep the same
QuestCompletedSideEffect.ShowSnackBar parameters and CustomSnackBarType.ALERT).
In
`@app/src/main/java/com/byeboo/app/presentation/quest/component/bottomsheet/MoreOptionsBottomSheet.kt`:
- Around line 85-92: Replace the hardcoded Vertical padding on HorizontalDivider
in MoreOptionsBottomSheet (the Modifier.padding(vertical = 20.dp) call) with a
responsive value derived from the existing screenHeightDp/screenWidthDp approach
used in this file; compute the vertical padding from screenHeightDp (using the
same scale factor pattern used elsewhere) and apply that computed value to
Modifier.padding so the divider spacing scales with screen size.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/component/card/MyAnswerItem.kt`:
- Line 60: In MyAnswerItem (file MyAnswerItem.kt) the Spacer uses
Modifier.padding(screenHeightDp(12.dp)) which adds padding both top and bottom
(totaling 24dp) instead of providing a 12dp vertical gap; change the Spacer's
modifier to Modifier.height(screenHeightDp(12.dp)) so it produces the intended
12dp vertical space (refer to the Spacer instance around the commented line and
mirror the approach used later on line 70).
In
`@app/src/main/java/com/byeboo/app/presentation/quest/component/type/OptionType.kt`:
- Around line 6-29: The enum OptionType currently hardcodes Korean titles in the
optionTitle property for entries BLOCK, REPORT, EDIT, DELETE; change optionTitle
to reference string resources instead (e.g., R.string.option_block,
R.string.option_report, R.string.option_edit, R.string.option_delete) and update
callers to resolve the string via Context or a string provider when displaying
(keep the enum values as resource IDs or store `@StringRes` ints rather than raw
Strings). Ensure you add the corresponding entries to strings.xml and mark
optionTitle as an Int annotated with `@StringRes` in the OptionType class.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt`:
- Around line 129-133: The back icon currently lacks a click handler; wrap the
Icon in a clickable surface (e.g., IconButton or Modifier.clickable) and invoke
the appropriate navigation callback passed into CommonAnswerScreen (use the
existing navigateUp or navigateToQuest parameter/name) to perform navigation
when tapped; ensure the click target uses the same tint and accessibility by
keeping contentDescription non-null (e.g., "Back") so TalkBack users get the
action.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt`:
- Around line 122-126: Add a navigateUp callback to the MyAnswerDetailRoute and
wire it to the back icon's click handler: update the MyAnswerDetailRoute
signature to accept a navigateUp: () -> Unit parameter, pass that down to
MyAnswerDetailScreen, and replace the TODO in the Modifier.noRippleClickable
used for the back icon so it calls navigateUp() when clicked; ensure any callers
of MyAnswerDetailRoute provide the appropriate NavController::navigateUp or
equivalent lambda.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerScreen.kt`:
- Around line 88-92: The back button is non-functional because
Modifier.noRippleClickable has no onClick handler; in MyAnswerScreen replace the
TODO with a lambda that performs navigation (e.g., Modifier.noRippleClickable {
navController.popBackStack() } ) or, if NavController isn't available in this
composable, add an onBackPressed/onNavigateUp: ()->Unit parameter to
MyAnswerScreen and call that inside the noRippleClickable lambda
(Modifier.noRippleClickable { onBackPressed() }) so the icon actually navigates
back.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerViewModel.kt`:
- Around line 84-90: The current viewModelScope.launch wrapper around the
when(option) block is unnecessary because there are no suspend calls; remove the
viewModelScope.launch call and execute the when(option) directly (retaining the
OptionType.EDIT and OptionType.DELETE branches) and only reintroduce
viewModelScope.launch around the when when you implement actual asynchronous
work for those branches (or make the called functions suspend and keep the
launch). Refer to the viewModelScope.launch and the when(option) handling
OptionType.EDIT / OptionType.DELETE in MyAnswerViewModel to locate and update
the code.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/start/QuestStartViewModel.kt`:
- Around line 92-95: Duplicate ShowSnackBar emission with the same message/type
is repeated in QuestStartViewModel (the QuestStartSideEffect.ShowSnackBar blocks
at the two failure branches around the existing emits), so extract a single
helper method (e.g., emitServerConnectionSnackBar or emitErrorSnackBar) inside
QuestStartViewModel that constructs/emits QuestStartSideEffect.ShowSnackBar with
the shared message and CustomSnackBarType.ALERT, then replace both duplicated
blocks (the ones around lines 92-95 and 132-135) with calls to that helper to
centralize the message/type and avoid drift.
In `@app/src/main/res/drawable/ic_block.xml`:
- Around line 6-8: SVG/XML contains an unnecessary clip-path that clips the
whole canvas (the <clip-path> element with android:pathData="M0,0h24v24h-24z");
remove that <clip-path> element (and its enclosing empty group if it becomes
redundant) from ic_block.xml so the drawable is simplified without changing
rendering.
In `@app/src/main/res/drawable/ic_overflow_menu.xml`:
- Around line 1-9: Replace the hardcoded android:fillColor="#ffffff" in the
<path> of the vector drawable with a color resource or theme attribute so the
icon follows dark/light themes and can be reused; e.g. change android:fillColor
to a reference like `@color/overflow_icon` or a theme attribute like
?attr/colorOnSurface (or make the vector tintable and remove the fillColor so
callers can set app:tint or ImageView.setColorFilter), update the color resource
if needed, and ensure usages apply the intended tint/theme attribute.
In `@app/src/main/res/drawable/ic_report.xml`:
- Around line 10-26: 해당 XML의 여러 path 요소(android:strokeColor 및
android:fillColor)에 하드코딩된 색상값 "#FF3B3E"가 중복되어 있으니 colors.xml에 예: <color
name="ic_report_tint">#FF3B3E</color> 같은 리소스를 추가한 뒤 ic_report.xml의 모든
android:strokeColor 및 android:fillColor="#FF3B3E"를 `@color/ic_report_tint로` 교체하세요;
변경 대상 식별에는 각 <path> 요소의 android:pathData 값(예: "M18,16H6V9.538...",
"M4,20L20,20", "M12.005,6.5...", "M12,12.5m-1,0...")과 속성 이름(strokeColor,
fillColor)을 참고하면 됩니다.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (82)
app/src/main/java/com/byeboo/app/core/designsystem/component/snackbar/CustomSnackBar.ktapp/src/main/java/com/byeboo/app/core/designsystem/component/snackbar/CustomSnackBarVisuals.ktapp/src/main/java/com/byeboo/app/core/designsystem/event/SnackbarTrigger.ktapp/src/main/java/com/byeboo/app/core/designsystem/type/CustomSnackBarType.ktapp/src/main/java/com/byeboo/app/presentation/auth/userinfo/UserInfoScreen.ktapp/src/main/java/com/byeboo/app/presentation/auth/userinfo/UserInfoState.ktapp/src/main/java/com/byeboo/app/presentation/auth/userinfo/UserInfoViewModel.ktapp/src/main/java/com/byeboo/app/presentation/home/HomeScreen.ktapp/src/main/java/com/byeboo/app/presentation/home/HomeUiState.ktapp/src/main/java/com/byeboo/app/presentation/home/HomeViewModel.ktapp/src/main/java/com/byeboo/app/presentation/home/homeamulet/HomeAmuletScreen.ktapp/src/main/java/com/byeboo/app/presentation/home/homeamulet/HomeAmuletState.ktapp/src/main/java/com/byeboo/app/presentation/home/homeamulet/HomeAmuletViewModel.ktapp/src/main/java/com/byeboo/app/presentation/main/MainNavHost.ktapp/src/main/java/com/byeboo/app/presentation/main/MainNavigator.ktapp/src/main/java/com/byeboo/app/presentation/main/MainScreen.ktapp/src/main/java/com/byeboo/app/presentation/mypage/MyPageScreen.ktapp/src/main/java/com/byeboo/app/presentation/mypage/MyPageState.ktapp/src/main/java/com/byeboo/app/presentation/mypage/MypageViewModel.ktapp/src/main/java/com/byeboo/app/presentation/mypage/blockedusers/BlockedUsersScreen.ktapp/src/main/java/com/byeboo/app/presentation/mypage/blockedusers/BlockedUsersState.ktapp/src/main/java/com/byeboo/app/presentation/mypage/editprofile/EditProfileScreen.ktapp/src/main/java/com/byeboo/app/presentation/mypage/editprofile/EditProfileState.ktapp/src/main/java/com/byeboo/app/presentation/mypage/editprofile/EditProfileViewModel.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/OffboardingJourneyState.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/OffboardingJourneyViewModel.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingcompletedguide/OffboardingCompletedGuideScreen.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingcompletedguide/OffboardingCompletedGuideState.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingcompletedguide/OffboardingCompletedGuideViewModel.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingcompletedjourney/OffboardingCompletedJourneyScreen.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingquestcompleted/OffboardingQuestCompletedScreen.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingquestcompleted/OffboardingQuestCompletedState.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingquestcompleted/OffboardingQuestCompletedViewModel.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingquestreview/OffboardingQuestReviewScreen.ktapp/src/main/java/com/byeboo/app/presentation/offboarding/offboardingquestreview/OffboardingQuestReviewState.ktapp/src/main/java/com/byeboo/app/presentation/quest/QuestScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/QuestViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/behavior/QuestBehaviorCompleteScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/behavior/QuestBehaviorCompleteState.ktapp/src/main/java/com/byeboo/app/presentation/quest/behavior/QuestBehaviorCompleteViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/behavior/QuestBehaviorState.ktapp/src/main/java/com/byeboo/app/presentation/quest/behavior/QuestBehaviorViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/behavior/QuestBehaviorWritingScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/component/bottomsheet/MoreOptionsBottomSheet.ktapp/src/main/java/com/byeboo/app/presentation/quest/component/card/CommonAnswerItem.ktapp/src/main/java/com/byeboo/app/presentation/quest/component/card/MyAnswerItem.ktapp/src/main/java/com/byeboo/app/presentation/quest/component/type/OptionType.ktapp/src/main/java/com/byeboo/app/presentation/quest/model/QuestModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/model/QuestState.ktapp/src/main/java/com/byeboo/app/presentation/quest/navigation/QuestNavigation.ktapp/src/main/java/com/byeboo/app/presentation/quest/navigation/QuestRoute.ktapp/src/main/java/com/byeboo/app/presentation/quest/record/QuestRecordingCompleteScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/record/QuestRecordingCompleteState.ktapp/src/main/java/com/byeboo/app/presentation/quest/record/QuestRecordingCompleteViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/record/QuestRecordingScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/record/QuestRecordingState.ktapp/src/main/java/com/byeboo/app/presentation/quest/record/QuestRecordingViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerState.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerState.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/my/QuestReviewScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/my/QuestReviewState.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/my/QuestReviewViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/screen/CommonJourneyScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/start/QuestStartScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/start/QuestStartState.ktapp/src/main/java/com/byeboo/app/presentation/quest/start/QuestStartViewModel.ktapp/src/main/java/com/byeboo/app/presentation/quest/tip/QuestTipScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/tip/QuestTipState.ktapp/src/main/java/com/byeboo/app/presentation/quest/tip/QuestTipViewModel.ktapp/src/main/java/com/byeboo/app/presentation/splash/SplashScreen.ktapp/src/main/java/com/byeboo/app/presentation/splash/SplashState.ktapp/src/main/java/com/byeboo/app/presentation/splash/SplashViewModel.ktapp/src/main/res/drawable/ic_block.xmlapp/src/main/res/drawable/ic_overflow_menu.xmlapp/src/main/res/drawable/ic_report.xmlapp/src/main/res/drawable/ic_success.xmlapp/src/main/res/drawable/ic_trash.xml
.../main/java/com/byeboo/app/presentation/quest/component/bottomsheet/MoreOptionsBottomSheet.kt
Outdated
Show resolved
Hide resolved
| composable<QuestMyAnswersDetail> { | ||
| MyAnswerDetailRoute( | ||
| paddingValues = paddingValues, | ||
| ) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find MyAnswerDetailRoute implementation
fd -t f "MyAnswerDetailRoute" --type fRepository: 36-APPJAM-HEARTZ/ByeBoo-ANDROID
Length of output: 57
🏁 Script executed:
# Search for MyAnswerDetailRoute function/composable definition
rg -n "fun MyAnswerDetailRoute|@Composable.*MyAnswerDetailRoute" --type=kotlinRepository: 36-APPJAM-HEARTZ/ByeBoo-ANDROID
Length of output: 201
🏁 Script executed:
# Find MyAnswerViewModel file
fd -t f "*MyAnswerViewModel*" --type fRepository: 36-APPJAM-HEARTZ/ByeBoo-ANDROID
Length of output: 373
🏁 Script executed:
# Check MyAnswerViewModel constructor and SavedStateHandle usage
rg -n "class MyAnswerViewModel|SavedStateHandle|answerId" --type=kotlin -B 2 -A 5 | grep -A 20 "MyAnswerViewModel"Repository: 36-APPJAM-HEARTZ/ByeBoo-ANDROID
Length of output: 8822
🏁 Script executed:
# Read MyAnswerDetailRoute implementation
cat -n app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt | head -80Repository: 36-APPJAM-HEARTZ/ByeBoo-ANDROID
Length of output: 3779
🏁 Script executed:
# Read the full MyAnswerViewModel to see all details
cat -n app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerViewModel.ktRepository: 36-APPJAM-HEARTZ/ByeBoo-ANDROID
Length of output: 4635
🏁 Script executed:
# Search for QuestMyAnswersDetail route definition in QuestNavigation
rg -n "QuestMyAnswersDetail" app/src/main/java/com/byeboo/app/presentation/quest/navigation/QuestNavigation.kt -B 2 -A 2Repository: 36-APPJAM-HEARTZ/ByeBoo-ANDROID
Length of output: 346
MyAnswerDetailRoute이 QuestMyAnswersDetail 라우트로부터 answerId를 수신하지 않습니다.
네비게이션에서 QuestMyAnswersDetail(answerId)로 이동하지만, MyAnswerDetailRoute는 이 파라미터를 받지 않습니다. 현재 구현에서는 uiState.answers.first()를 사용하므로 항상 첫 번째 답변만 표시됩니다.
MyAnswerViewModel에서 SavedStateHandle을 주입받아 라우트 파라미터로부터 answerId를 추출하도록 수정해야 합니다:
class MyAnswerViewModel
`@Inject`
constructor(
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {
private val answerId: Long = savedStateHandle.toRoute<QuestMyAnswersDetail>().answerId
// ... answerId를 사용하여 해당 답변 조회
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/navigation/QuestNavigation.kt`
around lines 133 - 137, MyAnswerDetailRoute is not receiving the answerId from
the QuestMyAnswersDetail nav route, so the UI always shows the first answer;
update the navigation composable to pass the route args into the route and
change MyAnswerViewModel to read the answerId from SavedStateHandle (use
savedStateHandle.toRoute<QuestMyAnswersDetail>().answerId) and use that id to
load the specific answer; target symbols: composable<QuestMyAnswersDetail>,
MyAnswerDetailRoute, MyAnswerViewModel, SavedStateHandle, toRoute, answerId.
app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt
Outdated
Show resolved
Hide resolved
| modifier: Modifier = Modifier, | ||
| ) { | ||
| val scrollState = rememberScrollState() | ||
| val answerState = uiState.answers.first() |
There was a problem hiding this comment.
uiState.answers.first()는 빈 리스트에서 NoSuchElementException을 발생시킵니다.
answers 리스트가 비어있을 경우 앱이 크래시됩니다. 안전한 접근 방식을 사용하거나 빈 상태를 처리해야 합니다.
🐛 수정 제안
`@Composable`
private fun MyAnswerDetailScreen(
uiState: MyAnswerState,
paddingValues: PaddingValues,
onClickMoreOptions: () -> Unit,
onDismissBottomSheet: () -> Unit,
onOptionClick: (OptionType) -> Unit,
modifier: Modifier = Modifier,
) {
val scrollState = rememberScrollState()
- val answerState = uiState.answers.first()
+ val answerState = uiState.answers.firstOrNull() ?: return📝 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 answerState = uiState.answers.first() | |
| `@Composable` | |
| private fun MyAnswerDetailScreen( | |
| uiState: MyAnswerState, | |
| paddingValues: PaddingValues, | |
| onClickMoreOptions: () -> Unit, | |
| onDismissBottomSheet: () -> Unit, | |
| onOptionClick: (OptionType) -> Unit, | |
| modifier: Modifier = Modifier, | |
| ) { | |
| val scrollState = rememberScrollState() | |
| val answerState = uiState.answers.firstOrNull() ?: return |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt`
at line 64, The current code uses uiState.answers.first() which throws
NoSuchElementException for empty lists; change that to a safe access (e.g., use
firstOrNull() or getOrNull(0)) and handle the null case rather than letting it
crash — update the val answerState assignment in MyAnswerDetailScreen to use
uiState.answers.firstOrNull() (or uiState.answers.getOrNull(0)) and then either
early-return, show an empty/error UI, or provide a fallback value so downstream
code using answerState is not executed with a missing item.
...c/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt
Outdated
Show resolved
Hide resolved
| Text( | ||
| text = | ||
| buildAnnotatedString { | ||
| append("하츠핑하츠님의") | ||
| append("\n") | ||
| append("공통퀘스트 답변이에요") | ||
| }, | ||
| color = ByeBooTheme.colors.gray50, | ||
| style = ByeBooTheme.typography.head2, | ||
| modifier = Modifier.padding(vertical = screenHeightDp(10.dp)), | ||
| ) |
There was a problem hiding this comment.
닉네임이 하드코딩되어 있습니다.
"하츠핑하츠님의"가 하드코딩되어 있습니다. 실제 사용자 닉네임은 uiState에서 가져오거나 ViewModel을 통해 주입받아야 합니다.
🔧 수정 제안
Text(
text =
buildAnnotatedString {
- append("하츠핑하츠님의")
+ append("${uiState.nickname}님의")
append("\n")
append("공통퀘스트 답변이에요")
},🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerScreen.kt`
around lines 96 - 106, The Text composable in MyAnswerScreen currently hardcodes
the nickname string ("하츠핑하츠님의") inside the buildAnnotatedString; replace that
hardcoded text by injecting the real user nickname from the screen state (e.g.,
use uiState.nickname or a value exposed by the ViewModel) when building the
string in the Text composable (the buildAnnotatedString block used for the
header), ensuring you handle null/empty nickname with a sensible fallback.
app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt
Outdated
Show resolved
Hide resolved
|
|
||
| @Composable | ||
| private fun MyAnswerDetailTopBar( | ||
| onClickMoreOptions: () -> Unit, |
There was a problem hiding this comment.
이 탑 바를 공통 컴포넌트로 빼는건 별로일까요?
...c/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt
Outdated
Show resolved
Hide resolved
| modifier = modifier, | ||
| ) | ||
|
|
||
| QuestTitle( |
There was a problem hiding this comment.
공통퀘스트는 피그마상 타이틀이 조금 다른데 같은데 확인 부탁 드립니다!
There was a problem hiding this comment.
이 부분 아직 이전 pr 병합을 못해서 일단 이렇게 썼습니다!
추후에 풀 받아온 후 수정하겠습니다!
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
app/src/main/java/com/byeboo/app/presentation/quest/review/common/component/AnswerDetailTopBar.kt (1)
19-23: 뒤로가기 콜백 파라미터 누락현재
onClickMoreOptions만 파라미터로 받고 있지만, 뒤로가기 아이콘도 클릭 가능한 상태입니다(Line 36-38). 재사용성과 완성도를 위해onClickBack콜백도 추가하는 것이 좋습니다.♻️ 제안: onClickBack 파라미터 추가
`@Composable` fun AnswerDetailTopBar( + onClickBack: () -> Unit, onClickMoreOptions: () -> Unit, modifier: Modifier = Modifier, ) {그리고 Line 36-38의
noRippleClickable에 적용:modifier = Modifier.noRippleClickable( - // Todo: 뒤로가기 + onClick = onClickBack, ),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/main/java/com/byeboo/app/presentation/quest/review/common/component/AnswerDetailTopBar.kt` around lines 19 - 23, Add a missing back-click callback to the AnswerDetailTopBar composable by introducing an onClickBack: () -> Unit parameter (with a sensible default if desired) alongside the existing onClickMoreOptions; then update the back icon's noRippleClickable invocation (the click handler around the Back icon in AnswerDetailTopBar) to call onClickBack instead of being hardcoded/absent so back presses are handled by the caller.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt`:
- Around line 82-85: CommonAnswerScreen currently forwards its incoming modifier
to AnswerDetailTopBar even though that modifier is already applied to the parent
Column (see Column in CommonAnswerScreen); change the call to AnswerDetailTopBar
to pass a fresh/empty Modifier (or omit the modifier argument if optional)
instead of the external modifier to avoid double-applying the same modifier;
update the invocation of AnswerDetailTopBar in CommonAnswerScreen and ensure any
local styling needed by AnswerDetailTopBar is provided via a dedicated internal
modifier rather than the external parameter.
- Line 94: Spacer에 Modifier.padding(bottom = ...)를 사용하면 의도한 수직 간격이 적용되지 않으므로, 해당
Spacer 호출(함수/파일의 Spacer(...) 사용 부분)에서 Modifier.padding을 제거하고 대신
Modifier.height(screenHeightDp(10.dp))로 크기를 지정해 수직 여백을 명시적으로 적용하도록 변경하세요; 즉 현재의
Spacer(modifier = Modifier.padding(bottom = screenHeightDp(10.dp)))를
Spacer(modifier = Modifier.height(screenHeightDp(10.dp)))로 바꾸면 됩니다.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/component/AnswerDetailTopBar.kt`:
- Around line 31-38: Two Icon composables currently set contentDescription =
null (e.g., the Icon using ImageVector.vectorResource(id = R.drawable.ic_left)
with Modifier.noRippleClickable) which prevents screen readers from conveying
the button purpose; update both Icon usages (the left/back Icon and the other
Icon in the 43-52 range) to provide meaningful, localized contentDescription
strings (use string resources like R.string.back or R.string.edit/action_name)
instead of null, and only keep null if the icon is purely decorative; ensure the
descriptions match the button action invoked by the surrounding clickable
(Modifier.noRippleClickable) so accessibility tools read the correct intent.
---
Nitpick comments:
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/component/AnswerDetailTopBar.kt`:
- Around line 19-23: Add a missing back-click callback to the AnswerDetailTopBar
composable by introducing an onClickBack: () -> Unit parameter (with a sensible
default if desired) alongside the existing onClickMoreOptions; then update the
back icon's noRippleClickable invocation (the click handler around the Back icon
in AnswerDetailTopBar) to call onClickBack instead of being hardcoded/absent so
back presses are handled by the caller.
ℹ️ Review info
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/src/main/java/com/byeboo/app/presentation/quest/component/bottomsheet/MoreOptionsBottomSheet.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/component/AnswerDetailTopBar.ktapp/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt
🚧 Files skipped from review as they are similar to previous changes (2)
- app/src/main/java/com/byeboo/app/presentation/quest/review/common/personal/MyAnswerDetailScreen.kt
- app/src/main/java/com/byeboo/app/presentation/quest/component/bottomsheet/MoreOptionsBottomSheet.kt
| AnswerDetailTopBar( | ||
| onClickMoreOptions = onClickMoreOptions, | ||
| modifier = modifier, | ||
| ) |
There was a problem hiding this comment.
외부 modifier를 내부 컴포넌트에 전달
CommonAnswerScreen의 modifier 파라미터를 AnswerDetailTopBar에 다시 전달하고 있습니다. 이 modifier는 이미 Line 72의 Column에 적용되어 있으므로, AnswerDetailTopBar에는 빈 Modifier 또는 별도의 modifier를 사용해야 합니다.
🐛 수정 제안
AnswerDetailTopBar(
onClickMoreOptions = onClickMoreOptions,
- modifier = modifier,
+ modifier = Modifier,
)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt`
around lines 82 - 85, CommonAnswerScreen currently forwards its incoming
modifier to AnswerDetailTopBar even though that modifier is already applied to
the parent Column (see Column in CommonAnswerScreen); change the call to
AnswerDetailTopBar to pass a fresh/empty Modifier (or omit the modifier argument
if optional) instead of the external modifier to avoid double-applying the same
modifier; update the invocation of AnswerDetailTopBar in CommonAnswerScreen and
ensure any local styling needed by AnswerDetailTopBar is provided via a
dedicated internal modifier rather than the external parameter.
| questQuestion = "그 사람이 싫어하기에 내가 포기해야만 했던 일은 무엇일까?", | ||
| ) | ||
|
|
||
| Spacer(modifier = Modifier.padding(bottom = screenHeightDp(10.dp))) |
There was a problem hiding this comment.
Spacer에 padding 대신 height 사용 권장
Spacer의 크기를 지정할 때 Modifier.padding(bottom = ...)은 의도한 대로 동작하지 않습니다. 수직 간격을 주려면 Modifier.height()를 사용하세요.
🐛 수정 제안
- Spacer(modifier = Modifier.padding(bottom = screenHeightDp(10.dp)))
+ Spacer(modifier = Modifier.height(screenHeightDp(10.dp)))📝 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.
| Spacer(modifier = Modifier.padding(bottom = screenHeightDp(10.dp))) | |
| Spacer(modifier = Modifier.height(screenHeightDp(10.dp))) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/all/CommonAnswerScreen.kt`
at line 94, Spacer에 Modifier.padding(bottom = ...)를 사용하면 의도한 수직 간격이 적용되지 않으므로,
해당 Spacer 호출(함수/파일의 Spacer(...) 사용 부분)에서 Modifier.padding을 제거하고 대신
Modifier.height(screenHeightDp(10.dp))로 크기를 지정해 수직 여백을 명시적으로 적용하도록 변경하세요; 즉 현재의
Spacer(modifier = Modifier.padding(bottom = screenHeightDp(10.dp)))를
Spacer(modifier = Modifier.height(screenHeightDp(10.dp)))로 바꾸면 됩니다.
| Icon( | ||
| imageVector = ImageVector.vectorResource(id = R.drawable.ic_left), | ||
| contentDescription = null, | ||
| tint = ByeBooTheme.colors.gray50, | ||
| modifier = | ||
| Modifier.noRippleClickable( | ||
| // Todo: 뒤로가기 | ||
| ), |
There was a problem hiding this comment.
접근성: contentDescription 누락
두 아이콘 모두 contentDescription = null로 설정되어 있어 스크린 리더 사용자가 버튼의 용도를 알 수 없습니다.
♿ 제안: contentDescription 추가
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_left),
- contentDescription = null,
+ contentDescription = "뒤로 가기",
tint = ByeBooTheme.colors.gray50, Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_overflow_menu),
- contentDescription = null,
+ contentDescription = "더보기 옵션",
tint = ByeBooTheme.colors.white,Also applies to: 43-52
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@app/src/main/java/com/byeboo/app/presentation/quest/review/common/component/AnswerDetailTopBar.kt`
around lines 31 - 38, Two Icon composables currently set contentDescription =
null (e.g., the Icon using ImageVector.vectorResource(id = R.drawable.ic_left)
with Modifier.noRippleClickable) which prevents screen readers from conveying
the button purpose; update both Icon usages (the left/back Icon and the other
Icon in the 43-52 range) to provide meaningful, localized contentDescription
strings (use string resources like R.string.back or R.string.edit/action_name)
instead of null, and only keep null if the icon is purely decorative; ensure the
descriptions match the button action invoked by the surrounding clickable
(Modifier.noRippleClickable) so accessibility tools read the correct intent.
Related issue 🛠
Work Description 📝
Screenshot 📸
_.mp4
_.mp4
Uncompleted Tasks 😅
PR Point 📌
더미데이터 넣어서 UI만 확인할 수 있게끔 했습니다!
모달 추가는 코리 반영하면서 넣어놓을게요!
이번 PR 실수가 많을 거 같아요 열.코로 많은 지적해주세요 ㅎㅎ
이번 스프린트에서 스낵바 아이콘이 하나 더 추가됐는데요!
아이콘 타입 이넘 활용해서 넣고, 스낵바 사용하는 모든 화면 수정했습니다 !
확인 부탁드려요! 🙇♀️
자잘한 수정 때문에 건든 파일이 많네요.. 여기 부분 위주로 봐주시면 돼요!
트러블 슈팅 💥
Summary by CodeRabbit
릴리즈 노트
새 기능
UI/UX 개선